1 /* $OpenBSD: x509_lu.c,v 1.55 2022/01/14 07:53:45 tb Exp $ */
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 <string.h>
61 
62 #include <openssl/err.h>
63 #include <openssl/lhash.h>
64 #include <openssl/x509.h>
65 #include <openssl/x509v3.h>
66 #include "x509_lcl.h"
67 
68 X509_LOOKUP *
69 X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
70 {
71 	X509_LOOKUP *lu;
72 
73 	if ((lu = calloc(1, sizeof(*lu))) == NULL) {
74 		X509error(ERR_R_MALLOC_FAILURE);
75 		return NULL;
76 	}
77 
78 	lu->method = method;
79 
80 	if (method->new_item != NULL && !method->new_item(lu)) {
81 		free(lu);
82 		return NULL;
83 	}
84 
85 	return lu;
86 }
87 
88 void
89 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 	free(ctx);
96 }
97 
98 int
99 X509_LOOKUP_init(X509_LOOKUP *ctx)
100 {
101 	if (ctx->method == NULL)
102 		return 0;
103 	if (ctx->method->init == NULL)
104 		return 1;
105 	return ctx->method->init(ctx);
106 }
107 
108 int
109 X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
110 {
111 	if (ctx->method == NULL)
112 		return 0;
113 	if (ctx->method->shutdown == NULL)
114 		return 1;
115 	return ctx->method->shutdown(ctx);
116 }
117 
118 int
119 X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
120     char **ret)
121 {
122 	if (ctx->method == NULL)
123 		return -1;
124 	if (ctx->method->ctrl == NULL)
125 		return 1;
126 	return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
127 }
128 
129 int
130 X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, X509_NAME *name,
131     X509_OBJECT *ret)
132 {
133 	if (ctx->method == NULL || ctx->method->get_by_subject == NULL)
134 		return 0;
135 	return ctx->method->get_by_subject(ctx, type, name, ret);
136 }
137 
138 int
139 X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
140     X509_NAME *name, 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);
145 }
146 
147 int
148 X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
149     const unsigned char *bytes, int len, 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);
154 }
155 
156 int
157 X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, const char *str,
158     int len, X509_OBJECT *ret)
159 {
160 	if (ctx->method == NULL || ctx->method->get_by_alias == NULL)
161 		return 0;
162 	return ctx->method->get_by_alias(ctx, type, str, len, ret);
163 }
164 
165 static int
166 x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b)
167 {
168 	int ret;
169 
170 	if ((ret = (*a)->type - (*b)->type) != 0)
171 		return ret;
172 
173 	switch ((*a)->type) {
174 	case X509_LU_X509:
175 		return X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
176 	case X509_LU_CRL:
177 		return X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
178 	}
179 	return 0;
180 }
181 
182 X509_STORE *
183 X509_STORE_new(void)
184 {
185 	X509_STORE *store;
186 
187 	if ((store = calloc(1, sizeof(*store))) == NULL)
188 		goto err;
189 
190 	if ((store->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL)
191 		goto err;
192 	if ((store->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL)
193 		goto err;
194 	if ((store->param = X509_VERIFY_PARAM_new()) == NULL)
195 		goto err;
196 
197 	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, store,
198 	    &store->ex_data))
199 		goto err;
200 
201 	store->references = 1;
202 
203 	return store;
204 
205  err:
206 	X509error(ERR_R_MALLOC_FAILURE);
207 	X509_STORE_free(store);
208 
209 	return NULL;
210 }
211 
212 X509_OBJECT *
213 X509_OBJECT_new(void)
214 {
215 	X509_OBJECT *obj;
216 
217 	if ((obj = calloc(1, sizeof(*obj))) == NULL) {
218 		X509error(ERR_R_MALLOC_FAILURE);
219 		return NULL;
220 	}
221 
222 	obj->type = X509_LU_NONE;
223 
224 	return obj;
225 }
226 
227 void
228 X509_OBJECT_free(X509_OBJECT *a)
229 {
230 	if (a == NULL)
231 		return;
232 
233 	switch (a->type) {
234 	case X509_LU_X509:
235 		X509_free(a->data.x509);
236 		break;
237 	case X509_LU_CRL:
238 		X509_CRL_free(a->data.crl);
239 		break;
240 	}
241 
242 	free(a);
243 }
244 
245 void
246 X509_STORE_free(X509_STORE *store)
247 {
248 	STACK_OF(X509_LOOKUP) *sk;
249 	X509_LOOKUP *lu;
250 	int i;
251 
252 	if (store == NULL)
253 		return;
254 
255 	if (CRYPTO_add(&store->references, -1, CRYPTO_LOCK_X509_STORE) > 0)
256 		return;
257 
258 	sk = store->get_cert_methods;
259 	for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
260 		lu = sk_X509_LOOKUP_value(sk, i);
261 		X509_LOOKUP_shutdown(lu);
262 		X509_LOOKUP_free(lu);
263 	}
264 	sk_X509_LOOKUP_free(sk);
265 	sk_X509_OBJECT_pop_free(store->objs, X509_OBJECT_free);
266 
267 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, store, &store->ex_data);
268 	X509_VERIFY_PARAM_free(store->param);
269 	free(store);
270 }
271 
272 int
273 X509_STORE_up_ref(X509_STORE *store)
274 {
275 	return CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE) > 1;
276 }
277 
278 X509_LOOKUP *
279 X509_STORE_add_lookup(X509_STORE *store, X509_LOOKUP_METHOD *method)
280 {
281 	STACK_OF(X509_LOOKUP) *sk;
282 	X509_LOOKUP *lu;
283 	int i;
284 
285 	sk = store->get_cert_methods;
286 	for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
287 		lu = sk_X509_LOOKUP_value(sk, i);
288 		if (method == lu->method) {
289 			return lu;
290 		}
291 	}
292 
293 	if ((lu = X509_LOOKUP_new(method)) == NULL)
294 		return NULL;
295 
296 	lu->store_ctx = store;
297 	if (sk_X509_LOOKUP_push(store->get_cert_methods, lu) <= 0) {
298 		X509error(ERR_R_MALLOC_FAILURE);
299 		X509_LOOKUP_free(lu);
300 		return NULL;
301 	}
302 
303 	return lu;
304 }
305 
306 X509_OBJECT *
307 X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
308     X509_NAME *name)
309 {
310 	X509_OBJECT *obj;
311 
312 	if ((obj = X509_OBJECT_new()) == NULL)
313 		return NULL;
314 	if (!X509_STORE_CTX_get_by_subject(vs, type, name, obj)) {
315 		X509_OBJECT_free(obj);
316 		return NULL;
317 	}
318 
319 	return obj;
320 }
321 
322 int
323 X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
324     X509_NAME *name, X509_OBJECT *ret)
325 {
326 	X509_STORE *ctx = vs->store;
327 	X509_LOOKUP *lu;
328 	X509_OBJECT stmp, *tmp;
329 	int i;
330 
331 	if (ctx == NULL)
332 		return 0;
333 
334 	memset(&stmp, 0, sizeof(stmp));
335 
336 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
337 	tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
338 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
339 
340 	if (tmp == NULL || type == X509_LU_CRL) {
341 		for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
342 			lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
343 			if (X509_LOOKUP_by_subject(lu, type, name, &stmp) != 0) {
344 				tmp = &stmp;
345 				break;
346 			}
347 		}
348 		if (tmp == NULL)
349 			return 0;
350 	}
351 
352 	if (!X509_OBJECT_up_ref_count(tmp))
353 		return 0;
354 
355 	*ret = *tmp;
356 
357 	return 1;
358 }
359 
360 /* Add obj to the store. Takes ownership of obj. */
361 static int
362 X509_STORE_add_object(X509_STORE *store, X509_OBJECT *obj)
363 {
364 	int ret = 0;
365 
366 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
367 
368 	if (X509_OBJECT_retrieve_match(store->objs, obj) != NULL) {
369 		/* Object is already present in the store. That's fine. */
370 		ret = 1;
371 		goto out;
372 	}
373 
374 	if (sk_X509_OBJECT_push(store->objs, obj) <= 0) {
375 		X509error(ERR_R_MALLOC_FAILURE);
376 		goto out;
377 	}
378 
379 	obj = NULL;
380 	ret = 1;
381 
382  out:
383 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
384 	X509_OBJECT_free(obj);
385 
386 	return ret;
387 }
388 
389 int
390 X509_STORE_add_cert(X509_STORE *store, X509 *x)
391 {
392 	X509_OBJECT *obj;
393 
394 	if (x == NULL)
395 		return 0;
396 
397 	if ((obj = X509_OBJECT_new()) == NULL)
398 		return 0;
399 
400 	if (!X509_up_ref(x)) {
401 		X509_OBJECT_free(obj);
402 		return 0;
403 	}
404 
405 	obj->type = X509_LU_X509;
406 	obj->data.x509 = x;
407 
408 	return X509_STORE_add_object(store, obj);
409 }
410 
411 int
412 X509_STORE_add_crl(X509_STORE *store, X509_CRL *x)
413 {
414 	X509_OBJECT *obj;
415 
416 	if (x == NULL)
417 		return 0;
418 
419 	if ((obj = X509_OBJECT_new()) == NULL)
420 		return 0;
421 
422 	if (!X509_CRL_up_ref(x)) {
423 		X509_OBJECT_free(obj);
424 		return 0;
425 	}
426 
427 	obj->type = X509_LU_CRL;
428 	obj->data.crl = x;
429 
430 	return X509_STORE_add_object(store, obj);
431 }
432 
433 int
434 X509_OBJECT_up_ref_count(X509_OBJECT *a)
435 {
436 	switch (a->type) {
437 	case X509_LU_X509:
438 		return X509_up_ref(a->data.x509);
439 	case X509_LU_CRL:
440 		return X509_CRL_up_ref(a->data.crl);
441 	}
442 	return 1;
443 }
444 
445 X509_LOOKUP_TYPE
446 X509_OBJECT_get_type(const X509_OBJECT *a)
447 {
448 	return a->type;
449 }
450 
451 static int
452 x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
453     X509_NAME *name, int *pnmatch)
454 {
455 	X509_OBJECT stmp;
456 	X509 x509_s;
457 	X509_CINF cinf_s;
458 	X509_CRL crl_s;
459 	X509_CRL_INFO crl_info_s;
460 	int idx;
461 
462 	stmp.type = type;
463 	switch (type) {
464 	case X509_LU_X509:
465 		stmp.data.x509 = &x509_s;
466 		x509_s.cert_info = &cinf_s;
467 		cinf_s.subject = name;
468 		break;
469 	case X509_LU_CRL:
470 		stmp.data.crl = &crl_s;
471 		crl_s.crl = &crl_info_s;
472 		crl_info_s.issuer = name;
473 		break;
474 	default:
475 		return -1;
476 	}
477 
478 	idx = sk_X509_OBJECT_find(h, &stmp);
479 	if (idx >= 0 && pnmatch) {
480 		int tidx;
481 		const X509_OBJECT *tobj, *pstmp;
482 
483 		*pnmatch = 1;
484 		pstmp = &stmp;
485 		for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
486 			tobj = sk_X509_OBJECT_value(h, tidx);
487 			if (x509_object_cmp(&tobj, &pstmp))
488 				break;
489 			(*pnmatch)++;
490 		}
491 	}
492 	return idx;
493 }
494 
495 int
496 X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
497     X509_NAME *name)
498 {
499 	return x509_object_idx_cnt(h, type, name, NULL);
500 }
501 
502 X509_OBJECT *
503 X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
504     X509_NAME *name)
505 {
506 	int idx;
507 
508 	idx = X509_OBJECT_idx_by_subject(h, type, name);
509 	if (idx == -1)
510 		return NULL;
511 	return sk_X509_OBJECT_value(h, idx);
512 }
513 
514 X509 *
515 X509_OBJECT_get0_X509(const X509_OBJECT *xo)
516 {
517 	if (xo != NULL && xo->type == X509_LU_X509)
518 		return xo->data.x509;
519 	return NULL;
520 }
521 
522 X509_CRL *
523 X509_OBJECT_get0_X509_CRL(X509_OBJECT *xo)
524 {
525 	if (xo != NULL && xo->type == X509_LU_CRL)
526 		return xo->data.crl;
527 	return NULL;
528 }
529 
530 static STACK_OF(X509) *
531 X509_get1_certs_from_cache(X509_STORE *store, X509_NAME *name)
532 {
533 	STACK_OF(X509) *sk = NULL;
534 	X509 *x = NULL;
535 	X509_OBJECT *obj;
536 	int i, idx, cnt;
537 
538 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
539 
540 	idx = x509_object_idx_cnt(store->objs, X509_LU_X509, name, &cnt);
541 	if (idx < 0)
542 		goto err;
543 
544 	if ((sk = sk_X509_new_null()) == NULL)
545 		goto err;
546 
547 	for (i = 0; i < cnt; i++, idx++) {
548 		obj = sk_X509_OBJECT_value(store->objs, idx);
549 
550 		x = obj->data.x509;
551 		if (!X509_up_ref(x)) {
552 			x = NULL;
553 			goto err;
554 		}
555 		if (!sk_X509_push(sk, x))
556 			goto err;
557 	}
558 
559 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
560 
561 	return sk;
562 
563  err:
564 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
565 	sk_X509_pop_free(sk, X509_free);
566 	X509_free(x);
567 
568 	return NULL;
569 }
570 
571 STACK_OF(X509) *
572 X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *name)
573 {
574 	X509_STORE *store = ctx->store;
575 	STACK_OF(X509) *sk;
576 	X509_OBJECT *obj;
577 
578 	if (store == NULL)
579 		return NULL;
580 
581 	if ((sk = X509_get1_certs_from_cache(store, name)) != NULL)
582 		return sk;
583 
584 	/* Nothing found: do lookup to possibly add new objects to cache. */
585 	obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, name);
586 	if (obj == NULL)
587 		return NULL;
588 	X509_OBJECT_free(obj);
589 
590 	return X509_get1_certs_from_cache(store, name);
591 }
592 
593 STACK_OF(X509_CRL) *
594 X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *name)
595 {
596 	X509_STORE *store = ctx->store;
597 	STACK_OF(X509_CRL) *sk = NULL;
598 	X509_CRL *x = NULL;
599 	X509_OBJECT *obj = NULL;
600 	int i, idx, cnt;
601 
602 	if (store == NULL)
603 		return NULL;
604 
605 	/* Always do lookup to possibly add new CRLs to cache */
606 	obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_CRL, name);
607 	if (obj == NULL)
608 		return NULL;
609 
610 	X509_OBJECT_free(obj);
611 	obj = NULL;
612 
613 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
614 	idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, name, &cnt);
615 	if (idx < 0)
616 		goto err;
617 
618 	if ((sk = sk_X509_CRL_new_null()) == NULL)
619 		goto err;
620 
621 	for (i = 0; i < cnt; i++, idx++) {
622 		obj = sk_X509_OBJECT_value(store->objs, idx);
623 
624 		x = obj->data.crl;
625 		if (!X509_CRL_up_ref(x)) {
626 			x = NULL;
627 			goto err;
628 		}
629 		if (!sk_X509_CRL_push(sk, x))
630 			goto err;
631 	}
632 
633 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
634 	return sk;
635 
636  err:
637 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
638 	X509_CRL_free(x);
639 	sk_X509_CRL_pop_free(sk, X509_CRL_free);
640 	return NULL;
641 }
642 
643 X509_OBJECT *
644 X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
645 {
646 	int idx, i;
647 	X509_OBJECT *obj;
648 
649 	idx = sk_X509_OBJECT_find(h, x);
650 	if (idx == -1)
651 		return NULL;
652 	if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
653 		return sk_X509_OBJECT_value(h, idx);
654 	for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
655 		obj = sk_X509_OBJECT_value(h, i);
656 		if (x509_object_cmp((const X509_OBJECT **)&obj,
657 		    (const X509_OBJECT **)&x))
658 			return NULL;
659 		if (x->type == X509_LU_X509) {
660 			if (!X509_cmp(obj->data.x509, x->data.x509))
661 				return obj;
662 		} else if (x->type == X509_LU_CRL) {
663 			if (!X509_CRL_match(obj->data.crl, x->data.crl))
664 				return obj;
665 		} else
666 			return obj;
667 	}
668 	return NULL;
669 }
670 
671 /* Try to get issuer certificate from store. Due to limitations
672  * of the API this can only retrieve a single certificate matching
673  * a given subject name. However it will fill the cache with all
674  * matching certificates, so we can examine the cache for all
675  * matches.
676  *
677  * Return values are:
678  *  1 lookup successful.
679  *  0 certificate not found.
680  * -1 some other error.
681  */
682 int
683 X509_STORE_CTX_get1_issuer(X509 **out_issuer, X509_STORE_CTX *ctx, X509 *x)
684 {
685 	X509_NAME *xn;
686 	X509_OBJECT *obj, *pobj;
687 	X509 *issuer = NULL;
688 	int i, idx, ret;
689 
690 	*out_issuer = NULL;
691 
692 	xn = X509_get_issuer_name(x);
693 	obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, xn);
694 	if (obj == NULL)
695 		return 0;
696 
697 	if ((issuer = X509_OBJECT_get0_X509(obj)) == NULL) {
698 		X509_OBJECT_free(obj);
699 		return 0;
700 	}
701 	if (!X509_up_ref(issuer)) {
702 		X509_OBJECT_free(obj);
703 		return -1;
704 	}
705 
706 	/* If certificate matches all OK */
707 	if (ctx->check_issued(ctx, x, issuer)) {
708 		if (x509_check_cert_time(ctx, issuer, -1)) {
709 			*out_issuer = issuer;
710 			X509_OBJECT_free(obj);
711 			return 1;
712 		}
713 	}
714 	X509_free(issuer);
715 	issuer = NULL;
716 	X509_OBJECT_free(obj);
717 	obj = NULL;
718 
719 	if (ctx->store == NULL)
720 		return 0;
721 
722 	/* Else find index of first cert accepted by 'check_issued' */
723 	CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
724 	idx = X509_OBJECT_idx_by_subject(ctx->store->objs, X509_LU_X509, xn);
725 	if (idx != -1) /* should be true as we've had at least one match */ {
726 		/* Look through all matching certs for suitable issuer */
727 		for (i = idx; i < sk_X509_OBJECT_num(ctx->store->objs); i++) {
728 			pobj = sk_X509_OBJECT_value(ctx->store->objs, i);
729 			/* See if we've run past the matches */
730 			if (pobj->type != X509_LU_X509)
731 				break;
732 			if (X509_NAME_cmp(xn,
733 			    X509_get_subject_name(pobj->data.x509)))
734 				break;
735 			if (ctx->check_issued(ctx, x, pobj->data.x509)) {
736 				issuer = pobj->data.x509;
737 				/*
738 				 * If times check, exit with match,
739 				 * otherwise keep looking. Leave last
740 				 * match in issuer so we return nearest
741 				 * match if no certificate time is OK.
742 				 */
743 				if (x509_check_cert_time(ctx, issuer, -1))
744 					break;
745 			}
746 		}
747 	}
748 	ret = 0;
749 	if (issuer != NULL) {
750 		if (!X509_up_ref(issuer)) {
751 			ret = -1;
752 		} else {
753 			*out_issuer = issuer;
754 			ret = 1;
755 		}
756 	}
757 	CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
758 	return ret;
759 }
760 
761 STACK_OF(X509_OBJECT) *
762 X509_STORE_get0_objects(X509_STORE *xs)
763 {
764 	return xs->objs;
765 }
766 
767 void *
768 X509_STORE_get_ex_data(X509_STORE *xs, int idx)
769 {
770 	return CRYPTO_get_ex_data(&xs->ex_data, idx);
771 }
772 
773 int
774 X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data)
775 {
776 	return CRYPTO_set_ex_data(&xs->ex_data, idx, data);
777 }
778 
779 int
780 X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
781 {
782 	return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
783 }
784 
785 int
786 X509_STORE_set_depth(X509_STORE *ctx, int depth)
787 {
788 	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
789 	return 1;
790 }
791 
792 int
793 X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
794 {
795 	return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
796 }
797 
798 int
799 X509_STORE_set_trust(X509_STORE *ctx, int trust)
800 {
801 	return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
802 }
803 
804 int
805 X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
806 {
807 	return X509_VERIFY_PARAM_set1(ctx->param, param);
808 }
809 
810 X509_VERIFY_PARAM *
811 X509_STORE_get0_param(X509_STORE *ctx)
812 {
813 	return ctx->param;
814 }
815 
816 void
817 X509_STORE_set_verify(X509_STORE *store, X509_STORE_CTX_verify_fn verify)
818 {
819 	store->verify = verify;
820 }
821 
822 X509_STORE_CTX_verify_fn
823 X509_STORE_get_verify(X509_STORE *store)
824 {
825 	return store->verify;
826 }
827 
828 void
829 X509_STORE_set_verify_cb(X509_STORE *store, X509_STORE_CTX_verify_cb verify_cb)
830 {
831 	store->verify_cb = verify_cb;
832 }
833 
834 X509_STORE_CTX_verify_cb
835 X509_STORE_get_verify_cb(X509_STORE *store)
836 {
837 	return store->verify_cb;
838 }
839