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