1 /*
2 * Copyright 2016-2026 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 if (uri == NULL) {
502 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER);
503 return 0;
504 }
505 OPENSSL_strlcpy(scheme, uri, sizeof(scheme));
506 if ((p = strchr(scheme, ':')) != NULL)
507 *p++ = '\0';
508 else /* We don't work without explicit scheme */
509 return 0;
510
511 if (ui_method != NULL
512 && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data)
513 || !ossl_pw_enable_passphrase_caching(&pwdata))) {
514 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB);
515 return 0;
516 }
517
518 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
519 fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq);
520
521 if (fetched_loader != NULL && fetched_loader->p_delete != NULL) {
522 const OSSL_PROVIDER *provider = OSSL_STORE_LOADER_get0_provider(fetched_loader);
523 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
524
525 /*
526 * It's assumed that the loader's delete() method reports its own
527 * errors
528 */
529 OSSL_TRACE1(STORE, "Performing URI delete %s\n", uri);
530 res = fetched_loader->p_delete(provctx, uri, params,
531 ossl_pw_passphrase_callback_dec,
532 &pwdata);
533 }
534 /* Clear any internally cached passphrase */
535 (void)ossl_pw_clear_passphrase_cache(&pwdata);
536
537 OSSL_STORE_LOADER_free(fetched_loader);
538
539 return res;
540 }
541
OSSL_STORE_error(OSSL_STORE_CTX * ctx)542 int OSSL_STORE_error(OSSL_STORE_CTX *ctx)
543 {
544 int ret = 1;
545
546 if (ctx->fetched_loader != NULL)
547 ret = ctx->error_flag;
548 #ifndef OPENSSL_NO_DEPRECATED_3_0
549 if (ctx->fetched_loader == NULL)
550 ret = ctx->loader->error(ctx->loader_ctx);
551 #endif
552 return ret;
553 }
554
OSSL_STORE_eof(OSSL_STORE_CTX * ctx)555 int OSSL_STORE_eof(OSSL_STORE_CTX *ctx)
556 {
557 int ret = 0;
558
559 if (ctx->cached_info != NULL
560 && sk_OSSL_STORE_INFO_num(ctx->cached_info) == 0) {
561 sk_OSSL_STORE_INFO_free(ctx->cached_info);
562 ctx->cached_info = NULL;
563 }
564
565 if (ctx->cached_info == NULL) {
566 ret = 1;
567 if (ctx->fetched_loader != NULL)
568 ret = ctx->loader->p_eof(ctx->loader_ctx);
569 #ifndef OPENSSL_NO_DEPRECATED_3_0
570 if (ctx->fetched_loader == NULL)
571 ret = ctx->loader->eof(ctx->loader_ctx);
572 #endif
573 }
574 return ret != 0;
575 }
576
ossl_store_close_it(OSSL_STORE_CTX * ctx)577 static int ossl_store_close_it(OSSL_STORE_CTX *ctx)
578 {
579 int ret = 0;
580
581 if (ctx == NULL)
582 return 1;
583 OSSL_TRACE1(STORE, "Closing %p\n", (void *)ctx->loader_ctx);
584
585 if (ctx->fetched_loader != NULL)
586 ret = ctx->loader->p_close(ctx->loader_ctx);
587 #ifndef OPENSSL_NO_DEPRECATED_3_0
588 if (ctx->fetched_loader == NULL)
589 ret = ctx->loader->closefn(ctx->loader_ctx);
590 #endif
591
592 sk_OSSL_STORE_INFO_pop_free(ctx->cached_info, OSSL_STORE_INFO_free);
593 OSSL_STORE_LOADER_free(ctx->fetched_loader);
594 OPENSSL_free(ctx->properties);
595 ossl_pw_clear_passphrase_data(&ctx->pwdata);
596 return ret;
597 }
598
OSSL_STORE_close(OSSL_STORE_CTX * ctx)599 int OSSL_STORE_close(OSSL_STORE_CTX *ctx)
600 {
601 int ret = ossl_store_close_it(ctx);
602
603 OPENSSL_free(ctx);
604 return ret;
605 }
606
607 /*
608 * Functions to generate OSSL_STORE_INFOs, one function for each type we
609 * support having in them as well as a generic constructor.
610 *
611 * In all cases, ownership of the object is transferred to the OSSL_STORE_INFO
612 * and will therefore be freed when the OSSL_STORE_INFO is freed.
613 */
OSSL_STORE_INFO_new(int type,void * data)614 OSSL_STORE_INFO *OSSL_STORE_INFO_new(int type, void *data)
615 {
616 OSSL_STORE_INFO *info = OPENSSL_zalloc(sizeof(*info));
617
618 if (info == NULL)
619 return NULL;
620
621 info->type = type;
622 info->_.data = data;
623 return info;
624 }
625
OSSL_STORE_INFO_new_NAME(char * name)626 OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name)
627 {
628 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_NAME, NULL);
629
630 if (info == NULL) {
631 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
632 return NULL;
633 }
634
635 info->_.name.name = name;
636 info->_.name.desc = NULL;
637
638 return info;
639 }
640
OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO * info,char * desc)641 int OSSL_STORE_INFO_set0_NAME_description(OSSL_STORE_INFO *info, char *desc)
642 {
643 if (info->type != OSSL_STORE_INFO_NAME) {
644 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
645 return 0;
646 }
647
648 info->_.name.desc = desc;
649
650 return 1;
651 }
OSSL_STORE_INFO_new_PARAMS(EVP_PKEY * params)652 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params)
653 {
654 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PARAMS, params);
655
656 if (info == NULL)
657 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
658 return info;
659 }
660
OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY * pkey)661 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey)
662 {
663 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PUBKEY, pkey);
664
665 if (info == NULL)
666 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
667 return info;
668 }
669
OSSL_STORE_INFO_new_PKEY(EVP_PKEY * pkey)670 OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey)
671 {
672 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PKEY, pkey);
673
674 if (info == NULL)
675 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
676 return info;
677 }
678
OSSL_STORE_INFO_new_CERT(X509 * x509)679 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509)
680 {
681 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CERT, x509);
682
683 if (info == NULL)
684 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
685 return info;
686 }
687
OSSL_STORE_INFO_new_CRL(X509_CRL * crl)688 OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl)
689 {
690 OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CRL, crl);
691
692 if (info == NULL)
693 ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB);
694 return info;
695 }
696
697 /*
698 * Functions to try to extract data from an OSSL_STORE_INFO.
699 */
OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO * info)700 int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info)
701 {
702 return info->type;
703 }
704
OSSL_STORE_INFO_get0_data(int type,const OSSL_STORE_INFO * info)705 void *OSSL_STORE_INFO_get0_data(int type, const OSSL_STORE_INFO *info)
706 {
707 if (info->type == type)
708 return info->_.data;
709 return NULL;
710 }
711
OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO * info)712 const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info)
713 {
714 if (info->type == OSSL_STORE_INFO_NAME)
715 return info->_.name.name;
716 return NULL;
717 }
718
OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO * info)719 char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info)
720 {
721 if (info->type == OSSL_STORE_INFO_NAME)
722 return OPENSSL_strdup(info->_.name.name);
723 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
724 return NULL;
725 }
726
OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO * info)727 const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info)
728 {
729 if (info->type == OSSL_STORE_INFO_NAME)
730 return info->_.name.desc;
731 return NULL;
732 }
733
OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO * info)734 char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info)
735 {
736 if (info->type == OSSL_STORE_INFO_NAME)
737 return OPENSSL_strdup(info->_.name.desc ? info->_.name.desc : "");
738 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME);
739 return NULL;
740 }
741
OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO * info)742 EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info)
743 {
744 if (info->type == OSSL_STORE_INFO_PARAMS)
745 return info->_.params;
746 return NULL;
747 }
748
OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO * info)749 EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info)
750 {
751 if (info->type == OSSL_STORE_INFO_PARAMS) {
752 if (!EVP_PKEY_up_ref(info->_.params))
753 return NULL;
754 return info->_.params;
755 }
756 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS);
757 return NULL;
758 }
759
OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO * info)760 EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info)
761 {
762 if (info->type == OSSL_STORE_INFO_PUBKEY)
763 return info->_.pubkey;
764 return NULL;
765 }
766
OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO * info)767 EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info)
768 {
769 if (info->type == OSSL_STORE_INFO_PUBKEY) {
770 if (!EVP_PKEY_up_ref(info->_.pubkey))
771 return NULL;
772 return info->_.pubkey;
773 }
774 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY);
775 return NULL;
776 }
777
OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO * info)778 EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info)
779 {
780 if (info->type == OSSL_STORE_INFO_PKEY)
781 return info->_.pkey;
782 return NULL;
783 }
784
OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO * info)785 EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info)
786 {
787 if (info->type == OSSL_STORE_INFO_PKEY) {
788 if (!EVP_PKEY_up_ref(info->_.pkey))
789 return NULL;
790 return info->_.pkey;
791 }
792 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY);
793 return NULL;
794 }
795
OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO * info)796 X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info)
797 {
798 if (info->type == OSSL_STORE_INFO_CERT)
799 return info->_.x509;
800 return NULL;
801 }
802
OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO * info)803 X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info)
804 {
805 if (info->type == OSSL_STORE_INFO_CERT) {
806 if (!X509_up_ref(info->_.x509))
807 return NULL;
808 return info->_.x509;
809 }
810 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE);
811 return NULL;
812 }
813
OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO * info)814 X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info)
815 {
816 if (info->type == OSSL_STORE_INFO_CRL)
817 return info->_.crl;
818 return NULL;
819 }
820
OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO * info)821 X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info)
822 {
823 if (info->type == OSSL_STORE_INFO_CRL) {
824 if (!X509_CRL_up_ref(info->_.crl))
825 return NULL;
826 return info->_.crl;
827 }
828 ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL);
829 return NULL;
830 }
831
832 /*
833 * Free the OSSL_STORE_INFO
834 */
OSSL_STORE_INFO_free(OSSL_STORE_INFO * info)835 void OSSL_STORE_INFO_free(OSSL_STORE_INFO *info)
836 {
837 if (info != NULL) {
838 switch (info->type) {
839 case OSSL_STORE_INFO_NAME:
840 OPENSSL_free(info->_.name.name);
841 OPENSSL_free(info->_.name.desc);
842 break;
843 case OSSL_STORE_INFO_PARAMS:
844 EVP_PKEY_free(info->_.params);
845 break;
846 case OSSL_STORE_INFO_PUBKEY:
847 EVP_PKEY_free(info->_.pubkey);
848 break;
849 case OSSL_STORE_INFO_PKEY:
850 EVP_PKEY_free(info->_.pkey);
851 break;
852 case OSSL_STORE_INFO_CERT:
853 X509_free(info->_.x509);
854 break;
855 case OSSL_STORE_INFO_CRL:
856 X509_CRL_free(info->_.crl);
857 break;
858 }
859 OPENSSL_free(info);
860 }
861 }
862
OSSL_STORE_supports_search(OSSL_STORE_CTX * ctx,int search_type)863 int OSSL_STORE_supports_search(OSSL_STORE_CTX *ctx, int search_type)
864 {
865 int ret = 0;
866
867 if (ctx->fetched_loader != NULL) {
868 void *provctx = ossl_provider_ctx(OSSL_STORE_LOADER_get0_provider(ctx->fetched_loader));
869 const OSSL_PARAM *params;
870 const OSSL_PARAM *p_subject = NULL;
871 const OSSL_PARAM *p_issuer = NULL;
872 const OSSL_PARAM *p_serial = NULL;
873 const OSSL_PARAM *p_fingerprint = NULL;
874 const OSSL_PARAM *p_alias = NULL;
875
876 if (ctx->fetched_loader->p_settable_ctx_params == NULL)
877 return 0;
878
879 params = ctx->fetched_loader->p_settable_ctx_params(provctx);
880 p_subject = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SUBJECT);
881 p_issuer = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ISSUER);
882 p_serial = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_SERIAL);
883 p_fingerprint = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_FINGERPRINT);
884 p_alias = OSSL_PARAM_locate_const(params, OSSL_STORE_PARAM_ALIAS);
885
886 switch (search_type) {
887 case OSSL_STORE_SEARCH_BY_NAME:
888 ret = (p_subject != NULL);
889 break;
890 case OSSL_STORE_SEARCH_BY_ISSUER_SERIAL:
891 ret = (p_issuer != NULL && p_serial != NULL);
892 break;
893 case OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT:
894 ret = (p_fingerprint != NULL);
895 break;
896 case OSSL_STORE_SEARCH_BY_ALIAS:
897 ret = (p_alias != NULL);
898 break;
899 }
900 }
901 #ifndef OPENSSL_NO_DEPRECATED_3_0
902 if (ctx->fetched_loader == NULL) {
903 OSSL_STORE_SEARCH tmp_search;
904
905 if (ctx->loader->find == NULL)
906 return 0;
907 tmp_search.search_type = search_type;
908 ret = ctx->loader->find(NULL, &tmp_search);
909 }
910 #endif
911 return ret;
912 }
913
914 /* Search term constructors */
OSSL_STORE_SEARCH_by_name(X509_NAME * name)915 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name)
916 {
917 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
918
919 if (search == NULL)
920 return NULL;
921
922 search->search_type = OSSL_STORE_SEARCH_BY_NAME;
923 search->name = name;
924 return search;
925 }
926
OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME * name,const ASN1_INTEGER * serial)927 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name,
928 const ASN1_INTEGER *serial)
929 {
930 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
931
932 if (search == NULL)
933 return NULL;
934
935 search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL;
936 search->name = name;
937 search->serial = serial;
938 return search;
939 }
940
OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD * digest,const unsigned char * bytes,size_t len)941 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest,
942 const unsigned char
943 *bytes,
944 size_t len)
945 {
946 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
947 int md_size;
948
949 if (search == NULL)
950 return NULL;
951
952 md_size = EVP_MD_get_size(digest);
953 if (md_size <= 0) {
954 OPENSSL_free(search);
955 return NULL;
956 }
957
958 if (digest != NULL && len != (size_t)md_size) {
959 ERR_raise_data(ERR_LIB_OSSL_STORE,
960 OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST,
961 "%s size is %d, fingerprint size is %zu",
962 EVP_MD_get0_name(digest), md_size, len);
963 OPENSSL_free(search);
964 return NULL;
965 }
966
967 search->search_type = OSSL_STORE_SEARCH_BY_KEY_FINGERPRINT;
968 search->digest = digest;
969 search->string = bytes;
970 search->stringlength = len;
971 return search;
972 }
973
OSSL_STORE_SEARCH_by_alias(const char * alias)974 OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias)
975 {
976 OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search));
977
978 if (search == NULL)
979 return NULL;
980
981 search->search_type = OSSL_STORE_SEARCH_BY_ALIAS;
982 search->string = (const unsigned char *)alias;
983 search->stringlength = strlen(alias);
984 return search;
985 }
986
987 /* Search term destructor */
OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH * search)988 void OSSL_STORE_SEARCH_free(OSSL_STORE_SEARCH *search)
989 {
990 OPENSSL_free(search);
991 }
992
993 /* Search term accessors */
OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH * criterion)994 int OSSL_STORE_SEARCH_get_type(const OSSL_STORE_SEARCH *criterion)
995 {
996 return criterion->search_type;
997 }
998
OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH * criterion)999 X509_NAME *OSSL_STORE_SEARCH_get0_name(const OSSL_STORE_SEARCH *criterion)
1000 {
1001 return criterion->name;
1002 }
1003
OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH * criterion)1004 const ASN1_INTEGER *OSSL_STORE_SEARCH_get0_serial(const OSSL_STORE_SEARCH
1005 *criterion)
1006 {
1007 return criterion->serial;
1008 }
1009
OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH * criterion,size_t * length)1010 const unsigned char *OSSL_STORE_SEARCH_get0_bytes(const OSSL_STORE_SEARCH
1011 *criterion,
1012 size_t *length)
1013 {
1014 *length = criterion->stringlength;
1015 return criterion->string;
1016 }
1017
OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH * criterion)1018 const char *OSSL_STORE_SEARCH_get0_string(const OSSL_STORE_SEARCH *criterion)
1019 {
1020 return (const char *)criterion->string;
1021 }
1022
OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH * criterion)1023 const EVP_MD *OSSL_STORE_SEARCH_get0_digest(const OSSL_STORE_SEARCH *criterion)
1024 {
1025 return criterion->digest;
1026 }
1027
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)1028 OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
1029 OSSL_LIB_CTX *libctx, const char *propq,
1030 const UI_METHOD *ui_method, void *ui_data,
1031 const OSSL_PARAM params[],
1032 OSSL_STORE_post_process_info_fn post_process,
1033 void *post_process_data)
1034 {
1035 const OSSL_STORE_LOADER *loader = NULL;
1036 OSSL_STORE_LOADER *fetched_loader = NULL;
1037 OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
1038 OSSL_STORE_CTX *ctx = NULL;
1039
1040 if (scheme == NULL)
1041 scheme = "file";
1042
1043 OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme);
1044 ERR_set_mark();
1045 #ifndef OPENSSL_NO_DEPRECATED_3_0
1046 if ((loader = ossl_store_get0_loader_int(scheme)) != NULL)
1047 loader_ctx = loader->attach(loader, bp, libctx, propq,
1048 ui_method, ui_data);
1049 #endif
1050 if (loader == NULL
1051 && (fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq)) != NULL) {
1052 const OSSL_PROVIDER *provider = OSSL_STORE_LOADER_get0_provider(fetched_loader);
1053 void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider);
1054 OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp);
1055
1056 if (cbio == NULL
1057 || fetched_loader->p_attach == NULL
1058 || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) {
1059 OSSL_STORE_LOADER_free(fetched_loader);
1060 fetched_loader = NULL;
1061 } else if (!loader_set_params(fetched_loader, loader_ctx,
1062 params, propq)) {
1063 (void)fetched_loader->p_close(loader_ctx);
1064 OSSL_STORE_LOADER_free(fetched_loader);
1065 fetched_loader = NULL;
1066 }
1067 loader = fetched_loader;
1068 ossl_core_bio_free(cbio);
1069 }
1070
1071 if (loader_ctx == NULL) {
1072 ERR_clear_last_mark();
1073 return NULL;
1074 }
1075
1076 if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
1077 ERR_clear_last_mark();
1078 return NULL;
1079 }
1080
1081 if (ui_method != NULL
1082 && !ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data)) {
1083 ERR_clear_last_mark();
1084 OPENSSL_free(ctx);
1085 return NULL;
1086 }
1087
1088 ctx->fetched_loader = fetched_loader;
1089 ctx->loader = loader;
1090 ctx->loader_ctx = loader_ctx;
1091 ctx->post_process = post_process;
1092 ctx->post_process_data = post_process_data;
1093
1094 /*
1095 * ossl_store_get0_loader_int will raise an error if the loader for
1096 * the scheme cannot be retrieved. But if a loader was successfully
1097 * fetched then we remove this error from the error stack.
1098 */
1099 ERR_pop_to_mark();
1100
1101 return ctx;
1102 }
1103