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