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