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) != NULL)
49 /* use the propq from params */
50 return 1;
51
52 propp[0] = OSSL_PARAM_construct_utf8_string(OSSL_STORE_PARAM_PROPERTIES,
53 (char *)propq, 0);
54 propp[1] = OSSL_PARAM_construct_end();
55
56 if (!loader->p_set_ctx_params(loader_ctx, propp))
57 return 0;
58 }
59 return 1;
60 }
61
62 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)63 OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
64 const UI_METHOD *ui_method, void *ui_data,
65 const OSSL_PARAM params[],
66 OSSL_STORE_post_process_info_fn post_process,
67 void *post_process_data)
68 {
69 struct ossl_passphrase_data_st pwdata = { 0 };
70 const OSSL_STORE_LOADER *loader = NULL;
71 OSSL_STORE_LOADER *fetched_loader = NULL;
72 OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
73 OSSL_STORE_CTX *ctx = NULL;
74 char *propq_copy = NULL;
75 int no_loader_found = 1;
76 char scheme_copy[256], *p, *schemes[2], *scheme = NULL;
77 size_t schemes_n = 0;
78 size_t i;
79
80 /*
81 * Put the file scheme first. If the uri does represent an existing file,
82 * possible device name and all, then it should be loaded. Only a failed
83 * attempt at loading a local file should have us try something else.
84 */
85 schemes[schemes_n++] = "file";
86
87 /*
88 * Now, check if we have something that looks like a scheme, and add it
89 * as a second scheme. However, also check if there's an authority start
90 * (://), because that will invalidate the previous file scheme. Also,
91 * check that this isn't actually the file scheme, as there's no point
92 * going through that one twice!
93 */
94 OPENSSL_strlcpy(scheme_copy, uri, sizeof(scheme_copy));
95 if ((p = strchr(scheme_copy, ':')) != NULL) {
96 *p++ = '\0';
97 if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) {
98 if (HAS_PREFIX(p, "//"))
99 schemes_n--; /* Invalidate the file scheme */
100 schemes[schemes_n++] = scheme_copy;
101 }
102 }
103
104 ERR_set_mark();
105
106 if (ui_method != NULL
107 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
108 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
109 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
110 goto err;
111 }
112
113 /*
114 * Try each scheme until we find one that could open the URI.
115 *
116 * For each scheme, we look for the engine implementation first, and
117 * failing that, we then try to fetch a provided implementation.
118 * This is consistent with how we handle legacy / engine implementations
119 * elsewhere.
120 */
121 for (i = 0; loader_ctx == NULL && i < schemes_n; i++) {
122 scheme = schemes[i];
123 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
124 #ifndef OPENSSL_NO_DEPRECATED_3_0
125 ERR_set_mark();
126 if ((loader = ossl_store_get0_loader_int(scheme)) != NULL) {
127 ERR_clear_last_mark();
128 no_loader_found = 0;
129 if (loader->open_ex != NULL)
130 loader_ctx = loader->open_ex(loader, uri, libctx, propq,
131 ui_method, ui_data);
132 else
133 loader_ctx = loader->open(loader, uri, ui_method, ui_data);
134 } else {
135 ERR_pop_to_mark();
136 }
137 #endif
138 if (loader == NULL
139 && (fetched_loader =
140 OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
141 const OSSL_PROVIDER *provider =
142 OSSL_STORE_LOADER_get0_provider(fetched_loader);
143 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
144
145 no_loader_found = 0;
146 if (fetched_loader->p_open_ex != NULL) {
147 loader_ctx =
148 fetched_loader->p_open_ex(provctx, uri, params,
149 ossl_pw_passphrase_callback_dec,
150 &pwdata);
151 } else {
152 if (fetched_loader->p_open != NULL &&
153 (loader_ctx = fetched_loader->p_open(provctx, uri)) != NULL &&
154 !loader_set_params(fetched_loader, loader_ctx,
155 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 = { NULL, };
218
219 tmpctx.fetched_loader = fetched_loader;
220 tmpctx.loader = loader;
221 tmpctx.loader_ctx = loader_ctx;
222
223 /*
224 * We ignore a returned error because we will return NULL anyway in
225 * this case, so if something goes wrong when closing, that'll simply
226 * just add another entry on the error stack.
227 */
228 (void)ossl_store_close_it(&tmpctx);
229 }
230 /* Coverity false positive, the reference counting is confusing it */
231 /* coverity[pass_freed_arg] */
232 OSSL_STORE_LOADER_free(fetched_loader);
233 OPENSSL_free(propq_copy);
234 OPENSSL_free(ctx);
235 return NULL;
236 }
237
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)238 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
239 const UI_METHOD *ui_method, void *ui_data,
240 OSSL_STORE_post_process_info_fn post_process,
241 void *post_process_data)
242 {
243 return OSSL_STORE_open_ex(uri, NULL, NULL, ui_method, ui_data, NULL,
244 post_process, post_process_data);
245 }
246
247 #ifndef OPENSSL_NO_DEPRECATED_3_0
OSSL_STORE_ctrl(OSSL_STORE_CTX * ctx,int cmd,...)248 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
249 {
250 va_list args;
251 int ret;
252
253 va_start(args, cmd);
254 ret = OSSL_STORE_vctrl(ctx, cmd, args);
255 va_end(args);
256
257 return ret;
258 }
259
OSSL_STORE_vctrl(OSSL_STORE_CTX * ctx,int cmd,va_list args)260 int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, va_list args)
261 {
262 if (ctx->fetched_loader != NULL) {
263 if (ctx->fetched_loader->p_set_ctx_params != NULL) {
264 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
265
266 switch (cmd) {
267 case OSSL_STORE_C_USE_SECMEM:
268 {
269 int on = *(va_arg(args, int *));
270
271 params[0] = OSSL_PARAM_construct_int("use_secmem", &on);
272 }
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] =
313 OSSL_PARAM_construct_int(OSSL_STORE_PARAM_EXPECT, &expected_type);
314 ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx, params);
315 }
316 #ifndef OPENSSL_NO_DEPRECATED_3_0
317 if (ctx->fetched_loader == NULL
318 && ctx->loader->expect != NULL) {
319 ret = ctx->loader->expect(ctx->loader_ctx, expected_type);
320 }
321 #endif
322 return ret;
323 }
324
OSSL_STORE_find(OSSL_STORE_CTX * ctx,const OSSL_STORE_SEARCH * search)325 int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search)
326 {
327 int ret = 1;
328
329 if (ctx->loading) {
330 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADING_STARTED);
331 return 0;
332 }
333 if (search == NULL) {
334 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
335 return 0;
336 }
337
338 if (ctx->fetched_loader != NULL) {
339 OSSL_PARAM_BLD *bld;
340 OSSL_PARAM *params;
341 /* OSSL_STORE_SEARCH_BY_NAME, OSSL_STORE_SEARCH_BY_ISSUER_SERIAL*/
342 void *name_der = NULL;
343 int name_der_sz;
344 /* OSSL_STORE_SEARCH_BY_ISSUER_SERIAL */
345 BIGNUM *number = NULL;
346
347 if (ctx->fetched_loader->p_set_ctx_params == NULL) {
348 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
349 return 0;
350 }
351
352 if ((bld = OSSL_PARAM_BLD_new()) == NULL) {
353 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
354 return 0;
355 }
356
357 ret = 0; /* Assume the worst */
358
359 switch (search->search_type) {
360 case OSSL_STORE_SEARCH_BY_NAME:
361 if ((name_der_sz = i2d_X509_NAME(search->name,
362 (unsigned char **)&name_der)) > 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)) > 0
371 && (number = ASN1_INTEGER_to_BN(search->serial, NULL)) != NULL
372 && OSSL_PARAM_BLD_push_octet_string(bld,
373 OSSL_STORE_PARAM_ISSUER,
374 name_der, name_der_sz)
375 && OSSL_PARAM_BLD_push_BN(bld, OSSL_STORE_PARAM_SERIAL,
376 number))
377 ret = 1;
378 break;
379 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
380 if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_DIGEST,
381 EVP_MD_get0_name(search->digest),
382 0)
383 && OSSL_PARAM_BLD_push_octet_string(bld,
384 OSSL_STORE_PARAM_FINGERPRINT,
385 search->string,
386 search->stringlength))
387 ret = 1;
388 break;
389 case OSSL_STORE_SEARCH_BY_ALIAS:
390 if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_STORE_PARAM_ALIAS,
391 (char *)search->string,
392 search->stringlength))
393 ret = 1;
394 break;
395 }
396 if (ret) {
397 params = OSSL_PARAM_BLD_to_param(bld);
398 ret = ctx->fetched_loader->p_set_ctx_params(ctx->loader_ctx,
399 params);
400 OSSL_PARAM_free(params);
401 }
402 OSSL_PARAM_BLD_free(bld);
403 OPENSSL_free(name_der);
404 BN_free(number);
405 } else {
406 #ifndef OPENSSL_NO_DEPRECATED_3_0
407 /* legacy loader section */
408 if (ctx->loader->find == NULL) {
409 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_UNSUPPORTED_OPERATION);
410 return 0;
411 }
412 ret = ctx->loader->find(ctx->loader_ctx, search);
413 #endif
414 }
415
416 return ret;
417 }
418
OSSL_STORE_load(OSSL_STORE_CTX * ctx)419 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
420 {
421 OSSL_STORE_INFO *v = NULL;
422
423 ctx->loading = 1;
424 again:
425 if (OSSL_STORE_eof(ctx))
426 return NULL;
427
428 if (ctx->loader != NULL)
429 OSSL_TRACE(STORE, "Loading next object\n");
430
431 if (ctx->cached_info != NULL) {
432 v = sk_OSSL_STORE_INFO_shift(ctx->cached_info);
433 } else {
434 if (ctx->fetched_loader != NULL) {
435 struct ossl_load_result_data_st load_data;
436
437 load_data.v = NULL;
438 load_data.ctx = ctx;
439 ctx->error_flag = 0;
440
441 if (!ctx->fetched_loader->p_load(ctx->loader_ctx,
442 ossl_store_handle_load_result,
443 &load_data,
444 ossl_pw_passphrase_callback_dec,
445 &ctx->pwdata)) {
446 ctx->error_flag = 1;
447 return NULL;
448 }
449 v = load_data.v;
450 }
451 #ifndef OPENSSL_NO_DEPRECATED_3_0
452 if (ctx->fetched_loader == NULL)
453 v = ctx->loader->load(ctx->loader_ctx,
454 ctx->pwdata._.ui_method.ui_method,
455 ctx->pwdata._.ui_method.ui_method_data);
456 #endif
457 }
458
459 if (ctx->post_process != NULL && v != NULL) {
460 v = ctx->post_process(v, ctx->post_process_data);
461
462 /*
463 * By returning NULL, the callback decides that this object should
464 * be ignored.
465 */
466 if (v == NULL)
467 goto again;
468 }
469
470 /* Clear any internally cached passphrase */
471 (void)ossl_pw_clear_passphrase_cache(&ctx->pwdata);
472
473 if (v != NULL && ctx->expected_type != 0) {
474 int returned_type = OSSL_STORE_INFO_get_type(v);
475
476 if (returned_type != OSSL_STORE_INFO_NAME && returned_type != 0) {
477 if (ctx->expected_type != returned_type) {
478 OSSL_STORE_INFO_free(v);
479 goto again;
480 }
481 }
482 }
483
484 if (v != NULL)
485 OSSL_TRACE1(STORE, "Got a %s\n",
486 OSSL_STORE_INFO_type_string(OSSL_STORE_INFO_get_type(v)));
487
488 return v;
489 }
490
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[])491 int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq,
492 const UI_METHOD *ui_method, void *ui_data,
493 const OSSL_PARAM params[])
494 {
495 OSSL_STORE_LOADER *fetched_loader = NULL;
496 char scheme[256], *p;
497 int res = 0;
498 struct ossl_passphrase_data_st pwdata = {0};
499
500 OPENSSL_strlcpy(scheme, uri, sizeof(scheme));
501 if ((p = strchr(scheme, ':')) != NULL)
502 *p++ = '\0';
503 else /* We don't work without explicit scheme */
504 return 0;
505
506 if (ui_method != NULL
507 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
508 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
509 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
510 return 0;
511 }
512
513 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
514 fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq);
515
516 if (fetched_loader != NULL && fetched_loader->p_delete != NULL) {
517 const OSSL_PROVIDER *provider =
518 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 =
865 ossl_provider_ctx(OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader));
866 const OSSL_PARAM *params;
867 const OSSL_PARAM *p_subject = NULL;
868 const OSSL_PARAM *p_issuer = NULL;
869 const OSSL_PARAM *p_serial = NULL;
870 const OSSL_PARAM *p_fingerprint = NULL;
871 const OSSL_PARAM *p_alias = NULL;
872
873 if (ctx->fetched_loader->p_settable_ctx_params == NULL)
874 return 0;
875
876 params = ctx->fetched_loader->p_settable_ctx_params(provctx);
877 p_subject = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
878 p_issuer = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ISSUER);
879 p_serial = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SERIAL);
880 p_fingerprint =
881 OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_FINGERPRINT);
882 p_alias = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ALIAS);
883
884 switch (search_type) {
885 case OSSL_STORE_SEARCH_BY_NAME:
886 ret = (p_subject != NULL);
887 break;
888 case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
889 ret = (p_issuer != NULL && p_serial != NULL);
890 break;
891 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
892 ret = (p_fingerprint != NULL);
893 break;
894 case OSSL_STORE_SEARCH_BY_ALIAS:
895 ret = (p_alias != NULL);
896 break;
897 }
898 }
899 #ifndef OPENSSL_NO_DEPRECATED_3_0
900 if (ctx->fetched_loader == NULL) {
901 OSSL_STORE_SEARCH tmp_search;
902
903 if (ctx->loader->find == NULL)
904 return 0;
905 tmp_search.search_type = search_type;
906 ret = ctx->loader->find(NULL, &tmp_search);
907 }
908 #endif
909 return ret;
910 }
911
912 /* Search term constructors */
OSSL_STORE_SEARCH_by_name(X509_NAME * name)913 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
914 {
915 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
916
917 if (search == NULL)
918 return NULL;
919
920 search->search_type = OSSL_STORE_SEARCH_BY_NAME;
921 search->name = name;
922 return search;
923 }
924
OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME * name,const ASN1_INTEGER * serial)925 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
926 const ASN1_INTEGER *serial)
927 {
928 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
929
930 if (search == NULL)
931 return NULL;
932
933 search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
934 search->name = name;
935 search->serial = serial;
936 return search;
937 }
938
OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD * digest,const unsigned char * bytes,size_t len)939 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
940 const unsigned char
941 *bytes, size_t len)
942 {
943 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
944 int md_size;
945
946 if (search == NULL)
947 return NULL;
948
949 md_size = EVP_MD_get_size(digest);
950 if (md_size <= 0) {
951 OPENSSL_free(search);
952 return NULL;
953 }
954
955 if (digest != NULL && len != (size_t)md_size) {
956 ERR_raise_data(ERR_LIB_OSSL_STORE,
957 OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST,
958 "%s size is %d, fingerprint size is %zu",
959 EVP_MD_get0_name(digest), md_size, len);
960 OPENSSL_free(search);
961 return NULL;
962 }
963
964 search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
965 search->digest = digest;
966 search->string = bytes;
967 search->stringlength = len;
968 return search;
969 }
970
OSSL_STORE_SEARCH_by_alias(const char * alias)971 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias)
972 {
973 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
974
975 if (search == NULL)
976 return NULL;
977
978 search->search_type = OSSL_STORE_SEARCH_BY_ALIAS;
979 search->string = (const unsigned char *)alias;
980 search->stringlength = strlen(alias);
981 return search;
982 }
983
984 /* Search term destructor */
OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH * search)985 void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search)
986 {
987 OPENSSL_free(search);
988 }
989
990 /* Search term accessors */
OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH * criterion)991 int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion)
992 {
993 return criterion->search_type;
994 }
995
OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH * criterion)996 X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion)
997 {
998 return criterion->name;
999 }
1000
OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH * criterion)1001 const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
1002 *criterion)
1003 {
1004 return criterion->serial;
1005 }
1006
OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH * criterion,size_t * length)1007 const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
1008 *criterion, 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 =
1048 OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
1049 const OSSL_PROVIDER *provider =
1050 OSSL_STORE_LOADER_get0_provider(fetched_loader);
1051 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
1052 OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp);
1053
1054 if (cbio == NULL
1055 || fetched_loader->p_attach == NULL
1056 || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) {
1057 OSSL_STORE_LOADER_free(fetched_loader);
1058 fetched_loader = NULL;
1059 } else if (!loader_set_params(fetched_loader, loader_ctx,
1060 params, propq)) {
1061 (void)fetched_loader->p_close(loader_ctx);
1062 OSSL_STORE_LOADER_free(fetched_loader);
1063 fetched_loader = NULL;
1064 }
1065 loader = fetched_loader;
1066 ossl_core_bio_free(cbio);
1067 }
1068
1069 if (loader_ctx == NULL) {
1070 ERR_clear_last_mark();
1071 return NULL;
1072 }
1073
1074 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
1075 ERR_clear_last_mark();
1076 return NULL;
1077 }
1078
1079 if (ui_method != NULL
1080 && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
1081 ERR_clear_last_mark();
1082 OPENSSL_free(ctx);
1083 return NULL;
1084 }
1085
1086 ctx->fetched_loader = fetched_loader;
1087 ctx->loader = loader;
1088 ctx->loader_ctx = loader_ctx;
1089 ctx->post_process = post_process;
1090 ctx->post_process_data = post_process_data;
1091
1092 /*
1093 * ossl_store_get0_loader_int will raise an error if the loader for
1094 * the scheme cannot be retrieved. But if a loader was successfully
1095 * fetched then we remove this error from the error stack.
1096 */
1097 ERR_pop_to_mark();
1098
1099 return ctx;
1100 }
1101