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