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