xref: /freebsd/crypto/openssl/crypto/store/store_lib.c (revision 10a428653ee7216475f1ddce3fb4cbf1200319f8)
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