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