xref: /openbsd-src/lib/libcrypto/x509/x509_vpm.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /* $OpenBSD: x509_vpm.c,v 1.32 2022/11/26 16:08:55 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2004.
4  */
5 /* ====================================================================
6  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <stdio.h>
60 #include <string.h>
61 
62 #include <openssl/buffer.h>
63 #include <openssl/crypto.h>
64 #include <openssl/lhash.h>
65 #include <openssl/stack.h>
66 #include <openssl/x509.h>
67 #include <openssl/x509v3.h>
68 
69 #include "vpm_int.h"
70 #include "x509_local.h"
71 
72 /* X509_VERIFY_PARAM functions */
73 
74 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
75     size_t emaillen);
76 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
77     size_t iplen);
78 
79 #define SET_HOST 0
80 #define ADD_HOST 1
81 
82 static void
83 str_free(char *s)
84 {
85     free(s);
86 }
87 
88 #define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
89 
90 
91 /*
92  * Post 1.0.1 sk function "deep_copy".  For the moment we simply make
93  * these take void * and use them directly without a glorious blob of
94  * obfuscating macros of dubious value in front of them. All this in
95  * preparation for a rototilling of safestack.h (likely inspired by
96  * this).
97  */
98 static void *
99 sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
100 {
101 	_STACK *sk = sk_void;
102 	void *(*copy_func)(void *) = copy_func_void;
103 	void (*free_func)(void *) = free_func_void;
104 	_STACK *ret = sk_dup(sk);
105 	size_t i;
106 
107 	if (ret == NULL)
108 		return NULL;
109 
110 	for (i = 0; i < ret->num; i++) {
111 		if (ret->data[i] == NULL)
112 			continue;
113 		ret->data[i] = copy_func(ret->data[i]);
114 		if (ret->data[i] == NULL) {
115 			size_t j;
116 			for (j = 0; j < i; j++) {
117 				if (ret->data[j] != NULL)
118 					free_func(ret->data[j]);
119 			}
120 			sk_free(ret);
121 			return NULL;
122 		}
123 	}
124 
125 	return ret;
126 }
127 
128 static int
129 x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID *id, int mode,
130     const char *name, size_t namelen)
131 {
132 	char *copy;
133 
134 	if (name != NULL && namelen == 0)
135 		namelen = strlen(name);
136 	/*
137 	 * Refuse names with embedded NUL bytes.
138 	 */
139 	if (name && memchr(name, '\0', namelen))
140 		return 0;
141 
142 	if (mode == SET_HOST && id->hosts) {
143 		string_stack_free(id->hosts);
144 		id->hosts = NULL;
145 	}
146 	if (name == NULL || namelen == 0)
147 		return 1;
148 	copy = strndup(name, namelen);
149 	if (copy == NULL)
150 		return 0;
151 
152 	if (id->hosts == NULL &&
153 	    (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
154 		free(copy);
155 		return 0;
156 	}
157 
158 	if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
159 		free(copy);
160 		if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
161 			sk_OPENSSL_STRING_free(id->hosts);
162 			id->hosts = NULL;
163 		}
164 		return 0;
165 	}
166 
167 	return 1;
168 }
169 
170 static void
171 x509_verify_param_zero(X509_VERIFY_PARAM *param)
172 {
173 	X509_VERIFY_PARAM_ID *paramid;
174 	if (!param)
175 		return;
176 	free(param->name);
177 	param->name = NULL;
178 	param->purpose = 0;
179 	param->trust = 0;
180 	/*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
181 	param->inh_flags = 0;
182 	param->flags = 0;
183 	param->depth = -1;
184 	if (param->policies) {
185 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
186 		param->policies = NULL;
187 	}
188 	paramid = param->id;
189 	if (paramid->hosts) {
190 		string_stack_free(paramid->hosts);
191 		paramid->hosts = NULL;
192 	}
193 	free(paramid->peername);
194 	paramid->peername = NULL;
195 	free(paramid->email);
196 	paramid->email = NULL;
197 	paramid->emaillen = 0;
198 	free(paramid->ip);
199 	paramid->ip = NULL;
200 	paramid->iplen = 0;
201 	paramid->poisoned = 0;
202 }
203 
204 X509_VERIFY_PARAM *
205 X509_VERIFY_PARAM_new(void)
206 {
207 	X509_VERIFY_PARAM *param;
208 	X509_VERIFY_PARAM_ID *paramid;
209 	param = calloc(1, sizeof(X509_VERIFY_PARAM));
210 	if (param == NULL)
211 		return NULL;
212 	paramid = calloc(1, sizeof(X509_VERIFY_PARAM_ID));
213 	if (paramid == NULL) {
214 		free(param);
215 		return NULL;
216 	}
217 	param->id = paramid;
218 	x509_verify_param_zero(param);
219 	return param;
220 }
221 LCRYPTO_ALIAS(X509_VERIFY_PARAM_new)
222 
223 void
224 X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
225 {
226 	if (param == NULL)
227 		return;
228 	x509_verify_param_zero(param);
229 	free(param->id);
230 	free(param);
231 }
232 LCRYPTO_ALIAS(X509_VERIFY_PARAM_free)
233 
234 /*
235  * This function determines how parameters are "inherited" from one structure
236  * to another. There are several different ways this can happen.
237  *
238  * 1. If a child structure needs to have its values initialized from a parent
239  *    they are simply copied across. For example SSL_CTX copied to SSL.
240  * 2. If the structure should take on values only if they are currently unset.
241  *    For example the values in an SSL structure will take appropriate value
242  *    for SSL servers or clients but only if the application has not set new
243  *    ones.
244  *
245  * The "inh_flags" field determines how this function behaves.
246  *
247  * Normally any values which are set in the default are not copied from the
248  * destination and verify flags are ORed together.
249  *
250  * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
251  * to the destination. Effectively the values in "to" become default values
252  * which will be used only if nothing new is set in "from".
253  *
254  * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
255  * they are set or not. Flags is still Ored though.
256  *
257  * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
258  * of ORed.
259  *
260  * If X509_VP_FLAG_LOCKED is set then no values are copied.
261  *
262  * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
263  * after the next call.
264  */
265 
266 /* Macro to test if a field should be copied from src to dest */
267 
268 #define test_x509_verify_param_copy(field, def) \
269 	(to_overwrite || \
270 		((src->field != def) && (to_default || (dest->field == def))))
271 
272 /* As above but for ID fields */
273 
274 #define test_x509_verify_param_copy_id(idf, def) \
275 	test_x509_verify_param_copy(id->idf, def)
276 
277 /* Macro to test and copy a field if necessary */
278 
279 #define x509_verify_param_copy(field, def) \
280 	if (test_x509_verify_param_copy(field, def)) \
281 		dest->field = src->field
282 
283 int
284 X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, const X509_VERIFY_PARAM *src)
285 {
286 	unsigned long inh_flags;
287 	int to_default, to_overwrite;
288 	X509_VERIFY_PARAM_ID *id;
289 
290 	if (!src)
291 		return 1;
292 	id = src->id;
293 	inh_flags = dest->inh_flags | src->inh_flags;
294 
295 	if (inh_flags & X509_VP_FLAG_ONCE)
296 		dest->inh_flags = 0;
297 
298 	if (inh_flags & X509_VP_FLAG_LOCKED)
299 		return 1;
300 
301 	if (inh_flags & X509_VP_FLAG_DEFAULT)
302 		to_default = 1;
303 	else
304 		to_default = 0;
305 
306 	if (inh_flags & X509_VP_FLAG_OVERWRITE)
307 		to_overwrite = 1;
308 	else
309 		to_overwrite = 0;
310 
311 	x509_verify_param_copy(purpose, 0);
312 	x509_verify_param_copy(trust, 0);
313 	x509_verify_param_copy(depth, -1);
314 
315 	/* If overwrite or check time not set, copy across */
316 
317 	if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
318 		dest->check_time = src->check_time;
319 		dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
320 		/* Don't need to copy flag: that is done below */
321 	}
322 
323 	if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
324 		dest->flags = 0;
325 
326 	dest->flags |= src->flags;
327 
328 	if (test_x509_verify_param_copy(policies, NULL)) {
329 		if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
330 			return 0;
331 	}
332 
333 	/* Copy the host flags if and only if we're copying the host list */
334 	if (test_x509_verify_param_copy_id(hosts, NULL)) {
335 		if (dest->id->hosts) {
336 			string_stack_free(dest->id->hosts);
337 			dest->id->hosts = NULL;
338 		}
339 		if (id->hosts) {
340 			dest->id->hosts =
341 			    sk_deep_copy(id->hosts, strdup, str_free);
342 			if (dest->id->hosts == NULL)
343 				return 0;
344 			dest->id->hostflags = id->hostflags;
345 		}
346 	}
347 
348 	if (test_x509_verify_param_copy_id(email, NULL)) {
349 		if (!X509_VERIFY_PARAM_set1_email(dest, id->email,
350 		    id->emaillen))
351 			return 0;
352 	}
353 
354 	if (test_x509_verify_param_copy_id(ip, NULL)) {
355 		if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
356 			return 0;
357 	}
358 
359 	return 1;
360 }
361 LCRYPTO_ALIAS(X509_VERIFY_PARAM_inherit)
362 
363 int
364 X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
365 {
366 	unsigned long save_flags = to->inh_flags;
367 	int ret;
368 
369 	to->inh_flags |= X509_VP_FLAG_DEFAULT;
370 	ret = X509_VERIFY_PARAM_inherit(to, from);
371 	to->inh_flags = save_flags;
372 	return ret;
373 }
374 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1)
375 
376 static int
377 x509_param_set1_internal(char **pdest, size_t *pdestlen,  const char *src,
378     size_t srclen, int nonul)
379 {
380 	char *tmp;
381 
382 	if (src == NULL)
383 		return 0;
384 
385 	if (srclen == 0) {
386 		srclen = strlen(src);
387 		if (srclen == 0)
388 			return 0;
389 		if ((tmp = strdup(src)) == NULL)
390 			return 0;
391 	} else {
392 		if (nonul && memchr(src, '\0', srclen))
393 			return 0;
394 		if ((tmp = malloc(srclen)) == NULL)
395 			return 0;
396 		memcpy(tmp, src, srclen);
397 	}
398 
399 	if (*pdest)
400 		free(*pdest);
401 	*pdest = tmp;
402 	if (pdestlen)
403 		*pdestlen = srclen;
404 	return 1;
405 }
406 
407 int
408 X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
409 {
410 	free(param->name);
411 	param->name = NULL;
412 	if (name == NULL)
413 		return 1;
414 	param->name = strdup(name);
415 	if (param->name)
416 		return 1;
417 	return 0;
418 }
419 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_name)
420 
421 int
422 X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
423 {
424 	param->flags |= flags;
425 	if (flags & X509_V_FLAG_POLICY_MASK)
426 		param->flags |= X509_V_FLAG_POLICY_CHECK;
427 	return 1;
428 }
429 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_flags)
430 
431 int
432 X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
433 {
434 	param->flags &= ~flags;
435 	return 1;
436 }
437 LCRYPTO_ALIAS(X509_VERIFY_PARAM_clear_flags)
438 
439 unsigned long
440 X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
441 {
442 	return param->flags;
443 }
444 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_flags)
445 
446 int
447 X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
448 {
449 	return X509_PURPOSE_set(&param->purpose, purpose);
450 }
451 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_purpose)
452 
453 int
454 X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
455 {
456 	return X509_TRUST_set(&param->trust, trust);
457 }
458 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_trust)
459 
460 void
461 X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
462 {
463 	param->depth = depth;
464 }
465 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_depth)
466 
467 void
468 X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
469 {
470 	param->security_level = auth_level;
471 }
472 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_auth_level)
473 
474 time_t
475 X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
476 {
477 	return param->check_time;
478 }
479 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_time)
480 
481 void
482 X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
483 {
484 	param->check_time = t;
485 	param->flags |= X509_V_FLAG_USE_CHECK_TIME;
486 }
487 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_time)
488 
489 int
490 X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
491 {
492 	if (!param->policies) {
493 		param->policies = sk_ASN1_OBJECT_new_null();
494 		if (!param->policies)
495 			return 0;
496 	}
497 	if (!sk_ASN1_OBJECT_push(param->policies, policy))
498 		return 0;
499 	return 1;
500 }
501 LCRYPTO_ALIAS(X509_VERIFY_PARAM_add0_policy)
502 
503 int
504 X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
505     STACK_OF(ASN1_OBJECT) *policies)
506 {
507 	int i;
508 	ASN1_OBJECT *oid, *doid;
509 
510 	if (!param)
511 		return 0;
512 	if (param->policies)
513 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
514 
515 	if (!policies) {
516 		param->policies = NULL;
517 		return 1;
518 	}
519 
520 	param->policies = sk_ASN1_OBJECT_new_null();
521 	if (!param->policies)
522 		return 0;
523 
524 	for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
525 		oid = sk_ASN1_OBJECT_value(policies, i);
526 		doid = OBJ_dup(oid);
527 		if (!doid)
528 			return 0;
529 		if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
530 			ASN1_OBJECT_free(doid);
531 			return 0;
532 		}
533 	}
534 	param->flags |= X509_V_FLAG_POLICY_CHECK;
535 	return 1;
536 }
537 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_policies)
538 
539 int
540 X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
541     const char *name, size_t namelen)
542 {
543 	if (x509_param_set_hosts_internal(param->id, SET_HOST, name, namelen))
544 		return 1;
545 	param->id->poisoned = 1;
546 	return 0;
547 }
548 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_host)
549 
550 int
551 X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
552     const char *name, size_t namelen)
553 {
554 	if (x509_param_set_hosts_internal(param->id, ADD_HOST, name, namelen))
555 		return 1;
556 	param->id->poisoned = 1;
557 	return 0;
558 }
559 LCRYPTO_ALIAS(X509_VERIFY_PARAM_add1_host)
560 
561 void
562 X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags)
563 {
564 	param->id->hostflags = flags;
565 }
566 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_hostflags)
567 
568 char *
569 X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
570 {
571 	return param->id->peername;
572 }
573 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0_peername)
574 
575 int
576 X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,  const char *email,
577     size_t emaillen)
578 {
579 	if (x509_param_set1_internal(&param->id->email, &param->id->emaillen,
580 	    email, emaillen, 1))
581 		return 1;
582 	param->id->poisoned = 1;
583 	return 0;
584 }
585 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_email)
586 
587 int
588 X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
589     size_t iplen)
590 {
591 	if (iplen != 4 && iplen != 16)
592 		goto err;
593 	if (x509_param_set1_internal((char **)&param->id->ip, &param->id->iplen,
594 		(char *)ip, iplen, 0))
595 		return 1;
596  err:
597 	param->id->poisoned = 1;
598 	return 0;
599 }
600 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_ip)
601 
602 int
603 X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
604 {
605 	unsigned char ipout[16];
606 	size_t iplen;
607 
608 	iplen = (size_t)a2i_ipadd(ipout, ipasc);
609 	return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
610 }
611 LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_ip_asc)
612 
613 int
614 X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
615 {
616 	return param->depth;
617 }
618 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_depth)
619 
620 const char *
621 X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
622 {
623 	return param->name;
624 }
625 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0_name)
626 
627 static const X509_VERIFY_PARAM_ID _empty_id = { NULL };
628 
629 #define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
630 
631 /*
632  * Default verify parameters: these are used for various applications and can
633  * be overridden by the user specified table.
634  */
635 
636 static const X509_VERIFY_PARAM default_table[] = {
637 	{
638 		.name = "default",
639 		.flags = X509_V_FLAG_TRUSTED_FIRST,
640 		.depth = 100,
641 		.trust = 0,  /* XXX This is not the default trust value */
642 		.id = vpm_empty_id
643 	},
644 	{
645 		.name = "pkcs7",
646 		.purpose = X509_PURPOSE_SMIME_SIGN,
647 		.trust = X509_TRUST_EMAIL,
648 		.depth = -1,
649 		.id = vpm_empty_id
650 	},
651 	{
652 		.name = "smime_sign",
653 		.purpose = X509_PURPOSE_SMIME_SIGN,
654 		.trust = X509_TRUST_EMAIL,
655 		.depth =  -1,
656 		.id = vpm_empty_id
657 	},
658 	{
659 		.name = "ssl_client",
660 		.purpose = X509_PURPOSE_SSL_CLIENT,
661 		.trust = X509_TRUST_SSL_CLIENT,
662 		.depth = -1,
663 		.id = vpm_empty_id
664 	},
665 	{
666 		.name = "ssl_server",
667 		.purpose = X509_PURPOSE_SSL_SERVER,
668 		.trust = X509_TRUST_SSL_SERVER,
669 		.depth = -1,
670 		.id = vpm_empty_id
671 	}
672 };
673 
674 static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
675 
676 static int
677 param_cmp(const X509_VERIFY_PARAM * const *a,
678     const X509_VERIFY_PARAM * const *b)
679 {
680 	return strcmp((*a)->name, (*b)->name);
681 }
682 
683 int
684 X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
685 {
686 	X509_VERIFY_PARAM *ptmp;
687 	if (!param_table) {
688 		param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
689 		if (!param_table)
690 			return 0;
691 	} else {
692 		size_t idx;
693 
694 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param))
695 		    != -1) {
696 			ptmp = sk_X509_VERIFY_PARAM_value(param_table,
697 			    idx);
698 			X509_VERIFY_PARAM_free(ptmp);
699 			(void)sk_X509_VERIFY_PARAM_delete(param_table,
700 			    idx);
701 		}
702 	}
703 	if (!sk_X509_VERIFY_PARAM_push(param_table, param))
704 		return 0;
705 	return 1;
706 }
707 LCRYPTO_ALIAS(X509_VERIFY_PARAM_add0_table)
708 
709 int
710 X509_VERIFY_PARAM_get_count(void)
711 {
712 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
713 	if (param_table)
714 		num += sk_X509_VERIFY_PARAM_num(param_table);
715 	return num;
716 }
717 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_count)
718 
719 const X509_VERIFY_PARAM *
720 X509_VERIFY_PARAM_get0(int id)
721 {
722 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
723 	if (id < num)
724 		return default_table + id;
725 	return sk_X509_VERIFY_PARAM_value(param_table, id - num);
726 }
727 LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0)
728 
729 const X509_VERIFY_PARAM *
730 X509_VERIFY_PARAM_lookup(const char *name)
731 {
732 	X509_VERIFY_PARAM pm;
733 	unsigned int i, limit;
734 
735 	pm.name = (char *)name;
736 	if (param_table) {
737 		size_t idx;
738 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1)
739 			return sk_X509_VERIFY_PARAM_value(param_table, idx);
740 	}
741 
742 	limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
743 	for (i = 0; i < limit; i++) {
744 		if (strcmp(default_table[i].name, name) == 0) {
745 			return &default_table[i];
746 		}
747 	}
748 	return NULL;
749 }
750 LCRYPTO_ALIAS(X509_VERIFY_PARAM_lookup)
751 
752 void
753 X509_VERIFY_PARAM_table_cleanup(void)
754 {
755 	if (param_table)
756 		sk_X509_VERIFY_PARAM_pop_free(param_table,
757 		    X509_VERIFY_PARAM_free);
758 	param_table = NULL;
759 }
760 LCRYPTO_ALIAS(X509_VERIFY_PARAM_table_cleanup)
761