Home | History | Annotate | Download | only in x509
      1 /* crypto/x509/x509_lu.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) cryptsoft.com).
      7  * The implementation was written so as to conform with Netscapes SSL.
      8  *
      9  * This library is free for commercial and non-commercial use as long as
     10  * the following conditions are aheared to.  The following conditions
     11  * apply to all code found in this distribution, be it the RC4, RSA,
     12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     13  * included with this distribution is covered by the same copyright terms
     14  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     15  *
     16  * Copyright remains Eric Young's, and as such any Copyright notices in
     17  * the code are not to be removed.
     18  * If this package is used in a product, Eric Young should be given attribution
     19  * as the author of the parts of the library used.
     20  * This can be in the form of a textual message at program startup or
     21  * in documentation (online or textual) provided with the package.
     22  *
     23  * Redistribution and use in source and binary forms, with or without
     24  * modification, are permitted provided that the following conditions
     25  * are met:
     26  * 1. Redistributions of source code must retain the copyright
     27  *    notice, this list of conditions and the following disclaimer.
     28  * 2. Redistributions in binary form must reproduce the above copyright
     29  *    notice, this list of conditions and the following disclaimer in the
     30  *    documentation and/or other materials provided with the distribution.
     31  * 3. All advertising materials mentioning features or use of this software
     32  *    must display the following acknowledgement:
     33  *    "This product includes cryptographic software written by
     34  *     Eric Young (eay (at) cryptsoft.com)"
     35  *    The word 'cryptographic' can be left out if the rouines from the library
     36  *    being used are not cryptographic related :-).
     37  * 4. If you include any Windows specific code (or a derivative thereof) from
     38  *    the apps directory (application code) you must include an acknowledgement:
     39  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     40  *
     41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     51  * SUCH DAMAGE.
     52  *
     53  * The licence and distribution terms for any publically available version or
     54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     55  * copied and put under another distribution licence
     56  * [including the GNU Public Licence.] */
     57 
     58 #include <string.h>
     59 
     60 #include <openssl/err.h>
     61 #include <openssl/lhash.h>
     62 #include <openssl/mem.h>
     63 #include <openssl/thread.h>
     64 #include <openssl/x509.h>
     65 #include <openssl/x509v3.h>
     66 
     67 #include "../internal.h"
     68 
     69 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
     70 {
     71     X509_LOOKUP *ret;
     72 
     73     ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
     74     if (ret == NULL)
     75         return NULL;
     76 
     77     ret->init = 0;
     78     ret->skip = 0;
     79     ret->method = method;
     80     ret->method_data = NULL;
     81     ret->store_ctx = NULL;
     82     if ((method->new_item != NULL) && !method->new_item(ret)) {
     83         OPENSSL_free(ret);
     84         return NULL;
     85     }
     86     return ret;
     87 }
     88 
     89 void X509_LOOKUP_free(X509_LOOKUP *ctx)
     90 {
     91     if (ctx == NULL)
     92         return;
     93     if ((ctx->method != NULL) && (ctx->method->free != NULL))
     94         (*ctx->method->free) (ctx);
     95     OPENSSL_free(ctx);
     96 }
     97 
     98 int X509_LOOKUP_init(X509_LOOKUP *ctx)
     99 {
    100     if (ctx->method == NULL)
    101         return 0;
    102     if (ctx->method->init != NULL)
    103         return ctx->method->init(ctx);
    104     else
    105         return 1;
    106 }
    107 
    108 int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
    109 {
    110     if (ctx->method == NULL)
    111         return 0;
    112     if (ctx->method->shutdown != NULL)
    113         return ctx->method->shutdown(ctx);
    114     else
    115         return 1;
    116 }
    117 
    118 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
    119                      char **ret)
    120 {
    121     if (ctx->method == NULL)
    122         return -1;
    123     if (ctx->method->ctrl != NULL)
    124         return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
    125     else
    126         return 1;
    127 }
    128 
    129 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
    130                            X509_OBJECT *ret)
    131 {
    132     if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
    133         return 0;
    134     if (ctx->skip)
    135         return 0;
    136     return ctx->method->get_by_subject(ctx, type, name, ret) > 0;
    137 }
    138 
    139 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
    140                                  ASN1_INTEGER *serial, X509_OBJECT *ret)
    141 {
    142     if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
    143         return 0;
    144     return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0;
    145 }
    146 
    147 int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
    148                                unsigned char *bytes, int len,
    149                                X509_OBJECT *ret)
    150 {
    151     if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
    152         return 0;
    153     return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0;
    154 }
    155 
    156 int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
    157                          X509_OBJECT *ret)
    158 {
    159     if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
    160         return 0;
    161     return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0;
    162 }
    163 
    164 static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
    165 {
    166     int ret;
    167 
    168     ret = ((*a)->type - (*b)->type);
    169     if (ret)
    170         return ret;
    171     switch ((*a)->type) {
    172     case X509_LU_X509:
    173         ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
    174         break;
    175     case X509_LU_CRL:
    176         ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
    177         break;
    178     default:
    179         /* abort(); */
    180         return 0;
    181     }
    182     return ret;
    183 }
    184 
    185 X509_STORE *X509_STORE_new(void)
    186 {
    187     X509_STORE *ret;
    188 
    189     if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
    190         return NULL;
    191     OPENSSL_memset(ret, 0, sizeof(*ret));
    192     CRYPTO_MUTEX_init(&ret->objs_lock);
    193     ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
    194     if (ret->objs == NULL)
    195         goto err;
    196     ret->cache = 1;
    197     ret->get_cert_methods = sk_X509_LOOKUP_new_null();
    198     if (ret->get_cert_methods == NULL)
    199         goto err;
    200     ret->param = X509_VERIFY_PARAM_new();
    201     if (ret->param == NULL)
    202         goto err;
    203 
    204     ret->references = 1;
    205     return ret;
    206  err:
    207     if (ret) {
    208         CRYPTO_MUTEX_cleanup(&ret->objs_lock);
    209         if (ret->param)
    210             X509_VERIFY_PARAM_free(ret->param);
    211         if (ret->get_cert_methods)
    212             sk_X509_LOOKUP_free(ret->get_cert_methods);
    213         if (ret->objs)
    214             sk_X509_OBJECT_free(ret->objs);
    215         OPENSSL_free(ret);
    216     }
    217     return NULL;
    218 }
    219 
    220 int X509_STORE_up_ref(X509_STORE *store)
    221 {
    222     CRYPTO_refcount_inc(&store->references);
    223     return 1;
    224 }
    225 
    226 static void cleanup(X509_OBJECT *a)
    227 {
    228     if (a == NULL) {
    229         return;
    230     }
    231     if (a->type == X509_LU_X509) {
    232         X509_free(a->data.x509);
    233     } else if (a->type == X509_LU_CRL) {
    234         X509_CRL_free(a->data.crl);
    235     } else {
    236         /* abort(); */
    237     }
    238 
    239     OPENSSL_free(a);
    240 }
    241 
    242 void X509_STORE_free(X509_STORE *vfy)
    243 {
    244     size_t j;
    245     STACK_OF(X509_LOOKUP) *sk;
    246     X509_LOOKUP *lu;
    247 
    248     if (vfy == NULL)
    249         return;
    250 
    251     if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
    252         return;
    253     }
    254 
    255     CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
    256 
    257     sk = vfy->get_cert_methods;
    258     for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) {
    259         lu = sk_X509_LOOKUP_value(sk, j);
    260         X509_LOOKUP_shutdown(lu);
    261         X509_LOOKUP_free(lu);
    262     }
    263     sk_X509_LOOKUP_free(sk);
    264     sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
    265 
    266     if (vfy->param)
    267         X509_VERIFY_PARAM_free(vfy->param);
    268     OPENSSL_free(vfy);
    269 }
    270 
    271 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
    272 {
    273     size_t i;
    274     STACK_OF(X509_LOOKUP) *sk;
    275     X509_LOOKUP *lu;
    276 
    277     sk = v->get_cert_methods;
    278     for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
    279         lu = sk_X509_LOOKUP_value(sk, i);
    280         if (m == lu->method) {
    281             return lu;
    282         }
    283     }
    284     /* a new one */
    285     lu = X509_LOOKUP_new(m);
    286     if (lu == NULL)
    287         return NULL;
    288     else {
    289         lu->store_ctx = v;
    290         if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
    291             return lu;
    292         else {
    293             X509_LOOKUP_free(lu);
    294             return NULL;
    295         }
    296     }
    297 }
    298 
    299 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
    300                               X509_OBJECT *ret)
    301 {
    302     X509_STORE *ctx = vs->ctx;
    303     X509_LOOKUP *lu;
    304     X509_OBJECT stmp, *tmp;
    305     int i;
    306 
    307     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    308     tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
    309     CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
    310 
    311     if (tmp == NULL || type == X509_LU_CRL) {
    312         for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
    313             lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
    314             if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) {
    315                 tmp = &stmp;
    316                 break;
    317             }
    318         }
    319         if (tmp == NULL)
    320             return 0;
    321     }
    322 
    323     /*
    324      * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret);
    325      */
    326 
    327     ret->type = tmp->type;
    328     ret->data.ptr = tmp->data.ptr;
    329 
    330     X509_OBJECT_up_ref_count(ret);
    331 
    332     return 1;
    333 }
    334 
    335 int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
    336 {
    337     X509_OBJECT *obj;
    338     int ret = 1;
    339 
    340     if (x == NULL)
    341         return 0;
    342     obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    343     if (obj == NULL) {
    344         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    345         return 0;
    346     }
    347     obj->type = X509_LU_X509;
    348     obj->data.x509 = x;
    349 
    350     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    351 
    352     X509_OBJECT_up_ref_count(obj);
    353 
    354     if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
    355         X509_OBJECT_free_contents(obj);
    356         OPENSSL_free(obj);
    357         OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
    358         ret = 0;
    359     } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
    360         X509_OBJECT_free_contents(obj);
    361         OPENSSL_free(obj);
    362         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    363         ret = 0;
    364     }
    365 
    366     CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
    367 
    368     return ret;
    369 }
    370 
    371 int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
    372 {
    373     X509_OBJECT *obj;
    374     int ret = 1;
    375 
    376     if (x == NULL)
    377         return 0;
    378     obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    379     if (obj == NULL) {
    380         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    381         return 0;
    382     }
    383     obj->type = X509_LU_CRL;
    384     obj->data.crl = x;
    385 
    386     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    387 
    388     X509_OBJECT_up_ref_count(obj);
    389 
    390     if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
    391         X509_OBJECT_free_contents(obj);
    392         OPENSSL_free(obj);
    393         OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
    394         ret = 0;
    395     } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
    396         X509_OBJECT_free_contents(obj);
    397         OPENSSL_free(obj);
    398         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    399         ret = 0;
    400     }
    401 
    402     CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
    403 
    404     return ret;
    405 }
    406 
    407 void X509_STORE_set0_additional_untrusted(X509_STORE *ctx,
    408                                           STACK_OF(X509) *untrusted) {
    409   ctx->additional_untrusted = untrusted;
    410 }
    411 
    412 int X509_OBJECT_up_ref_count(X509_OBJECT *a)
    413 {
    414     switch (a->type) {
    415     case X509_LU_X509:
    416         X509_up_ref(a->data.x509);
    417         break;
    418     case X509_LU_CRL:
    419         X509_CRL_up_ref(a->data.crl);
    420         break;
    421     }
    422     return 1;
    423 }
    424 
    425 void X509_OBJECT_free_contents(X509_OBJECT *a)
    426 {
    427     switch (a->type) {
    428     case X509_LU_X509:
    429         X509_free(a->data.x509);
    430         break;
    431     case X509_LU_CRL:
    432         X509_CRL_free(a->data.crl);
    433         break;
    434     }
    435 }
    436 
    437 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
    438                                X509_NAME *name, int *pnmatch)
    439 {
    440     X509_OBJECT stmp;
    441     X509 x509_s;
    442     X509_CINF cinf_s;
    443     X509_CRL crl_s;
    444     X509_CRL_INFO crl_info_s;
    445 
    446     stmp.type = type;
    447     switch (type) {
    448     case X509_LU_X509:
    449         stmp.data.x509 = &x509_s;
    450         x509_s.cert_info = &cinf_s;
    451         cinf_s.subject = name;
    452         break;
    453     case X509_LU_CRL:
    454         stmp.data.crl = &crl_s;
    455         crl_s.crl = &crl_info_s;
    456         crl_info_s.issuer = name;
    457         break;
    458     default:
    459         /* abort(); */
    460         return -1;
    461     }
    462 
    463     size_t idx;
    464     if (!sk_X509_OBJECT_find(h, &idx, &stmp))
    465         return -1;
    466 
    467     if (pnmatch != NULL) {
    468         int tidx;
    469         const X509_OBJECT *tobj, *pstmp;
    470         *pnmatch = 1;
    471         pstmp = &stmp;
    472         for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) {
    473             tobj = sk_X509_OBJECT_value(h, tidx);
    474             if (x509_object_cmp(&tobj, &pstmp))
    475                 break;
    476             (*pnmatch)++;
    477         }
    478     }
    479 
    480     return idx;
    481 }
    482 
    483 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
    484                                X509_NAME *name)
    485 {
    486     return x509_object_idx_cnt(h, type, name, NULL);
    487 }
    488 
    489 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
    490                                              int type, X509_NAME *name)
    491 {
    492     int idx;
    493     idx = X509_OBJECT_idx_by_subject(h, type, name);
    494     if (idx == -1)
    495         return NULL;
    496     return sk_X509_OBJECT_value(h, idx);
    497 }
    498 
    499 STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
    500 {
    501     int i, idx, cnt;
    502     STACK_OF(X509) *sk;
    503     X509 *x;
    504     X509_OBJECT *obj;
    505     sk = sk_X509_new_null();
    506     if (sk == NULL)
    507         return NULL;
    508     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    509     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
    510     if (idx < 0) {
    511         /*
    512          * Nothing found in cache: do lookup to possibly add new objects to
    513          * cache
    514          */
    515         X509_OBJECT xobj;
    516         CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    517         if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
    518             sk_X509_free(sk);
    519             return NULL;
    520         }
    521         X509_OBJECT_free_contents(&xobj);
    522         CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    523         idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
    524         if (idx < 0) {
    525             CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    526             sk_X509_free(sk);
    527             return NULL;
    528         }
    529     }
    530     for (i = 0; i < cnt; i++, idx++) {
    531         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
    532         x = obj->data.x509;
    533         if (!sk_X509_push(sk, x)) {
    534             CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    535             sk_X509_pop_free(sk, X509_free);
    536             return NULL;
    537         }
    538         X509_up_ref(x);
    539     }
    540     CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    541     return sk;
    542 
    543 }
    544 
    545 STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
    546 {
    547     int i, idx, cnt;
    548     STACK_OF(X509_CRL) *sk;
    549     X509_CRL *x;
    550     X509_OBJECT *obj, xobj;
    551     sk = sk_X509_CRL_new_null();
    552     if (sk == NULL)
    553         return NULL;
    554 
    555     /* Always do lookup to possibly add new CRLs to cache. */
    556     if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
    557         sk_X509_CRL_free(sk);
    558         return NULL;
    559     }
    560     X509_OBJECT_free_contents(&xobj);
    561     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    562     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
    563     if (idx < 0) {
    564         CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    565         sk_X509_CRL_free(sk);
    566         return NULL;
    567     }
    568 
    569     for (i = 0; i < cnt; i++, idx++) {
    570         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
    571         x = obj->data.crl;
    572         X509_CRL_up_ref(x);
    573         if (!sk_X509_CRL_push(sk, x)) {
    574             CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    575             X509_CRL_free(x);
    576             sk_X509_CRL_pop_free(sk, X509_CRL_free);
    577             return NULL;
    578         }
    579     }
    580     CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    581     return sk;
    582 }
    583 
    584 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
    585                                         X509_OBJECT *x)
    586 {
    587     size_t idx, i;
    588     X509_OBJECT *obj;
    589 
    590     if (!sk_X509_OBJECT_find(h, &idx, x)) {
    591         return NULL;
    592     }
    593     if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
    594         return sk_X509_OBJECT_value(h, idx);
    595     for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
    596         obj = sk_X509_OBJECT_value(h, i);
    597         if (x509_object_cmp
    598             ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
    599             return NULL;
    600         if (x->type == X509_LU_X509) {
    601             if (!X509_cmp(obj->data.x509, x->data.x509))
    602                 return obj;
    603         } else if (x->type == X509_LU_CRL) {
    604             if (!X509_CRL_match(obj->data.crl, x->data.crl))
    605                 return obj;
    606         } else
    607             return obj;
    608     }
    609     return NULL;
    610 }
    611 
    612 /*
    613  * Try to get issuer certificate from store. Due to limitations of the API
    614  * this can only retrieve a single certificate matching a given subject name.
    615  * However it will fill the cache with all matching certificates, so we can
    616  * examine the cache for all matches. Return values are: 1 lookup
    617  * successful.  0 certificate not found. -1 some other error.
    618  */
    619 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
    620 {
    621     X509_NAME *xn;
    622     X509_OBJECT obj, *pobj;
    623     int idx, ret;
    624     size_t i;
    625     xn = X509_get_issuer_name(x);
    626     if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj))
    627         return 0;
    628     /* If certificate matches all OK */
    629     if (ctx->check_issued(ctx, x, obj.data.x509)) {
    630         *issuer = obj.data.x509;
    631         return 1;
    632     }
    633     X509_OBJECT_free_contents(&obj);
    634 
    635     /* Else find index of first cert accepted by 'check_issued' */
    636     ret = 0;
    637     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    638     idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
    639     if (idx != -1) {            /* should be true as we've had at least one
    640                                  * match */
    641         /* Look through all matching certs for suitable issuer */
    642         for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
    643             pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
    644             /* See if we've run past the matches */
    645             if (pobj->type != X509_LU_X509)
    646                 break;
    647             if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
    648                 break;
    649             if (ctx->check_issued(ctx, x, pobj->data.x509)) {
    650                 *issuer = pobj->data.x509;
    651                 X509_OBJECT_up_ref_count(pobj);
    652                 ret = 1;
    653                 break;
    654             }
    655         }
    656     }
    657     CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    658     return ret;
    659 }
    660 
    661 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
    662 {
    663     return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
    664 }
    665 
    666 int X509_STORE_set_depth(X509_STORE *ctx, int depth)
    667 {
    668     X509_VERIFY_PARAM_set_depth(ctx->param, depth);
    669     return 1;
    670 }
    671 
    672 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
    673 {
    674     return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
    675 }
    676 
    677 int X509_STORE_set_trust(X509_STORE *ctx, int trust)
    678 {
    679     return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
    680 }
    681 
    682 int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
    683 {
    684     return X509_VERIFY_PARAM_set1(ctx->param, param);
    685 }
    686 
    687 void X509_STORE_set_verify_cb(X509_STORE *ctx,
    688                               int (*verify_cb) (int, X509_STORE_CTX *))
    689 {
    690     ctx->verify_cb = verify_cb;
    691 }
    692 
    693 void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
    694                                    STACK_OF (X509_CRL) *
    695                                    (*cb) (X509_STORE_CTX *ctx, X509_NAME *nm))
    696 {
    697     ctx->lookup_crls = cb;
    698 }
    699 
    700 X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
    701 {
    702     return ctx->ctx;
    703 }
    704