1 /*
2 * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13
14 /* We need to use some STORE deprecated APIs */
15 #define OPENSSL_SUPPRESS_DEPRECATED
16
17 #include "internal/e_os.h"
18
19 #include <openssl/crypto.h>
20 #include <openssl/err.h>
21 #include <openssl/trace.h>
22 #include <openssl/core_names.h>
23 #include <openssl/provider.h>
24 #include <openssl/param_build.h>
25 #include <openssl/store.h>
26 #include "internal/thread_once.h"
27 #include "internal/cryptlib.h"
28 #include "internal/provider.h"
29 #include "internal/bio.h"
30 #include "crypto/store.h"
31 #include "store_local.h"
32
33 static int ossl_store_close_it(OSSL_STORE_CTX *ctx);
34
loader_set_params(OSSL_STORE_LOADER * loader,OSSL_STORE_LOADER_CTX * loader_ctx,const OSSL_PARAM params[],const char * propq)35 static int loader_set_params(OSSL_STORE_LOADER *loader,
36 OSSL_STORE_LOADER_CTX *loader_ctx,
37 const OSSL_PARAM params[], const char *propq)
38 {
39 if (params != NULL) {
40 if (!loader->p_set_ctx_params(loader_ctx, params))
41 return 0;
42 }
43
44 if (propq != NULL) {
45 OSSL_PARAM propp[2];
46
47 if (OSSL_PARAM_locate_const(params,
48 OSSL_STORE_PARAM_PROPERTIES)
49 != NULL)
50 /* use the propq from params */
51 return 1;
52
53 propp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
54 (char *)propq, 0);
55 propp[1] = OSSL_PARAM_construct_end();
56
57 if (!loader->p_set_ctx_params(loader_ctx, propp))
58 return 0;
59 }
60 return 1;
61 }
62
63 OSSL_STORE_CTX *
OSSL_STORE_open_ex(const char * uri,OSSL_LIB_CTX * libctx,const char * propq,const UI_METHOD * ui_method,void * ui_data,const OSSL_PARAM params[],OSSL_STORE_post_process_info_fn post_process,void * post_process_data)64 OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
65 const UI_METHOD *ui_method, void *ui_data,
66 const OSSL_PARAM params[],
67 OSSL_STORE_post_process_info_fn post_process,
68 void *post_process_data)
69 {
70 struct ossl_passphrase_data_st pwdata = { 0 };
71 const OSSL_STORE_LOADER *loader = NULL;
72 OSSL_STORE_LOADER *fetched_loader = NULL;
73 OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
74 OSSL_STORE_CTX *ctx = NULL;
75 char *propq_copy = NULL;
76 int no_loader_found = 1;
77 char scheme_copy[256], *p, *schemes[2], *scheme = NULL;
78 size_t schemes_n = 0;
79 size_t i;
80
81 if (uri == NULL) {
82 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
83 return 0;
84 }
85
86 /*
87 * Put the file scheme first. If the uri does represent an existing file,
88 * possible device name and all, then it should be loaded. Only a failed
89 * attempt at loading a local file should have us try something else.
90 */
91 schemes[schemes_n++] = "file";
92
93 /*
94 * Now, check if we have something that looks like a scheme, and add it
95 * as a second scheme. However, also check if there's an authority start
96 * (://), because that will invalidate the previous file scheme. Also,
97 * check that this isn't actually the file scheme, as there's no point
98 * going through that one twice!
99 */
100 OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
101 if ((p = strchr(scheme_copy, ':')) != NULL) {
102 *p++ = '\0';
103 if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) {
104 if (HAS_PREFIX(p, "//"))
105 schemes_n--; /* Invalidate the file scheme */
106 schemes[schemes_n++] = scheme_copy;
107 }
108 }
109
110 ERR_set_mark();
111
112 if (ui_method != NULL
113 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
114 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
115 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
116 goto err;
117 }
118
119 /*
120 * Try each scheme until we find one that could open the URI.
121 *
122 * For each scheme, we look for the engine implementation first, and
123 * failing that, we then try to fetch a provided implementation.
124 * This is consistent with how we handle legacy / engine implementations
125 * elsewhere.
126 */
127 for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
128 scheme = schemes[i];
129 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
130 #ifndef OPENSSL_NO_DEPRECATED_3_0
131 ERR_set_mark();
132 if ((loader = ossl_store_get0_loader_int(scheme)) != NULL) {
133 ERR_clear_last_mark();
134 no_loader_found = 0;
135 if (loader->open_ex != NULL)
136 loader_ctx = loader->open_ex(loader, uri, libctx, propq,
137 ui_method, ui_data);
138 else
139 loader_ctx = loader->open(loader, uri, ui_method, ui_data);
140 } else {
141 ERR_pop_to_mark();
142 }
143 #endif
144 if (loader == NULL
145 && (fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
146 const OSSL_PROVIDER *provider = OSSL_STORE_LOADER_get0_provider(fetched_loader);
147 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
148
149 no_loader_found = 0;
150 if (fetched_loader->p_open_ex != NULL) {
151 loader_ctx = fetched_loader->p_open_ex(provctx, uri, params,
152 ossl_pw_passphrase_callback_dec,
153 &pwdata);
154 } else {
155 if (fetched_loader->p_open != NULL && (loader_ctx = fetched_loader->p_open(provctx, uri)) != NULL && !loader_set_params(fetched_loader, loader_ctx, params, propq)) {
156 (void)fetched_loader->p_close(loader_ctx);
157 loader_ctx = NULL;
158 }
159 }
160 if (loader_ctx == NULL) {
161 OSSL_STORE_LOADER_free(fetched_loader);
162 fetched_loader = NULL;
163 }
164 loader = fetched_loader;
165
166 /* Clear any internally cached passphrase */
167 (void)ossl_pw_clear_passphrase_cache(&pwdata);
168 }
169 }
170
171 if (no_loader_found)
172 /*
173 * It's assumed that ossl_store_get0_loader_int() and
174 * OSSL_STORE_LOADER_fetch() report their own errors
175 */
176 goto err;
177
178 OSSL_TRACE1(STORE, "Found loader for scheme %s\n", scheme);
179
180 if (loader_ctx == NULL)
181 /*
182 * It's assumed that the loader's open() method reports its own
183 * errors
184 */
185 goto err;
186
187 OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx);
188
189 if ((propq != NULL && (propq_copy = OPENSSL_strdup(propq)) == NULL)
190 || (ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
191 goto err;
192
193 ctx->properties = propq_copy;
194 ctx->fetched_loader = fetched_loader;
195 ctx->loader = loader;
196 ctx->loader_ctx = loader_ctx;
197 ctx->post_process = post_process;
198 ctx->post_process_data = post_process_data;
199 ctx->pwdata = pwdata;
200
201 /*
202 * If the attempt to open with the 'file' scheme loader failed and the
203 * other scheme loader succeeded, the failure to open with the 'file'
204 * scheme loader leaves an error on the error stack. Let's remove it.
205 */
206 ERR_pop_to_mark();
207
208 return ctx;
209
210 err:
211 ERR_clear_last_mark();
212 if (loader_ctx != NULL) {
213 /*
214 * Temporary structure so OSSL_STORE_close() can work even when
215 * |ctx| couldn't be allocated properly
216 */
217 OSSL_STORE_CTX tmpctx = {
218 NULL,
219 };
220
221 tmpctx.fetched_loader = fetched_loader;
222 tmpctx.loader = loader;
223 tmpctx.loader_ctx = loader_ctx;
224
225 /*
226 * We ignore a returned error because we will return NULL anyway in
227 * this case, so if something goes wrong when closing, that'll simply
228 * just add another entry on the error stack.
229 */
230 (void)ossl_store_close_it(&tmpctx);
231 }
232 /* Coverity false positive, the reference counting is confusing it */
233 /* coverity[pass_freed_arg] */
234 OSSL_STORE_LOADER_free(fetched_loader);
235 OPENSSL_free(propq_copy);
236 OPENSSL_free(ctx);
237 return NULL;
238 }
239
OSSL_STORE_open(const char * uri,const UI_METHOD * ui_method,void * ui_data,OSSL_STORE_post_process_info_fn post_process,void * post_process_data)240 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
241 const UI_METHOD *ui_method, void *ui_data,
242 OSSL_STORE_post_process_info_fn post_process,
243 void *post_process_data)
244 {
245 return OSSL_STORE_open_ex(uri, NULL, NULL, ui_method, ui_data, NULL,
246 post_process, post_process_data);
247 }
248
249 #ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_STORE_ctrl(OSSL_STORE_CTX * ctx,int cmd,...)250 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
251 {
252 va_list args;
253 int ret;
254
255 va_start(args, cmd);
256 ret = OSSL_STORE_vctrl(ctx, cmd, args);
257 va_end(args);
258
259 return ret;
260 }
261
OSSL_STORE_vctrl(OSSL_STORE_CTX * ctx,int cmd,va_list args)262 int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args)
263 {
264 if (ctx->fetched_loader != NULL) {
265 if (ctx->fetched_loader->p_set_ctx_params != NULL) {
266 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
267
268 switch (cmd) {
269 case OSSL_STORE_C_USE_SECMEM: {
270 int on = *(va_arg(args, int *));
271
272 params[0] = OSSL_PARAM_construct_int("use_secmem", &on);
273 } break;
274 default:
275 break;
276 }
277
278 return ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
279 params);
280 }
281 } else if (ctx->loader->ctrl != NULL) {
282 return ctx->loader->ctrl(ctx->loader_ctx, cmd, args);
283 }
284
285 /*
286 * If the fetched loader doesn't have a set_ctx_params or a ctrl, it's as
287 * if there was one that ignored our params, which usually returns 1.
288 */
289 return 1;
290 }
291 #endif
292
OSSL_STORE_expect(OSSL_STORE_CTX * ctx,int expected_type)293 int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type)
294 {
295 int ret = 1;
296
297 if (ctx == NULL
298 || expected_type < 0 || expected_type > OSSL_STORE_INFO_CRL) {
299 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
300 return 0;
301 }
302 if (ctx->loading) {
303 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
304 return 0;
305 }
306
307 ctx->expected_type = expected_type;
308 if (ctx->fetched_loader != NULL
309 && ctx->fetched_loader->p_set_ctx_params != NULL) {
310 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
311
312 params[0] = OSSL_PARAM_construct_int(OSSL_STORE_PARAM_EXPECT, &expected_type);
313 ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx, params);
314 }
315 #ifndef OPENSSL_NO_DEPRECATED_3_0
316 if (ctx->fetched_loader == NULL
317 && ctx->loader->expect != NULL) {
318 ret = ctx->loader->expect(ctx->loader_ctx, expected_type);
319 }
320 #endif
321 return ret;
322 }
323
OSSL_STORE_find(OSSL_STORE_CTX * ctx,const OSSL_STORE_SEARCH * search)324 int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search)
325 {
326 int ret = 1;
327
328 if (ctx->loading) {
329 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
330 return 0;
331 }
332 if (search == NULL) {
333 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
334 return 0;
335 }
336
337 if (ctx->fetched_loader != NULL) {
338 OSSL_PARAM_BLD *bld;
339 OSSL_PARAM *params;
340 /* OSSL_STORE_SEARCH_BY_NAME, OSSL_STORE_SEARCH_BY_ISSUER_SERIAL*/
341 void *name_der = NULL;
342 int name_der_sz;
343 /* OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */
344 BIGNUM *number = NULL;
345
346 if (ctx->fetched_loader->p_set_ctx_params == NULL) {
347 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
348 return 0;
349 }
350
351 if ((bld = OSSL_PARAM_BLD_new()) == NULL) {
352 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
353 return 0;
354 }
355
356 ret = 0; /* Assume the worst */
357
358 switch (search->search_type) {
359 case OSSL_STORE_SEARCH_BY_NAME:
360 if ((name_der_sz = i2d_X509_NAME(search->name,
361 (unsigned char **)&name_der))
362 > 0
363 && OSSL_PARAM_BLD_push_octet_string(bld,
364 OSSL_STORE_PARAM_SUBJECT,
365 name_der, name_der_sz))
366 ret = 1;
367 break;
368 case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
369 if ((name_der_sz = i2d_X509_NAME(search->name,
370 (unsigned char **)&name_der))
371 > 0
372 && (number = ASN1_INTEGER_to_BN(search->serial, NULL)) != NULL
373 && OSSL_PARAM_BLD_push_octet_string(bld,
374 OSSL_STORE_PARAM_ISSUER,
375 name_der, name_der_sz)
376 && OSSL_PARAM_BLD_push_BN(bld, OSSL_STORE_PARAM_SERIAL,
377 number))
378 ret = 1;
379 break;
380 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
381 if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_DIGEST,
382 EVP_MD_get0_name(search->digest),
383 0)
384 && OSSL_PARAM_BLD_push_octet_string(bld,
385 OSSL_STORE_PARAM_FINGERPRINT,
386 search->string,
387 search->stringlength))
388 ret = 1;
389 break;
390 case OSSL_STORE_SEARCH_BY_ALIAS:
391 if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_ALIAS,
392 (char *)search->string,
393 search->stringlength))
394 ret = 1;
395 break;
396 }
397 if (ret) {
398 params = OSSL_PARAM_BLD_to_param(bld);
399 ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
400 params);
401 OSSL_PARAM_free(params);
402 }
403 OSSL_PARAM_BLD_free(bld);
404 OPENSSL_free(name_der);
405 BN_free(number);
406 } else {
407 #ifndef OPENSSL_NO_DEPRECATED_3_0
408 /* legacy loader section */
409 if (ctx->loader->find == NULL) {
410 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
411 return 0;
412 }
413 ret = ctx->loader->find(ctx->loader_ctx, search);
414 #endif
415 }
416
417 return ret;
418 }
419
OSSL_STORE_load(OSSL_STORE_CTX * ctx)420 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
421 {
422 OSSL_STORE_INFO *v = NULL;
423
424 ctx->loading = 1;
425 again:
426 if (OSSL_STORE_eof(ctx))
427 return NULL;
428
429 if (ctx->loader != NULL)
430 OSSL_TRACE(STORE, "Loading next object\n");
431
432 if (ctx->cached_info != NULL) {
433 v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
434 } else {
435 if (ctx->fetched_loader != NULL) {
436 struct ossl_load_result_data_st load_data;
437
438 load_data.v = NULL;
439 load_data.ctx = ctx;
440 ctx->error_flag = 0;
441
442 if (!ctx->fetched_loader->p_load(ctx->loader_ctx,
443 ossl_store_handle_load_result,
444 &load_data,
445 ossl_pw_passphrase_callback_dec,
446 &ctx->pwdata)) {
447 ctx->error_flag = 1;
448 return NULL;
449 }
450 v = load_data.v;
451 }
452 #ifndef OPENSSL_NO_DEPRECATED_3_0
453 if (ctx->fetched_loader == NULL)
454 v = ctx->loader->load(ctx->loader_ctx,
455 ctx->pwdata._.ui_method.ui_method,
456 ctx->pwdata._.ui_method.ui_method_data);
457 #endif
458 }
459
460 if (ctx->post_process != NULL && v != NULL) {
461 v = ctx->post_process(v, ctx->post_process_data);
462
463 /*
464 * By returning NULL, the callback decides that this object should
465 * be ignored.
466 */
467 if (v == NULL)
468 goto again;
469 }
470
471 /* Clear any internally cached passphrase */
472 (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
473
474 if (v != NULL && ctx->expected_type != 0) {
475 int returned_type = OSSL_STORE_INFO_get_type(v);
476
477 if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) {
478 if (ctx->expected_type != returned_type) {
479 OSSL_STORE_INFO_free(v);
480 goto again;
481 }
482 }
483 }
484
485 if (v != NULL)
486 OSSL_TRACE1(STORE, "Got a %s\n",
487 OSSL_STORE_INFO_type_string(OSSL_STORE_INFO_get_type(v)));
488
489 return v;
490 }
491
OSSL_STORE_delete(const char * uri,OSSL_LIB_CTX * libctx,const char * propq,const UI_METHOD * ui_method,void * ui_data,const OSSL_PARAM params[])492 int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
493 const UI_METHOD *ui_method, void *ui_data,
494 const OSSL_PARAM params[])
495 {
496 OSSL_STORE_LOADER *fetched_loader = NULL;
497 char scheme[256], *p;
498 int res = 0;
499 struct ossl_passphrase_data_st pwdata = { 0 };
500
501 OPENSSL_strlcpy(scheme, uri, sizeof(scheme));
502 if ((p = strchr(scheme, ':')) != NULL)
503 *p++ = '\0';
504 else /* We don't work without explicit scheme */
505 return 0;
506
507 if (ui_method != NULL
508 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
509 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
510 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
511 return 0;
512 }
513
514 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
515 fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq);
516
517 if (fetched_loader != NULL && fetched_loader->p_delete != NULL) {
518 const OSSL_PROVIDER *provider = OSSL_STORE_LOADER_get0_provider(fetched_loader);
519 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
520
521 /*
522 * It's assumed that the loader's delete() method reports its own
523 * errors
524 */
525 OSSL_TRACE1(STORE, "Performing URI delete %s\n", uri);
526 res = fetched_loader->p_delete(provctx, uri, params,
527 ossl_pw_passphrase_callback_dec,
528 &pwdata);
529 }
530 /* Clear any internally cached passphrase */
531 (void)ossl_pw_clear_passphrase_cache(&pwdata);
532
533 OSSL_STORE_LOADER_free(fetched_loader);
534
535 return res;
536 }
537
OSSL_STORE_error(OSSL_STORE_CTX * ctx)538 int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
539 {
540 int ret = 1;
541
542 if (ctx->fetched_loader != NULL)
543 ret = ctx->error_flag;
544 #ifndef OPENSSL_NO_DEPRECATED_3_0
545 if (ctx->fetched_loader == NULL)
546 ret = ctx->loader->error(ctx->loader_ctx);
547 #endif
548 return ret;
549 }
550
OSSL_STORE_eof(OSSL_STORE_CTX * ctx)551 int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
552 {
553 int ret = 0;
554
555 if (ctx->cached_info != NULL
556 && sk_OSSL_STORE_INFO_num(ctx->cached_info) == 0) {
557 sk_OSSL_STORE_INFO_free(ctx->cached_info);
558 ctx->cached_info = NULL;
559 }
560
561 if (ctx->cached_info == NULL) {
562 ret = 1;
563 if (ctx->fetched_loader != NULL)
564 ret = ctx->loader->p_eof(ctx->loader_ctx);
565 #ifndef OPENSSL_NO_DEPRECATED_3_0
566 if (ctx->fetched_loader == NULL)
567 ret = ctx->loader->eof(ctx->loader_ctx);
568 #endif
569 }
570 return ret != 0;
571 }
572
ossl_store_close_it(OSSL_STORE_CTX * ctx)573 static int ossl_store_close_it(OSSL_STORE_CTX *ctx)
574 {
575 int ret = 0;
576
577 if (ctx == NULL)
578 return 1;
579 OSSL_TRACE1(STORE, "Closing %p\n", (void *)ctx->loader_ctx);
580
581 if (ctx->fetched_loader != NULL)
582 ret = ctx->loader->p_close(ctx->loader_ctx);
583 #ifndef OPENSSL_NO_DEPRECATED_3_0
584 if (ctx->fetched_loader == NULL)
585 ret = ctx->loader->closefn(ctx->loader_ctx);
586 #endif
587
588 sk_OSSL_STORE_INFO_pop_free(ctx->cached_info, OSSL_STORE_INFO_free);
589 OSSL_STORE_LOADER_free(ctx->fetched_loader);
590 OPENSSL_free(ctx->properties);
591 ossl_pw_clear_passphrase_data(&ctx->pwdata);
592 return ret;
593 }
594
OSSL_STORE_close(OSSL_STORE_CTX * ctx)595 int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
596 {
597 int ret = ossl_store_close_it(ctx);
598
599 OPENSSL_free(ctx);
600 return ret;
601 }
602
603 /*
604 * Functions to generate OSSL_STORE_INFOs, one function for each type we
605 * support having in them as well as a generic constructor.
606 *
607 * In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
608 * and will therefore be freed when the OSSL_STORE_INFO is freed.
609 */
OSSL_STORE_INFO_new(int type,void * data)610 OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data)
611 {
612 OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
613
614 if (info == NULL)
615 return NULL;
616
617 info->type = type;
618 info->_.data = data;
619 return info;
620 }
621
OSSL_STORE_INFO_new_NAME(char * name)622 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
623 {
624 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_NAME, NULL);
625
626 if (info == NULL) {
627 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
628 return NULL;
629 }
630
631 info->_.name.name = name;
632 info->_.name.desc = NULL;
633
634 return info;
635 }
636
OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO * info,char * desc)637 int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
638 {
639 if (info->type != OSSL_STORE_INFO_NAME) {
640 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
641 return 0;
642 }
643
644 info->_.name.desc = desc;
645
646 return 1;
647 }
OSSL_STORE_INFO_new_PARAMS(EVP_PKEY * params)648 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
649 {
650 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PARAMS, params);
651
652 if (info == NULL)
653 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
654 return info;
655 }
656
OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY * pkey)657 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
658 {
659 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PUBKEY, pkey);
660
661 if (info == NULL)
662 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
663 return info;
664 }
665
OSSL_STORE_INFO_new_PKEY(EVP_PKEY * pkey)666 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
667 {
668 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PKEY, pkey);
669
670 if (info == NULL)
671 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
672 return info;
673 }
674
OSSL_STORE_INFO_new_CERT(X509 * x509)675 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
676 {
677 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CERT, x509);
678
679 if (info == NULL)
680 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
681 return info;
682 }
683
OSSL_STORE_INFO_new_CRL(X509_CRL * crl)684 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
685 {
686 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CRL, crl);
687
688 if (info == NULL)
689 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
690 return info;
691 }
692
693 /*
694 * Functions to try to extract data from an OSSL_STORE_INFO.
695 */
OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO * info)696 int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
697 {
698 return info->type;
699 }
700
OSSL_STORE_INFO_get0_data(int type,const OSSL_STORE_INFO * info)701 void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info)
702 {
703 if (info->type == type)
704 return info->_.data;
705 return NULL;
706 }
707
OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO * info)708 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
709 {
710 if (info->type == OSSL_STORE_INFO_NAME)
711 return info->_.name.name;
712 return NULL;
713 }
714
OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO * info)715 char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
716 {
717 if (info->type == OSSL_STORE_INFO_NAME)
718 return OPENSSL_strdup(info->_.name.name);
719 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
720 return NULL;
721 }
722
OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO * info)723 const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info)
724 {
725 if (info->type == OSSL_STORE_INFO_NAME)
726 return info->_.name.desc;
727 return NULL;
728 }
729
OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO * info)730 char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
731 {
732 if (info->type == OSSL_STORE_INFO_NAME)
733 return OPENSSL_strdup(info->_.name.desc ? info->_.name.desc : "");
734 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
735 return NULL;
736 }
737
OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO * info)738 EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info)
739 {
740 if (info->type == OSSL_STORE_INFO_PARAMS)
741 return info->_.params;
742 return NULL;
743 }
744
OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO * info)745 EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
746 {
747 if (info->type == OSSL_STORE_INFO_PARAMS) {
748 if (!EVP_PKEY_up_ref(info->_.params))
749 return NULL;
750 return info->_.params;
751 }
752 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS);
753 return NULL;
754 }
755
OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO * info)756 EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info)
757 {
758 if (info->type == OSSL_STORE_INFO_PUBKEY)
759 return info->_.pubkey;
760 return NULL;
761 }
762
OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO * info)763 EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info)
764 {
765 if (info->type == OSSL_STORE_INFO_PUBKEY) {
766 if (!EVP_PKEY_up_ref(info->_.pubkey))
767 return NULL;
768 return info->_.pubkey;
769 }
770 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY);
771 return NULL;
772 }
773
OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO * info)774 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
775 {
776 if (info->type == OSSL_STORE_INFO_PKEY)
777 return info->_.pkey;
778 return NULL;
779 }
780
OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO * info)781 EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
782 {
783 if (info->type == OSSL_STORE_INFO_PKEY) {
784 if (!EVP_PKEY_up_ref(info->_.pkey))
785 return NULL;
786 return info->_.pkey;
787 }
788 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY);
789 return NULL;
790 }
791
OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO * info)792 X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info)
793 {
794 if (info->type == OSSL_STORE_INFO_CERT)
795 return info->_.x509;
796 return NULL;
797 }
798
OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO * info)799 X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
800 {
801 if (info->type == OSSL_STORE_INFO_CERT) {
802 if (!X509_up_ref(info->_.x509))
803 return NULL;
804 return info->_.x509;
805 }
806 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE);
807 return NULL;
808 }
809
OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO * info)810 X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info)
811 {
812 if (info->type == OSSL_STORE_INFO_CRL)
813 return info->_.crl;
814 return NULL;
815 }
816
OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO * info)817 X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
818 {
819 if (info->type == OSSL_STORE_INFO_CRL) {
820 if (!X509_CRL_up_ref(info->_.crl))
821 return NULL;
822 return info->_.crl;
823 }
824 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL);
825 return NULL;
826 }
827
828 /*
829 * Free the OSSL_STORE_INFO
830 */
OSSL_STORE_INFO_free(OSSL_STORE_INFO * info)831 void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
832 {
833 if (info != NULL) {
834 switch (info->type) {
835 case OSSL_STORE_INFO_NAME:
836 OPENSSL_free(info->_.name.name);
837 OPENSSL_free(info->_.name.desc);
838 break;
839 case OSSL_STORE_INFO_PARAMS:
840 EVP_PKEY_free(info->_.params);
841 break;
842 case OSSL_STORE_INFO_PUBKEY:
843 EVP_PKEY_free(info->_.pubkey);
844 break;
845 case OSSL_STORE_INFO_PKEY:
846 EVP_PKEY_free(info->_.pkey);
847 break;
848 case OSSL_STORE_INFO_CERT:
849 X509_free(info->_.x509);
850 break;
851 case OSSL_STORE_INFO_CRL:
852 X509_CRL_free(info->_.crl);
853 break;
854 }
855 OPENSSL_free(info);
856 }
857 }
858
OSSL_STORE_supports_search(OSSL_STORE_CTX * ctx,int search_type)859 int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type)
860 {
861 int ret = 0;
862
863 if (ctx->fetched_loader != NULL) {
864 void *provctx = ossl_provider_ctx(OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader));
865 const OSSL_PARAM *params;
866 const OSSL_PARAM *p_subject = NULL;
867 const OSSL_PARAM *p_issuer = NULL;
868 const OSSL_PARAM *p_serial = NULL;
869 const OSSL_PARAM *p_fingerprint = NULL;
870 const OSSL_PARAM *p_alias = NULL;
871
872 if (ctx->fetched_loader->p_settable_ctx_params == NULL)
873 return 0;
874
875 params = ctx->fetched_loader->p_settable_ctx_params(provctx);
876 p_subject = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
877 p_issuer = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ISSUER);
878 p_serial = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SERIAL);
879 p_fingerprint = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_FINGERPRINT);
880 p_alias = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ALIAS);
881
882 switch (search_type) {
883 case OSSL_STORE_SEARCH_BY_NAME:
884 ret = (p_subject != NULL);
885 break;
886 case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
887 ret = (p_issuer != NULL && p_serial != NULL);
888 break;
889 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
890 ret = (p_fingerprint != NULL);
891 break;
892 case OSSL_STORE_SEARCH_BY_ALIAS:
893 ret = (p_alias != NULL);
894 break;
895 }
896 }
897 #ifndef OPENSSL_NO_DEPRECATED_3_0
898 if (ctx->fetched_loader == NULL) {
899 OSSL_STORE_SEARCH tmp_search;
900
901 if (ctx->loader->find == NULL)
902 return 0;
903 tmp_search.search_type = search_type;
904 ret = ctx->loader->find(NULL, &tmp_search);
905 }
906 #endif
907 return ret;
908 }
909
910 /* Search term constructors */
OSSL_STORE_SEARCH_by_name(X509_NAME * name)911 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
912 {
913 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
914
915 if (search == NULL)
916 return NULL;
917
918 search->search_type = OSSL_STORE_SEARCH_BY_NAME;
919 search->name = name;
920 return search;
921 }
922
OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME * name,const ASN1_INTEGER * serial)923 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
924 const ASN1_INTEGER *serial)
925 {
926 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
927
928 if (search == NULL)
929 return NULL;
930
931 search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
932 search->name = name;
933 search->serial = serial;
934 return search;
935 }
936
OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD * digest,const unsigned char * bytes,size_t len)937 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
938 const unsigned char
939 *bytes,
940 size_t len)
941 {
942 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
943 int md_size;
944
945 if (search == NULL)
946 return NULL;
947
948 md_size = EVP_MD_get_size(digest);
949 if (md_size <= 0) {
950 OPENSSL_free(search);
951 return NULL;
952 }
953
954 if (digest != NULL && len != (size_t)md_size) {
955 ERR_raise_data(ERR_LIB_OSSL_STORE,
956 OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST,
957 "%s size is %d, fingerprint size is %zu",
958 EVP_MD_get0_name(digest), md_size, len);
959 OPENSSL_free(search);
960 return NULL;
961 }
962
963 search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
964 search->digest = digest;
965 search->string = bytes;
966 search->stringlength = len;
967 return search;
968 }
969
OSSL_STORE_SEARCH_by_alias(const char * alias)970 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias)
971 {
972 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
973
974 if (search == NULL)
975 return NULL;
976
977 search->search_type = OSSL_STORE_SEARCH_BY_ALIAS;
978 search->string = (const unsigned char *)alias;
979 search->stringlength = strlen(alias);
980 return search;
981 }
982
983 /* Search term destructor */
OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH * search)984 void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search)
985 {
986 OPENSSL_free(search);
987 }
988
989 /* Search term accessors */
OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH * criterion)990 int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion)
991 {
992 return criterion->search_type;
993 }
994
OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH * criterion)995 X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion)
996 {
997 return criterion->name;
998 }
999
OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH * criterion)1000 const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
1001 *criterion)
1002 {
1003 return criterion->serial;
1004 }
1005
OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH * criterion,size_t * length)1006 const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
1007 *criterion,
1008 size_t *length)
1009 {
1010 *length = criterion->stringlength;
1011 return criterion->string;
1012 }
1013
OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH * criterion)1014 const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion)
1015 {
1016 return (const char *)criterion->string;
1017 }
1018
OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH * criterion)1019 const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
1020 {
1021 return criterion->digest;
1022 }
1023
OSSL_STORE_attach(BIO * bp,const char * scheme,OSSL_LIB_CTX * libctx,const char * propq,const UI_METHOD * ui_method,void * ui_data,const OSSL_PARAM params[],OSSL_STORE_post_process_info_fn post_process,void * post_process_data)1024 OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
1025 OSSL_LIB_CTX *libctx, const char *propq,
1026 const UI_METHOD *ui_method, void *ui_data,
1027 const OSSL_PARAM params[],
1028 OSSL_STORE_post_process_info_fn post_process,
1029 void *post_process_data)
1030 {
1031 const OSSL_STORE_LOADER *loader = NULL;
1032 OSSL_STORE_LOADER *fetched_loader = NULL;
1033 OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
1034 OSSL_STORE_CTX *ctx = NULL;
1035
1036 if (scheme == NULL)
1037 scheme = "file";
1038
1039 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
1040 ERR_set_mark();
1041 #ifndef OPENSSL_NO_DEPRECATED_3_0
1042 if ((loader = ossl_store_get0_loader_int(scheme)) != NULL)
1043 loader_ctx = loader->attach(loader, bp, libctx, propq,
1044 ui_method, ui_data);
1045 #endif
1046 if (loader == NULL
1047 && (fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
1048 const OSSL_PROVIDER *provider = OSSL_STORE_LOADER_get0_provider(fetched_loader);
1049 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
1050 OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp);
1051
1052 if (cbio == NULL
1053 || fetched_loader->p_attach == NULL
1054 || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) {
1055 OSSL_STORE_LOADER_free(fetched_loader);
1056 fetched_loader = NULL;
1057 } else if (!loader_set_params(fetched_loader, loader_ctx,
1058 params, propq)) {
1059 (void)fetched_loader->p_close(loader_ctx);
1060 OSSL_STORE_LOADER_free(fetched_loader);
1061 fetched_loader = NULL;
1062 }
1063 loader = fetched_loader;
1064 ossl_core_bio_free(cbio);
1065 }
1066
1067 if (loader_ctx == NULL) {
1068 ERR_clear_last_mark();
1069 return NULL;
1070 }
1071
1072 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
1073 ERR_clear_last_mark();
1074 return NULL;
1075 }
1076
1077 if (ui_method != NULL
1078 && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
1079 ERR_clear_last_mark();
1080 OPENSSL_free(ctx);
1081 return NULL;
1082 }
1083
1084 ctx->fetched_loader = fetched_loader;
1085 ctx->loader = loader;
1086 ctx->loader_ctx = loader_ctx;
1087 ctx->post_process = post_process;
1088 ctx->post_process_data = post_process_data;
1089
1090 /*
1091 * ossl_store_get0_loader_int will raise an error if the loader for
1092 * the scheme cannot be retrieved. But if a loader was successfully
1093 * fetched then we remove this error from the error stack.
1094 */
1095 ERR_pop_to_mark();
1096
1097 return ctx;
1098 }
1099