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/mem.h>
     62 #include <openssl/thread.h>
     63 #include <openssl/x509.h>
     64 #include <openssl/x509v3.h>
     65 
     66 #include "../internal.h"
     67 
     68 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
     69 {
     70     X509_LOOKUP *ret;
     71 
     72     ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
     73     if (ret == NULL)
     74         return NULL;
     75 
     76     ret->init = 0;
     77     ret->skip = 0;
     78     ret->method = method;
     79     ret->method_data = NULL;
     80     ret->store_ctx = NULL;
     81     if ((method->new_item != NULL) && !method->new_item(ret)) {
     82         OPENSSL_free(ret);
     83         return NULL;
     84     }
     85     return ret;
     86 }
     87 
     88 void X509_LOOKUP_free(X509_LOOKUP *ctx)
     89 {
     90     if (ctx == NULL)
     91         return;
     92     if ((ctx->method != NULL) && (ctx->method->free != NULL))
     93         (*ctx->method->free) (ctx);
     94     OPENSSL_free(ctx);
     95 }
     96 
     97 int X509_LOOKUP_init(X509_LOOKUP *ctx)
     98 {
     99     if (ctx->method == NULL)
    100         return 0;
    101     if (ctx->method->init != NULL)
    102         return ctx->method->init(ctx);
    103     else
    104         return 1;
    105 }
    106 
    107 int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
    108 {
    109     if (ctx->method == NULL)
    110         return 0;
    111     if (ctx->method->shutdown != NULL)
    112         return ctx->method->shutdown(ctx);
    113     else
    114         return 1;
    115 }
    116 
    117 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
    118                      char **ret)
    119 {
    120     if (ctx->method == NULL)
    121         return -1;
    122     if (ctx->method->ctrl != NULL)
    123         return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
    124     else
    125         return 1;
    126 }
    127 
    128 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
    129                            X509_OBJECT *ret)
    130 {
    131     if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
    132         return 0;
    133     if (ctx->skip)
    134         return 0;
    135     return ctx->method->get_by_subject(ctx, type, name, ret) > 0;
    136 }
    137 
    138 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
    139                                  ASN1_INTEGER *serial, X509_OBJECT *ret)
    140 {
    141     if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
    142         return 0;
    143     return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0;
    144 }
    145 
    146 int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
    147                                unsigned char *bytes, int len,
    148                                X509_OBJECT *ret)
    149 {
    150     if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
    151         return 0;
    152     return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0;
    153 }
    154 
    155 int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
    156                          X509_OBJECT *ret)
    157 {
    158     if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
    159         return 0;
    160     return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0;
    161 }
    162 
    163 static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
    164 {
    165     int ret;
    166 
    167     ret = ((*a)->type - (*b)->type);
    168     if (ret)
    169         return ret;
    170     switch ((*a)->type) {
    171     case X509_LU_X509:
    172         ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
    173         break;
    174     case X509_LU_CRL:
    175         ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
    176         break;
    177     default:
    178         /* abort(); */
    179         return 0;
    180     }
    181     return ret;
    182 }
    183 
    184 X509_STORE *X509_STORE_new(void)
    185 {
    186     X509_STORE *ret;
    187 
    188     if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
    189         return NULL;
    190     OPENSSL_memset(ret, 0, sizeof(*ret));
    191     CRYPTO_MUTEX_init(&ret->objs_lock);
    192     ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
    193     if (ret->objs == NULL)
    194         goto err;
    195     ret->cache = 1;
    196     ret->get_cert_methods = sk_X509_LOOKUP_new_null();
    197     if (ret->get_cert_methods == NULL)
    198         goto err;
    199     ret->param = X509_VERIFY_PARAM_new();
    200     if (ret->param == NULL)
    201         goto err;
    202 
    203     ret->references = 1;
    204     return ret;
    205  err:
    206     if (ret) {
    207         CRYPTO_MUTEX_cleanup(&ret->objs_lock);
    208         if (ret->param)
    209             X509_VERIFY_PARAM_free(ret->param);
    210         if (ret->get_cert_methods)
    211             sk_X509_LOOKUP_free(ret->get_cert_methods);
    212         if (ret->objs)
    213             sk_X509_OBJECT_free(ret->objs);
    214         OPENSSL_free(ret);
    215     }
    216     return NULL;
    217 }
    218 
    219 int X509_STORE_up_ref(X509_STORE *store)
    220 {
    221     CRYPTO_refcount_inc(&store->references);
    222     return 1;
    223 }
    224 
    225 static void cleanup(X509_OBJECT *a)
    226 {
    227     if (a == NULL) {
    228         return;
    229     }
    230     if (a->type == X509_LU_X509) {
    231         X509_free(a->data.x509);
    232     } else if (a->type == X509_LU_CRL) {
    233         X509_CRL_free(a->data.crl);
    234     } else {
    235         /* abort(); */
    236     }
    237 
    238     OPENSSL_free(a);
    239 }
    240 
    241 void X509_STORE_free(X509_STORE *vfy)
    242 {
    243     size_t j;
    244     STACK_OF(X509_LOOKUP) *sk;
    245     X509_LOOKUP *lu;
    246 
    247     if (vfy == NULL)
    248         return;
    249 
    250     if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
    251         return;
    252     }
    253 
    254     CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
    255 
    256     sk = vfy->get_cert_methods;
    257     for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) {
    258         lu = sk_X509_LOOKUP_value(sk, j);
    259         X509_LOOKUP_shutdown(lu);
    260         X509_LOOKUP_free(lu);
    261     }
    262     sk_X509_LOOKUP_free(sk);
    263     sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
    264 
    265     if (vfy->param)
    266         X509_VERIFY_PARAM_free(vfy->param);
    267     OPENSSL_free(vfy);
    268 }
    269 
    270 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
    271 {
    272     size_t i;
    273     STACK_OF(X509_LOOKUP) *sk;
    274     X509_LOOKUP *lu;
    275 
    276     sk = v->get_cert_methods;
    277     for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
    278         lu = sk_X509_LOOKUP_value(sk, i);
    279         if (m == lu->method) {
    280             return lu;
    281         }
    282     }
    283     /* a new one */
    284     lu = X509_LOOKUP_new(m);
    285     if (lu == NULL)
    286         return NULL;
    287     else {
    288         lu->store_ctx = v;
    289         if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
    290             return lu;
    291         else {
    292             X509_LOOKUP_free(lu);
    293             return NULL;
    294         }
    295     }
    296 }
    297 
    298 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
    299                               X509_OBJECT *ret)
    300 {
    301     X509_STORE *ctx = vs->ctx;
    302     X509_LOOKUP *lu;
    303     X509_OBJECT stmp, *tmp;
    304     int i;
    305 
    306     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    307     tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
    308     CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
    309 
    310     if (tmp == NULL || type == X509_LU_CRL) {
    311         for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
    312             lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
    313             if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) {
    314                 tmp = &stmp;
    315                 break;
    316             }
    317         }
    318         if (tmp == NULL)
    319             return 0;
    320     }
    321 
    322     /*
    323      * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret);
    324      */
    325 
    326     ret->type = tmp->type;
    327     ret->data.ptr = tmp->data.ptr;
    328 
    329     X509_OBJECT_up_ref_count(ret);
    330 
    331     return 1;
    332 }
    333 
    334 int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
    335 {
    336     X509_OBJECT *obj;
    337     int ret = 1;
    338 
    339     if (x == NULL)
    340         return 0;
    341     obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    342     if (obj == NULL) {
    343         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    344         return 0;
    345     }
    346     obj->type = X509_LU_X509;
    347     obj->data.x509 = x;
    348 
    349     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    350 
    351     X509_OBJECT_up_ref_count(obj);
    352 
    353     if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
    354         X509_OBJECT_free_contents(obj);
    355         OPENSSL_free(obj);
    356         OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
    357         ret = 0;
    358     } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
    359         X509_OBJECT_free_contents(obj);
    360         OPENSSL_free(obj);
    361         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    362         ret = 0;
    363     }
    364 
    365     CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
    366 
    367     return ret;
    368 }
    369 
    370 int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
    371 {
    372     X509_OBJECT *obj;
    373     int ret = 1;
    374 
    375     if (x == NULL)
    376         return 0;
    377     obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
    378     if (obj == NULL) {
    379         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    380         return 0;
    381     }
    382     obj->type = X509_LU_CRL;
    383     obj->data.crl = x;
    384 
    385     CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
    386 
    387     X509_OBJECT_up_ref_count(obj);
    388 
    389     if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
    390         X509_OBJECT_free_contents(obj);
    391         OPENSSL_free(obj);
    392         OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
    393         ret = 0;
    394     } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
    395         X509_OBJECT_free_contents(obj);
    396         OPENSSL_free(obj);
    397         OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
    398         ret = 0;
    399     }
    400 
    401     CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
    402 
    403     return ret;
    404 }
    405 
    406 void X509_STORE_set0_additional_untrusted(X509_STORE *ctx,
    407                                           STACK_OF(X509) *untrusted) {
    408   ctx->additional_untrusted = untrusted;
    409 }
    410 
    411 int X509_OBJECT_up_ref_count(X509_OBJECT *a)
    412 {
    413     switch (a->type) {
    414     case X509_LU_X509:
    415         X509_up_ref(a->data.x509);
    416         break;
    417     case X509_LU_CRL:
    418         X509_CRL_up_ref(a->data.crl);
    419         break;
    420     }
    421     return 1;
    422 }
    423 
    424 void X509_OBJECT_free_contents(X509_OBJECT *a)
    425 {
    426     switch (a->type) {
    427     case X509_LU_X509:
    428         X509_free(a->data.x509);
    429         break;
    430     case X509_LU_CRL:
    431         X509_CRL_free(a->data.crl);
    432         break;
    433     }
    434 }
    435 
    436 int X509_OBJECT_get_type(const X509_OBJECT *a)
    437 {
    438     return a->type;
    439 }
    440 
    441 X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
    442 {
    443     if (a == NULL || a->type != X509_LU_X509) {
    444         return NULL;
    445     }
    446     return a->data.x509;
    447 }
    448 
    449 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
    450                                X509_NAME *name, int *pnmatch)
    451 {
    452     X509_OBJECT stmp;
    453     X509 x509_s;
    454     X509_CINF cinf_s;
    455     X509_CRL crl_s;
    456     X509_CRL_INFO crl_info_s;
    457 
    458     stmp.type = type;
    459     switch (type) {
    460     case X509_LU_X509:
    461         stmp.data.x509 = &x509_s;
    462         x509_s.cert_info = &cinf_s;
    463         cinf_s.subject = name;
    464         break;
    465     case X509_LU_CRL:
    466         stmp.data.crl = &crl_s;
    467         crl_s.crl = &crl_info_s;
    468         crl_info_s.issuer = name;
    469         break;
    470     default:
    471         /* abort(); */
    472         return -1;
    473     }
    474 
    475     size_t idx;
    476     if (!sk_X509_OBJECT_find(h, &idx, &stmp))
    477         return -1;
    478 
    479     if (pnmatch != NULL) {
    480         int tidx;
    481         const X509_OBJECT *tobj, *pstmp;
    482         *pnmatch = 1;
    483         pstmp = &stmp;
    484         for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) {
    485             tobj = sk_X509_OBJECT_value(h, tidx);
    486             if (x509_object_cmp(&tobj, &pstmp))
    487                 break;
    488             (*pnmatch)++;
    489         }
    490     }
    491 
    492     return idx;
    493 }
    494 
    495 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
    496                                X509_NAME *name)
    497 {
    498     return x509_object_idx_cnt(h, type, name, NULL);
    499 }
    500 
    501 X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
    502                                              int type, X509_NAME *name)
    503 {
    504     int idx;
    505     idx = X509_OBJECT_idx_by_subject(h, type, name);
    506     if (idx == -1)
    507         return NULL;
    508     return sk_X509_OBJECT_value(h, idx);
    509 }
    510 
    511 STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st)
    512 {
    513     return st->objs;
    514 }
    515 
    516 STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
    517 {
    518     int i, idx, cnt;
    519     STACK_OF(X509) *sk;
    520     X509 *x;
    521     X509_OBJECT *obj;
    522     sk = sk_X509_new_null();
    523     if (sk == NULL)
    524         return NULL;
    525     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    526     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
    527     if (idx < 0) {
    528         /*
    529          * Nothing found in cache: do lookup to possibly add new objects to
    530          * cache
    531          */
    532         X509_OBJECT xobj;
    533         CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    534         if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
    535             sk_X509_free(sk);
    536             return NULL;
    537         }
    538         X509_OBJECT_free_contents(&xobj);
    539         CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    540         idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
    541         if (idx < 0) {
    542             CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    543             sk_X509_free(sk);
    544             return NULL;
    545         }
    546     }
    547     for (i = 0; i < cnt; i++, idx++) {
    548         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
    549         x = obj->data.x509;
    550         if (!sk_X509_push(sk, x)) {
    551             CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    552             sk_X509_pop_free(sk, X509_free);
    553             return NULL;
    554         }
    555         X509_up_ref(x);
    556     }
    557     CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    558     return sk;
    559 
    560 }
    561 
    562 STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
    563 {
    564     int i, idx, cnt;
    565     STACK_OF(X509_CRL) *sk;
    566     X509_CRL *x;
    567     X509_OBJECT *obj, xobj;
    568     sk = sk_X509_CRL_new_null();
    569     if (sk == NULL)
    570         return NULL;
    571 
    572     /* Always do lookup to possibly add new CRLs to cache. */
    573     if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
    574         sk_X509_CRL_free(sk);
    575         return NULL;
    576     }
    577     X509_OBJECT_free_contents(&xobj);
    578     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    579     idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
    580     if (idx < 0) {
    581         CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    582         sk_X509_CRL_free(sk);
    583         return NULL;
    584     }
    585 
    586     for (i = 0; i < cnt; i++, idx++) {
    587         obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
    588         x = obj->data.crl;
    589         X509_CRL_up_ref(x);
    590         if (!sk_X509_CRL_push(sk, x)) {
    591             CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    592             X509_CRL_free(x);
    593             sk_X509_CRL_pop_free(sk, X509_CRL_free);
    594             return NULL;
    595         }
    596     }
    597     CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    598     return sk;
    599 }
    600 
    601 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
    602                                         X509_OBJECT *x)
    603 {
    604     size_t idx, i;
    605     X509_OBJECT *obj;
    606 
    607     if (!sk_X509_OBJECT_find(h, &idx, x)) {
    608         return NULL;
    609     }
    610     if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
    611         return sk_X509_OBJECT_value(h, idx);
    612     for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
    613         obj = sk_X509_OBJECT_value(h, i);
    614         if (x509_object_cmp
    615             ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
    616             return NULL;
    617         if (x->type == X509_LU_X509) {
    618             if (!X509_cmp(obj->data.x509, x->data.x509))
    619                 return obj;
    620         } else if (x->type == X509_LU_CRL) {
    621             if (!X509_CRL_match(obj->data.crl, x->data.crl))
    622                 return obj;
    623         } else
    624             return obj;
    625     }
    626     return NULL;
    627 }
    628 
    629 /*
    630  * Try to get issuer certificate from store. Due to limitations of the API
    631  * this can only retrieve a single certificate matching a given subject name.
    632  * However it will fill the cache with all matching certificates, so we can
    633  * examine the cache for all matches. Return values are: 1 lookup
    634  * successful.  0 certificate not found. -1 some other error.
    635  */
    636 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
    637 {
    638     X509_NAME *xn;
    639     X509_OBJECT obj, *pobj;
    640     int idx, ret;
    641     size_t i;
    642     xn = X509_get_issuer_name(x);
    643     if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj))
    644         return 0;
    645     /* If certificate matches all OK */
    646     if (ctx->check_issued(ctx, x, obj.data.x509)) {
    647         *issuer = obj.data.x509;
    648         return 1;
    649     }
    650     X509_OBJECT_free_contents(&obj);
    651 
    652     /* Else find index of first cert accepted by 'check_issued' */
    653     ret = 0;
    654     CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
    655     idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
    656     if (idx != -1) {            /* should be true as we've had at least one
    657                                  * match */
    658         /* Look through all matching certs for suitable issuer */
    659         for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
    660             pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
    661             /* See if we've run past the matches */
    662             if (pobj->type != X509_LU_X509)
    663                 break;
    664             if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
    665                 break;
    666             if (ctx->check_issued(ctx, x, pobj->data.x509)) {
    667                 *issuer = pobj->data.x509;
    668                 X509_OBJECT_up_ref_count(pobj);
    669                 ret = 1;
    670                 break;
    671             }
    672         }
    673     }
    674     CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
    675     return ret;
    676 }
    677 
    678 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
    679 {
    680     return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
    681 }
    682 
    683 int X509_STORE_set_depth(X509_STORE *ctx, int depth)
    684 {
    685     X509_VERIFY_PARAM_set_depth(ctx->param, depth);
    686     return 1;
    687 }
    688 
    689 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
    690 {
    691     return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
    692 }
    693 
    694 int X509_STORE_set_trust(X509_STORE *ctx, int trust)
    695 {
    696     return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
    697 }
    698 
    699 int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
    700 {
    701     return X509_VERIFY_PARAM_set1(ctx->param, param);
    702 }
    703 
    704 X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
    705 {
    706     return ctx->param;
    707 }
    708 
    709 void X509_STORE_set_verify_cb(X509_STORE *ctx,
    710                               int (*verify_cb) (int, X509_STORE_CTX *))
    711 {
    712     ctx->verify_cb = verify_cb;
    713 }
    714 
    715 void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
    716                                    STACK_OF (X509_CRL) *
    717                                    (*cb) (X509_STORE_CTX *ctx, X509_NAME *nm))
    718 {
    719     ctx->lookup_crls = cb;
    720 }
    721 
    722 X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
    723 {
    724     return ctx->ctx;
    725 }
    726