Home | History | Annotate | Line # | Download | only in x509
      1 /*
      2  * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <stdio.h>
     11 #include "internal/cryptlib.h"
     12 #include "internal/refcount.h"
     13 #include <openssl/x509.h>
     14 #include "crypto/x509.h"
     15 #include <openssl/x509v3.h>
     16 #include "x509_local.h"
     17 
     18 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
     19 {
     20     X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret));
     21 
     22     if (ret == NULL)
     23         return NULL;
     24 
     25     ret->method = method;
     26     if (method->new_item != NULL && method->new_item(ret) == 0) {
     27         OPENSSL_free(ret);
     28         return NULL;
     29     }
     30     return ret;
     31 }
     32 
     33 void X509_LOOKUP_free(X509_LOOKUP *ctx)
     34 {
     35     if (ctx == NULL)
     36         return;
     37     if ((ctx->method != NULL) && (ctx->method->free != NULL))
     38         (*ctx->method->free)(ctx);
     39     OPENSSL_free(ctx);
     40 }
     41 
     42 int X509_STORE_lock(X509_STORE *xs)
     43 {
     44     return CRYPTO_THREAD_write_lock(xs->lock);
     45 }
     46 
     47 int ossl_x509_store_read_lock(X509_STORE *xs)
     48 {
     49     return CRYPTO_THREAD_read_lock(xs->lock);
     50 }
     51 
     52 int X509_STORE_unlock(X509_STORE *xs)
     53 {
     54     return CRYPTO_THREAD_unlock(xs->lock);
     55 }
     56 
     57 int X509_LOOKUP_init(X509_LOOKUP *ctx)
     58 {
     59     if (ctx->method == NULL)
     60         return 0;
     61     if (ctx->method->init != NULL)
     62         return ctx->method->init(ctx);
     63     else
     64         return 1;
     65 }
     66 
     67 int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
     68 {
     69     if (ctx->method == NULL)
     70         return 0;
     71     if (ctx->method->shutdown != NULL)
     72         return ctx->method->shutdown(ctx);
     73     else
     74         return 1;
     75 }
     76 
     77 int X509_LOOKUP_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
     78     char **ret, OSSL_LIB_CTX *libctx, const char *propq)
     79 {
     80     if (ctx->method == NULL)
     81         return -1;
     82     if (ctx->method->ctrl_ex != NULL)
     83         return ctx->method->ctrl_ex(ctx, cmd, argc, argl, ret, libctx, propq);
     84     if (ctx->method->ctrl != NULL)
     85         return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
     86     return 1;
     87 }
     88 
     89 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
     90     char **ret)
     91 {
     92     return X509_LOOKUP_ctrl_ex(ctx, cmd, argc, argl, ret, NULL, NULL);
     93 }
     94 
     95 int X509_LOOKUP_by_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
     96     const X509_NAME *name, X509_OBJECT *ret,
     97     OSSL_LIB_CTX *libctx, const char *propq)
     98 {
     99     if (ctx->skip
    100         || ctx->method == NULL
    101         || (ctx->method->get_by_subject == NULL
    102             && ctx->method->get_by_subject_ex == NULL))
    103         return 0;
    104     if (ctx->method->get_by_subject_ex != NULL)
    105         return ctx->method->get_by_subject_ex(ctx, type, name, ret, libctx,
    106             propq);
    107     else
    108         return ctx->method->get_by_subject(ctx, type, name, ret);
    109 }
    110 
    111 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
    112     const X509_NAME *name, X509_OBJECT *ret)
    113 {
    114     return X509_LOOKUP_by_subject_ex(ctx, type, name, ret, NULL, NULL);
    115 }
    116 
    117 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
    118     const X509_NAME *name,
    119     const ASN1_INTEGER *serial,
    120     X509_OBJECT *ret)
    121 {
    122     if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
    123         return 0;
    124     return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
    125 }
    126 
    127 int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
    128     const unsigned char *bytes, int len,
    129     X509_OBJECT *ret)
    130 {
    131     if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
    132         return 0;
    133     return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
    134 }
    135 
    136 int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
    137     const char *str, int len, X509_OBJECT *ret)
    138 {
    139     if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
    140         return 0;
    141     return ctx->method->get_by_alias(ctx, type, str, len, ret);
    142 }
    143 
    144 int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data)
    145 {
    146     ctx->method_data = data;
    147     return 1;
    148 }
    149 
    150 void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx)
    151 {
    152     return ctx->method_data;
    153 }
    154 
    155 X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx)
    156 {
    157     return ctx->store_ctx;
    158 }
    159 
    160 static int x509_object_cmp(const X509_OBJECT *const *a,
    161     const X509_OBJECT *const *b)
    162 {
    163     int ret;
    164 
    165     ret = ((*a)->type - (*b)->type);
    166     if (ret)
    167         return ret;
    168     switch ((*a)->type) {
    169     case X509_LU_X509:
    170         ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
    171         break;
    172     case X509_LU_CRL:
    173         ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
    174         break;
    175     case X509_LU_NONE:
    176         /* abort(); */
    177         return 0;
    178     }
    179     return ret;
    180 }
    181 
    182 X509_STORE *X509_STORE_new(void)
    183 {
    184     X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
    185 
    186     if (ret == NULL)
    187         return NULL;
    188     if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
    189         ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
    190         goto err;
    191     }
    192     ret->cache = 1;
    193     if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) {
    194         ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
    195         goto err;
    196     }
    197 
    198     if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) {
    199         ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
    200         goto err;
    201     }
    202     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
    203         ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
    204         goto err;
    205     }
    206 
    207     ret->lock = CRYPTO_THREAD_lock_new();
    208     if (ret->lock == NULL) {
    209         ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
    210         goto err;
    211     }
    212 
    213     if (!CRYPTO_NEW_REF(&ret->references, 1))
    214         goto err;
    215     return ret;
    216 
    217 err:
    218     X509_VERIFY_PARAM_free(ret->param);
    219     sk_X509_OBJECT_free(ret->objs);
    220     sk_X509_LOOKUP_free(ret->get_cert_methods);
    221     CRYPTO_THREAD_lock_free(ret->lock);
    222     OPENSSL_free(ret);
    223     return NULL;
    224 }
    225 
    226 void X509_STORE_free(X509_STORE *xs)
    227 {
    228     int i;
    229     STACK_OF(X509_LOOKUP) *sk;
    230     X509_LOOKUP *lu;
    231 
    232     if (xs == NULL)
    233         return;
    234     CRYPTO_DOWN_REF(&xs->references, &i);
    235     REF_PRINT_COUNT("X509_STORE", i, xs);
    236     if (i > 0)
    237         return;
    238     REF_ASSERT_ISNT(i < 0);
    239 
    240     sk = xs->get_cert_methods;
    241     for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
    242         lu = sk_X509_LOOKUP_value(sk, i);
    243         X509_LOOKUP_shutdown(lu);
    244         X509_LOOKUP_free(lu);
    245     }
    246     sk_X509_LOOKUP_free(sk);
    247     sk_X509_OBJECT_pop_free(xs->objs, X509_OBJECT_free);
    248 
    249     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, xs, &xs->ex_data);
    250     X509_VERIFY_PARAM_free(xs->param);
    251     CRYPTO_THREAD_lock_free(xs->lock);
    252     CRYPTO_FREE_REF(&xs->references);
    253     OPENSSL_free(xs);
    254 }
    255 
    256 int X509_STORE_up_ref(X509_STORE *xs)
    257 {
    258     int i;
    259 
    260     if (CRYPTO_UP_REF(&xs->references, &i) <= 0)
    261         return 0;
    262 
    263     REF_PRINT_COUNT("X509_STORE", i, xs);
    264     REF_ASSERT_ISNT(i < 2);
    265     return i > 1 ? 1 : 0;
    266 }
    267 
    268 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m)
    269 {
    270     int i;
    271     STACK_OF(X509_LOOKUP) *sk;
    272     X509_LOOKUP *lu;
    273 
    274     sk = xs->get_cert_methods;
    275     for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
    276         lu = sk_X509_LOOKUP_value(sk, i);
    277         if (m == lu->method) {
    278             return lu;
    279         }
    280     }
    281     /* a new one */
    282     lu = X509_LOOKUP_new(m);
    283     if (lu == NULL) {
    284         ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
    285         return NULL;
    286     }
    287 
    288     lu->store_ctx = xs;
    289     if (sk_X509_LOOKUP_push(xs->get_cert_methods, lu))
    290         return lu;
    291     /* sk_X509_LOOKUP_push() failed */
    292     ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
    293     X509_LOOKUP_free(lu);
    294     return NULL;
    295 }
    296 
    297 /* Also fill the cache (ctx->store->objs) with all matching certificates. */
    298 X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *ctx,
    299     X509_LOOKUP_TYPE type,
    300     const X509_NAME *name)
    301 {
    302     X509_OBJECT *ret = X509_OBJECT_new();
    303 
    304     if (ret == NULL)
    305         return NULL;
    306     if (!X509_STORE_CTX_get_by_subject(ctx, type, name, ret)) {
    307         X509_OBJECT_free(ret);
    308         return NULL;
    309     }
    310     return ret;
    311 }
    312 
    313 /*
    314  * May be called with |ret| == NULL just for the side effect of
    315  * caching all certs matching the given subject DN in |ctx->store->objs|.
    316  * Returns 1 if successful,
    317  * 0 if not found or X509_LOOKUP_by_subject_ex() returns an error,
    318  * -1 on failure
    319  */
    320 int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type,
    321     const X509_NAME *name, X509_OBJECT *ret)
    322 {
    323     X509_STORE *store = ctx->store;
    324     X509_LOOKUP *lu;
    325     X509_OBJECT stmp, *tmp;
    326     int i, j;
    327 
    328     if (store == NULL)
    329         return 0;
    330 
    331     stmp.type = X509_LU_NONE;
    332     stmp.data.x509 = NULL;
    333 
    334     if (!ossl_x509_store_read_lock(store))
    335         return 0;
    336     /* Should already be sorted...but just in case */
    337     if (!sk_X509_OBJECT_is_sorted(store->objs)) {
    338         X509_STORE_unlock(store);
    339         /* Take a write lock instead of a read lock */
    340         if (!X509_STORE_lock(store))
    341             return 0;
    342         /*
    343          * Another thread might have sorted it in the meantime. But if so,
    344          * sk_X509_OBJECT_sort() exits early.
    345          */
    346         sk_X509_OBJECT_sort(store->objs);
    347     }
    348     tmp = X509_OBJECT_retrieve_by_subject(store->objs, type, name);
    349     X509_STORE_unlock(store);
    350 
    351     if (tmp == NULL || type == X509_LU_CRL) {
    352         for (i = 0; i < sk_X509_LOOKUP_num(store->get_cert_methods); i++) {
    353             lu = sk_X509_LOOKUP_value(store->get_cert_methods, i);
    354             if (lu->skip)
    355                 continue;
    356             if (lu->method == NULL)
    357                 return -1;
    358             j = X509_LOOKUP_by_subject_ex(lu, type, name, &stmp,
    359                 ctx->libctx, ctx->propq);
    360             if (j != 0) { /* non-zero value is considered success here */
    361                 tmp = &stmp;
    362                 break;
    363             }
    364         }
    365         if (tmp == NULL)
    366             return 0;
    367     }
    368 
    369     if (ret != NULL) {
    370         if (!X509_OBJECT_up_ref_count(tmp))
    371             return -1;
    372         ret->type = tmp->type;
    373         ret->data = tmp->data;
    374     }
    375     return 1;
    376 }
    377 
    378 /* Also fill the cache |ctx->store->objs| with all matching certificates. */
    379 int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *ctx,
    380     X509_LOOKUP_TYPE type,
    381     const X509_NAME *name, X509_OBJECT *ret)
    382 {
    383     return ossl_x509_store_ctx_get_by_subject(ctx, type, name, ret) > 0;
    384 }
    385 
    386 static int x509_store_add(X509_STORE *store, void *x, int crl)
    387 {
    388     X509_OBJECT *obj;
    389     int ret = 0, added = 0;
    390 
    391     if (x == NULL)
    392         return 0;
    393     obj = X509_OBJECT_new();
    394     if (obj == NULL)
    395         return 0;
    396 
    397     if (crl) {
    398         obj->type = X509_LU_CRL;
    399         obj->data.crl = (X509_CRL *)x;
    400     } else {
    401         obj->type = X509_LU_X509;
    402         obj->data.x509 = (X509 *)x;
    403     }
    404     if (!X509_OBJECT_up_ref_count(obj)) {
    405         obj->type = X509_LU_NONE;
    406         X509_OBJECT_free(obj);
    407         return 0;
    408     }
    409 
    410     if (!X509_STORE_lock(store)) {
    411         X509_OBJECT_free(obj);
    412         return 0;
    413     }
    414 
    415     if (X509_OBJECT_retrieve_match(store->objs, obj)) {
    416         ret = 1;
    417     } else {
    418         added = sk_X509_OBJECT_push(store->objs, obj);
    419         ret = added != 0;
    420     }
    421     X509_STORE_unlock(store);
    422 
    423     if (added == 0) /* obj not pushed */
    424         X509_OBJECT_free(obj);
    425 
    426     return ret;
    427 }
    428 
    429 int X509_STORE_add_cert(X509_STORE *xs, X509 *x)
    430 {
    431     if (!x509_store_add(xs, x, 0)) {
    432         ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
    433         return 0;
    434     }
    435     return 1;
    436 }
    437 
    438 int X509_STORE_add_crl(X509_STORE *xs, X509_CRL *x)
    439 {
    440     if (!x509_store_add(xs, x, 1)) {
    441         ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
    442         return 0;
    443     }
    444     return 1;
    445 }
    446 
    447 int X509_OBJECT_up_ref_count(X509_OBJECT *a)
    448 {
    449     switch (a->type) {
    450     case X509_LU_NONE:
    451         break;
    452     case X509_LU_X509:
    453         return X509_up_ref(a->data.x509);
    454     case X509_LU_CRL:
    455         return X509_CRL_up_ref(a->data.crl);
    456     }
    457     return 1;
    458 }
    459 
    460 X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
    461 {
    462     if (a == NULL || a->type != X509_LU_X509)
    463         return NULL;
    464     return a->data.x509;
    465 }
    466 
    467 X509_CRL *X509_OBJECT_get0_X509_CRL(const X509_OBJECT *a)
    468 {
    469     if (a == NULL || a->type != X509_LU_CRL)
    470         return NULL;
    471     return a->data.crl;
    472 }
    473 
    474 X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a)
    475 {
    476     return a->type;
    477 }
    478 
    479 X509_OBJECT *X509_OBJECT_new(void)
    480 {
    481     X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret));
    482 
    483     if (ret == NULL)
    484         return NULL;
    485     ret->type = X509_LU_NONE;
    486     return ret;
    487 }
    488 
    489 static void x509_object_free_internal(X509_OBJECT *a)
    490 {
    491     if (a == NULL)
    492         return;
    493     switch (a->type) {
    494     case X509_LU_NONE:
    495         break;
    496     case X509_LU_X509:
    497         X509_free(a->data.x509);
    498         break;
    499     case X509_LU_CRL:
    500         X509_CRL_free(a->data.crl);
    501         break;
    502     }
    503 }
    504 
    505 int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj)
    506 {
    507     if (a == NULL || !X509_up_ref(obj))
    508         return 0;
    509 
    510     x509_object_free_internal(a);
    511     a->type = X509_LU_X509;
    512     a->data.x509 = obj;
    513     return 1;
    514 }
    515 
    516 int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj)
    517 {
    518     if (a == NULL || !X509_CRL_up_ref(obj))
    519         return 0;
    520 
    521     x509_object_free_internal(a);
    522     a->type = X509_LU_CRL;
    523     a->data.crl = obj;
    524     return 1;
    525 }
    526 
    527 void X509_OBJECT_free(X509_OBJECT *a)
    528 {
    529     x509_object_free_internal(a);
    530     OPENSSL_free(a);
    531 }
    532 
    533 /* Returns -1 if not found, but also on error */
    534 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
    535     const X509_NAME *name, int *pnmatch)
    536 {
    537     X509_OBJECT stmp;
    538     X509 x509_s;
    539     X509_CRL crl_s;
    540 
    541     stmp.type = type;
    542     switch (type) {
    543     case X509_LU_X509:
    544         stmp.data.x509 = &x509_s;
    545         x509_s.cert_info.subject = (X509_NAME *)name; /* won't modify it */
    546         break;
    547     case X509_LU_CRL:
    548         stmp.data.crl = &crl_s;
    549         crl_s.crl.issuer = (X509_NAME *)name; /* won't modify it */
    550         break;
    551     case X509_LU_NONE:
    552     default:
    553         /* abort(); */
    554         return -1;
    555     }
    556 
    557     /* Assumes h is locked for read if applicable */
    558     return sk_X509_OBJECT_find_all(h, &stmp, pnmatch);
    559 }
    560 
    561 /* Assumes h is locked for read if applicable */
    562 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
    563     const X509_NAME *name)
    564 {
    565     return x509_object_idx_cnt(h, type, name, NULL);
    566 }
    567 
    568 /* Assumes h is locked for read if applicable */
    569 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
    570     X509_LOOKUP_TYPE type,
    571     const X509_NAME *name)
    572 {
    573     int idx = X509_OBJECT_idx_by_subject(h, type, name);
    574 
    575     if (idx == -1)
    576         return NULL;
    577     return sk_X509_OBJECT_value(h, idx);
    578 }
    579 
    580 STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *xs)
    581 {
    582     return xs->objs;
    583 }
    584 
    585 static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj)
    586 {
    587     X509_OBJECT *ret = X509_OBJECT_new();
    588     if (ret == NULL)
    589         return NULL;
    590 
    591     ret->type = obj->type;
    592     ret->data = obj->data;
    593     X509_OBJECT_up_ref_count(ret);
    594     return ret;
    595 }
    596 
    597 STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(X509_STORE *store)
    598 {
    599     STACK_OF(X509_OBJECT) *objs;
    600 
    601     if (store == NULL) {
    602         ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
    603         return NULL;
    604     }
    605 
    606     if (!ossl_x509_store_read_lock(store))
    607         return NULL;
    608 
    609     objs = sk_X509_OBJECT_deep_copy(store->objs, x509_object_dup,
    610         X509_OBJECT_free);
    611     X509_STORE_unlock(store);
    612     return objs;
    613 }
    614 
    615 STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store)
    616 {
    617     STACK_OF(X509) *sk;
    618     STACK_OF(X509_OBJECT) *objs;
    619     int i;
    620 
    621     if (store == NULL) {
    622         ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
    623         return NULL;
    624     }
    625     if ((sk = sk_X509_new_null()) == NULL)
    626         return NULL;
    627     if (!X509_STORE_lock(store))
    628         goto out_free;
    629 
    630     sk_X509_OBJECT_sort(store->objs);
    631     objs = X509_STORE_get0_objects(store);
    632     for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
    633         X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
    634 
    635         if (cert != NULL
    636             && !X509_add_cert(sk, cert, X509_ADD_FLAG_UP_REF))
    637             goto err;
    638     }
    639     X509_STORE_unlock(store);
    640     return sk;
    641 
    642 err:
    643     X509_STORE_unlock(store);
    644 out_free:
    645     OSSL_STACK_OF_X509_free(sk);
    646     return NULL;
    647 }
    648 
    649 /*-
    650  * Collect from |ctx->store| all certs with subject matching |nm|.
    651  * Returns NULL on internal/fatal error, empty stack if not found.
    652  */
    653 STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx,
    654     const X509_NAME *nm)
    655 {
    656     int i, idx, cnt;
    657     STACK_OF(X509) *sk = NULL;
    658     X509 *x;
    659     X509_OBJECT *obj;
    660     X509_STORE *store = ctx->store;
    661 
    662     if (store == NULL)
    663         return sk_X509_new_null();
    664 
    665     if (!X509_STORE_lock(store))
    666         return NULL;
    667 
    668     sk_X509_OBJECT_sort(store->objs);
    669     idx = x509_object_idx_cnt(store->objs, X509_LU_X509, nm, &cnt);
    670     if (idx < 0) {
    671         /*
    672          * Nothing found in cache: do lookup to possibly add new objects to
    673          * cache
    674          */
    675         X509_STORE_unlock(store);
    676         i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_X509, nm, NULL);
    677         if (i <= 0)
    678             return i < 0 ? NULL : sk_X509_new_null();
    679         if (!X509_STORE_lock(store))
    680             return NULL;
    681         sk_X509_OBJECT_sort(store->objs);
    682         idx = x509_object_idx_cnt(store->objs, X509_LU_X509, nm, &cnt);
    683     }
    684 
    685     sk = sk_X509_new_null();
    686     if (idx < 0 || sk == NULL)
    687         goto end;
    688     for (i = 0; i < cnt; i++, idx++) {
    689         obj = sk_X509_OBJECT_value(store->objs, idx);
    690         x = obj->data.x509;
    691         if (!X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF)) {
    692             X509_STORE_unlock(store);
    693             OSSL_STACK_OF_X509_free(sk);
    694             return NULL;
    695         }
    696     }
    697 end:
    698     X509_STORE_unlock(store);
    699     return sk;
    700 }
    701 
    702 /* Returns NULL on internal/fatal error, empty stack if not found */
    703 STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *ctx,
    704     const X509_NAME *nm)
    705 {
    706     int i = 1, idx, cnt;
    707     STACK_OF(X509_CRL) *sk;
    708     X509_CRL *x;
    709     X509_OBJECT *obj;
    710     X509_STORE *store = ctx->store;
    711 
    712     /* Always do lookup to possibly add new CRLs to cache */
    713     i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_CRL, nm, NULL);
    714     if (i < 0)
    715         return NULL;
    716     sk = sk_X509_CRL_new_null();
    717     if (i == 0)
    718         return sk;
    719     if (!X509_STORE_lock(store)) {
    720         sk_X509_CRL_free(sk);
    721         return NULL;
    722     }
    723     sk_X509_OBJECT_sort(store->objs);
    724     idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, nm, &cnt);
    725     if (idx < 0) {
    726         X509_STORE_unlock(store);
    727         return sk;
    728     }
    729 
    730     for (i = 0; i < cnt; i++, idx++) {
    731         obj = sk_X509_OBJECT_value(store->objs, idx);
    732         x = obj->data.crl;
    733         if (!X509_CRL_up_ref(x)) {
    734             X509_STORE_unlock(store);
    735             sk_X509_CRL_pop_free(sk, X509_CRL_free);
    736             return NULL;
    737         }
    738         if (!sk_X509_CRL_push(sk, x)) {
    739             X509_STORE_unlock(store);
    740             X509_CRL_free(x);
    741             sk_X509_CRL_pop_free(sk, X509_CRL_free);
    742             return NULL;
    743         }
    744     }
    745     X509_STORE_unlock(store);
    746     return sk;
    747 }
    748 
    749 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
    750     X509_OBJECT *x)
    751 {
    752     int idx, i, num;
    753     X509_OBJECT *obj;
    754 
    755     idx = sk_X509_OBJECT_find(h, x);
    756     if (idx < 0)
    757         return NULL;
    758     if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
    759         return sk_X509_OBJECT_value(h, idx);
    760     for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) {
    761         obj = sk_X509_OBJECT_value(h, i);
    762         if (x509_object_cmp((const X509_OBJECT **)&obj,
    763                 (const X509_OBJECT **)&x))
    764             return NULL;
    765         if (x->type == X509_LU_X509) {
    766             if (!X509_cmp(obj->data.x509, x->data.x509))
    767                 return obj;
    768         } else if (x->type == X509_LU_CRL) {
    769             if (X509_CRL_match(obj->data.crl, x->data.crl) == 0)
    770                 return obj;
    771         } else {
    772             return obj;
    773         }
    774     }
    775     return NULL;
    776 }
    777 
    778 int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags)
    779 {
    780     return X509_VERIFY_PARAM_set_flags(xs->param, flags);
    781 }
    782 
    783 int X509_STORE_set_depth(X509_STORE *xs, int depth)
    784 {
    785     X509_VERIFY_PARAM_set_depth(xs->param, depth);
    786     return 1;
    787 }
    788 
    789 int X509_STORE_set_purpose(X509_STORE *xs, int purpose)
    790 {
    791     return X509_VERIFY_PARAM_set_purpose(xs->param, purpose);
    792 }
    793 
    794 int X509_STORE_set_trust(X509_STORE *xs, int trust)
    795 {
    796     return X509_VERIFY_PARAM_set_trust(xs->param, trust);
    797 }
    798 
    799 int X509_STORE_set1_param(X509_STORE *xs, const X509_VERIFY_PARAM *param)
    800 {
    801     return X509_VERIFY_PARAM_set1(xs->param, param);
    802 }
    803 
    804 X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *xs)
    805 {
    806     return xs->param;
    807 }
    808 
    809 void X509_STORE_set_verify(X509_STORE *xs, X509_STORE_CTX_verify_fn verify)
    810 {
    811     xs->verify = verify;
    812 }
    813 
    814 X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *xs)
    815 {
    816     return xs->verify;
    817 }
    818 
    819 void X509_STORE_set_verify_cb(X509_STORE *xs,
    820     X509_STORE_CTX_verify_cb verify_cb)
    821 {
    822     xs->verify_cb = verify_cb;
    823 }
    824 
    825 X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *xs)
    826 {
    827     return xs->verify_cb;
    828 }
    829 
    830 void X509_STORE_set_get_issuer(X509_STORE *xs,
    831     X509_STORE_CTX_get_issuer_fn get_issuer)
    832 {
    833     xs->get_issuer = get_issuer;
    834 }
    835 
    836 X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *xs)
    837 {
    838     return xs->get_issuer;
    839 }
    840 
    841 void X509_STORE_set_check_issued(X509_STORE *xs,
    842     X509_STORE_CTX_check_issued_fn check_issued)
    843 {
    844     xs->check_issued = check_issued;
    845 }
    846 
    847 X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *xs)
    848 {
    849     return xs->check_issued;
    850 }
    851 
    852 void X509_STORE_set_check_revocation(X509_STORE *xs,
    853     X509_STORE_CTX_check_revocation_fn cb)
    854 {
    855     xs->check_revocation = cb;
    856 }
    857 
    858 X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *xs)
    859 {
    860     return xs->check_revocation;
    861 }
    862 
    863 void X509_STORE_set_get_crl(X509_STORE *xs,
    864     X509_STORE_CTX_get_crl_fn get_crl)
    865 {
    866     xs->get_crl = get_crl;
    867 }
    868 
    869 X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *xs)
    870 {
    871     return xs->get_crl;
    872 }
    873 
    874 void X509_STORE_set_check_crl(X509_STORE *xs,
    875     X509_STORE_CTX_check_crl_fn check_crl)
    876 {
    877     xs->check_crl = check_crl;
    878 }
    879 
    880 X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *xs)
    881 {
    882     return xs->check_crl;
    883 }
    884 
    885 void X509_STORE_set_cert_crl(X509_STORE *xs,
    886     X509_STORE_CTX_cert_crl_fn cert_crl)
    887 {
    888     xs->cert_crl = cert_crl;
    889 }
    890 
    891 X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *xs)
    892 {
    893     return xs->cert_crl;
    894 }
    895 
    896 void X509_STORE_set_check_policy(X509_STORE *xs,
    897     X509_STORE_CTX_check_policy_fn check_policy)
    898 {
    899     xs->check_policy = check_policy;
    900 }
    901 
    902 X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *xs)
    903 {
    904     return xs->check_policy;
    905 }
    906 
    907 void X509_STORE_set_lookup_certs(X509_STORE *xs,
    908     X509_STORE_CTX_lookup_certs_fn lookup_certs)
    909 {
    910     xs->lookup_certs = lookup_certs;
    911 }
    912 
    913 X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *xs)
    914 {
    915     return xs->lookup_certs;
    916 }
    917 
    918 void X509_STORE_set_lookup_crls(X509_STORE *xs,
    919     X509_STORE_CTX_lookup_crls_fn lookup_crls)
    920 {
    921     xs->lookup_crls = lookup_crls;
    922 }
    923 
    924 X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *xs)
    925 {
    926     return xs->lookup_crls;
    927 }
    928 
    929 void X509_STORE_set_cleanup(X509_STORE *xs,
    930     X509_STORE_CTX_cleanup_fn cleanup)
    931 {
    932     xs->cleanup = cleanup;
    933 }
    934 
    935 X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *xs)
    936 {
    937     return xs->cleanup;
    938 }
    939 
    940 int X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data)
    941 {
    942     return CRYPTO_set_ex_data(&xs->ex_data, idx, data);
    943 }
    944 
    945 void *X509_STORE_get_ex_data(const X509_STORE *xs, int idx)
    946 {
    947     return CRYPTO_get_ex_data(&xs->ex_data, idx);
    948 }
    949 
    950 X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
    951 {
    952     return ctx->store;
    953 }
    954