xref: /openbsd/lib/libcrypto/x509/x509_vpm.c (revision 771fbea0)
1 /* $OpenBSD: x509_vpm.c,v 1.26 2021/04/24 18:10:12 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 
71 /* X509_VERIFY_PARAM functions */
72 
73 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
74     size_t emaillen);
75 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
76     size_t iplen);
77 
78 #define SET_HOST 0
79 #define ADD_HOST 1
80 
81 static void
82 str_free(char *s)
83 {
84     free(s);
85 }
86 
87 #define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
88 
89 
90 /*
91  * Post 1.0.1 sk function "deep_copy".  For the moment we simply make
92  * these take void * and use them directly without a glorious blob of
93  * obfuscating macros of dubious value in front of them. All this in
94  * preparation for a rototilling of safestack.h (likely inspired by
95  * this).
96  */
97 static void *
98 sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
99 {
100 	_STACK *sk = sk_void;
101 	void *(*copy_func)(void *) = copy_func_void;
102 	void (*free_func)(void *) = free_func_void;
103 	_STACK *ret = sk_dup(sk);
104 	size_t i;
105 
106 	if (ret == NULL)
107 		return NULL;
108 
109 	for (i = 0; i < ret->num; i++) {
110 		if (ret->data[i] == NULL)
111 			continue;
112 		ret->data[i] = copy_func(ret->data[i]);
113 		if (ret->data[i] == NULL) {
114 			size_t j;
115 			for (j = 0; j < i; j++) {
116 				if (ret->data[j] != NULL)
117 					free_func(ret->data[j]);
118 			}
119 			sk_free(ret);
120 			return NULL;
121 		}
122 	}
123 
124 	return ret;
125 }
126 
127 static int
128 x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID *id, int mode,
129     const char *name, size_t namelen)
130 {
131 	char *copy;
132 
133 	if (name != NULL && namelen == 0)
134 		namelen = strlen(name);
135 	/*
136 	 * Refuse names with embedded NUL bytes.
137 	 */
138 	if (name && memchr(name, '\0', namelen))
139 		return 0;
140 
141 	if (mode == SET_HOST && id->hosts) {
142 		string_stack_free(id->hosts);
143 		id->hosts = NULL;
144 	}
145 	if (name == NULL || namelen == 0)
146 		return 1;
147 	copy = strndup(name, namelen);
148 	if (copy == NULL)
149 		return 0;
150 
151 	if (id->hosts == NULL &&
152 	    (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
153 		free(copy);
154 		return 0;
155 	}
156 
157 	if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
158 		free(copy);
159 		if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
160 			sk_OPENSSL_STRING_free(id->hosts);
161 			id->hosts = NULL;
162 		}
163 		return 0;
164 	}
165 
166 	return 1;
167 }
168 
169 static void
170 x509_verify_param_zero(X509_VERIFY_PARAM *param)
171 {
172 	X509_VERIFY_PARAM_ID *paramid;
173 	if (!param)
174 		return;
175 	free(param->name);
176 	param->name = NULL;
177 	param->purpose = 0;
178 	param->trust = 0;
179 	/*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
180 	param->inh_flags = 0;
181 	param->flags = 0;
182 	param->depth = -1;
183 	if (param->policies) {
184 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
185 		param->policies = NULL;
186 	}
187 	paramid = param->id;
188 	if (paramid->hosts) {
189 		string_stack_free(paramid->hosts);
190 		paramid->hosts = NULL;
191 	}
192 	free(paramid->peername);
193 	paramid->peername = NULL;
194 	free(paramid->email);
195 	paramid->email = NULL;
196 	paramid->emaillen = 0;
197 	free(paramid->ip);
198 	paramid->ip = NULL;
199 	paramid->iplen = 0;
200 	paramid->poisoned = 0;
201 }
202 
203 X509_VERIFY_PARAM *
204 X509_VERIFY_PARAM_new(void)
205 {
206 	X509_VERIFY_PARAM *param;
207 	X509_VERIFY_PARAM_ID *paramid;
208 	param = calloc(1, sizeof(X509_VERIFY_PARAM));
209 	if (param == NULL)
210 		return NULL;
211 	paramid = calloc(1, sizeof(X509_VERIFY_PARAM_ID));
212 	if (paramid == NULL) {
213 		free(param);
214 		return NULL;
215 	}
216 	param->id = paramid;
217 	x509_verify_param_zero(param);
218 	return param;
219 }
220 
221 void
222 X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
223 {
224 	if (param == NULL)
225 		return;
226 	x509_verify_param_zero(param);
227 	free(param->id);
228 	free(param);
229 }
230 
231 /*
232  * This function determines how parameters are "inherited" from one structure
233  * to another. There are several different ways this can happen.
234  *
235  * 1. If a child structure needs to have its values initialized from a parent
236  *    they are simply copied across. For example SSL_CTX copied to SSL.
237  * 2. If the structure should take on values only if they are currently unset.
238  *    For example the values in an SSL structure will take appropriate value
239  *    for SSL servers or clients but only if the application has not set new
240  *    ones.
241  *
242  * The "inh_flags" field determines how this function behaves.
243  *
244  * Normally any values which are set in the default are not copied from the
245  * destination and verify flags are ORed together.
246  *
247  * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
248  * to the destination. Effectively the values in "to" become default values
249  * which will be used only if nothing new is set in "from".
250  *
251  * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
252  * they are set or not. Flags is still Ored though.
253  *
254  * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
255  * of ORed.
256  *
257  * If X509_VP_FLAG_LOCKED is set then no values are copied.
258  *
259  * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
260  * after the next call.
261  */
262 
263 /* Macro to test if a field should be copied from src to dest */
264 
265 #define test_x509_verify_param_copy(field, def) \
266 	(to_overwrite || \
267 		((src->field != def) && (to_default || (dest->field == def))))
268 
269 /* As above but for ID fields */
270 
271 #define test_x509_verify_param_copy_id(idf, def) \
272 	test_x509_verify_param_copy(id->idf, def)
273 
274 /* Macro to test and copy a field if necessary */
275 
276 #define x509_verify_param_copy(field, def) \
277 	if (test_x509_verify_param_copy(field, def)) \
278 		dest->field = src->field
279 
280 int
281 X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, const X509_VERIFY_PARAM *src)
282 {
283 	unsigned long inh_flags;
284 	int to_default, to_overwrite;
285 	X509_VERIFY_PARAM_ID *id;
286 
287 	if (!src)
288 		return 1;
289 	id = src->id;
290 	inh_flags = dest->inh_flags | src->inh_flags;
291 
292 	if (inh_flags & X509_VP_FLAG_ONCE)
293 		dest->inh_flags = 0;
294 
295 	if (inh_flags & X509_VP_FLAG_LOCKED)
296 		return 1;
297 
298 	if (inh_flags & X509_VP_FLAG_DEFAULT)
299 		to_default = 1;
300 	else
301 		to_default = 0;
302 
303 	if (inh_flags & X509_VP_FLAG_OVERWRITE)
304 		to_overwrite = 1;
305 	else
306 		to_overwrite = 0;
307 
308 	x509_verify_param_copy(purpose, 0);
309 	x509_verify_param_copy(trust, 0);
310 	x509_verify_param_copy(depth, -1);
311 
312 	/* If overwrite or check time not set, copy across */
313 
314 	if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
315 		dest->check_time = src->check_time;
316 		dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
317 		/* Don't need to copy flag: that is done below */
318 	}
319 
320 	if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
321 		dest->flags = 0;
322 
323 	dest->flags |= src->flags;
324 
325 	if (test_x509_verify_param_copy(policies, NULL)) {
326 		if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
327 			return 0;
328 	}
329 
330 	/* Copy the host flags if and only if we're copying the host list */
331 	if (test_x509_verify_param_copy_id(hosts, NULL)) {
332 		if (dest->id->hosts) {
333 			string_stack_free(dest->id->hosts);
334 			dest->id->hosts = NULL;
335 		}
336 		if (id->hosts) {
337 			dest->id->hosts =
338 			    sk_deep_copy(id->hosts, strdup, str_free);
339 			if (dest->id->hosts == NULL)
340 				return 0;
341 			dest->id->hostflags = id->hostflags;
342 		}
343 	}
344 
345 	if (test_x509_verify_param_copy_id(email, NULL)) {
346 		if (!X509_VERIFY_PARAM_set1_email(dest, id->email,
347 		    id->emaillen))
348 			return 0;
349 	}
350 
351 	if (test_x509_verify_param_copy_id(ip, NULL)) {
352 		if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
353 			return 0;
354 	}
355 
356 	return 1;
357 }
358 
359 int
360 X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
361 {
362 	unsigned long save_flags = to->inh_flags;
363 	int ret;
364 
365 	to->inh_flags |= X509_VP_FLAG_DEFAULT;
366 	ret = X509_VERIFY_PARAM_inherit(to, from);
367 	to->inh_flags = save_flags;
368 	return ret;
369 }
370 
371 static int
372 x509_param_set1_internal(char **pdest, size_t *pdestlen,  const char *src,
373     size_t srclen, int nonul)
374 {
375 	char *tmp;
376 
377 	if (src == NULL)
378 		return 0;
379 
380 	if (srclen == 0) {
381 		srclen = strlen(src);
382 		if (srclen == 0)
383 			return 0;
384 		if ((tmp = strdup(src)) == NULL)
385 			return 0;
386 	} else {
387 		if (nonul && memchr(src, '\0', srclen))
388 			return 0;
389 		if ((tmp = malloc(srclen)) == NULL)
390 			return 0;
391 		memcpy(tmp, src, srclen);
392 	}
393 
394 	if (*pdest)
395 		free(*pdest);
396 	*pdest = tmp;
397 	if (pdestlen)
398 		*pdestlen = srclen;
399 	return 1;
400 }
401 
402 int
403 X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
404 {
405 	free(param->name);
406 	param->name = NULL;
407 	if (name == NULL)
408 		return 1;
409 	param->name = strdup(name);
410 	if (param->name)
411 		return 1;
412 	return 0;
413 }
414 
415 int
416 X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
417 {
418 	param->flags |= flags;
419 	if (flags & X509_V_FLAG_POLICY_MASK)
420 		param->flags |= X509_V_FLAG_POLICY_CHECK;
421 	return 1;
422 }
423 
424 int
425 X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
426 {
427 	param->flags &= ~flags;
428 	return 1;
429 }
430 
431 unsigned long
432 X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
433 {
434 	return param->flags;
435 }
436 
437 int
438 X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
439 {
440 	return X509_PURPOSE_set(&param->purpose, purpose);
441 }
442 
443 int
444 X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
445 {
446 	return X509_TRUST_set(&param->trust, trust);
447 }
448 
449 void
450 X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
451 {
452 	param->depth = depth;
453 }
454 
455 void
456 X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
457 {
458 	param->check_time = t;
459 	param->flags |= X509_V_FLAG_USE_CHECK_TIME;
460 }
461 
462 int
463 X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
464 {
465 	if (!param->policies) {
466 		param->policies = sk_ASN1_OBJECT_new_null();
467 		if (!param->policies)
468 			return 0;
469 	}
470 	if (!sk_ASN1_OBJECT_push(param->policies, policy))
471 		return 0;
472 	return 1;
473 }
474 
475 int
476 X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
477     STACK_OF(ASN1_OBJECT) *policies)
478 {
479 	int i;
480 	ASN1_OBJECT *oid, *doid;
481 
482 	if (!param)
483 		return 0;
484 	if (param->policies)
485 		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
486 
487 	if (!policies) {
488 		param->policies = NULL;
489 		return 1;
490 	}
491 
492 	param->policies = sk_ASN1_OBJECT_new_null();
493 	if (!param->policies)
494 		return 0;
495 
496 	for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
497 		oid = sk_ASN1_OBJECT_value(policies, i);
498 		doid = OBJ_dup(oid);
499 		if (!doid)
500 			return 0;
501 		if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
502 			ASN1_OBJECT_free(doid);
503 			return 0;
504 		}
505 	}
506 	param->flags |= X509_V_FLAG_POLICY_CHECK;
507 	return 1;
508 }
509 
510 int
511 X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
512     const char *name, size_t namelen)
513 {
514 	if (x509_param_set_hosts_internal(param->id, SET_HOST, name, namelen))
515 		return 1;
516 	param->id->poisoned = 1;
517 	return 0;
518 }
519 
520 int
521 X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
522     const char *name, size_t namelen)
523 {
524 	if (x509_param_set_hosts_internal(param->id, ADD_HOST, name, namelen))
525 		return 1;
526 	param->id->poisoned = 1;
527 	return 0;
528 }
529 
530 void
531 X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags)
532 {
533 	param->id->hostflags = flags;
534 }
535 
536 char *
537 X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
538 {
539 	return param->id->peername;
540 }
541 
542 int
543 X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,  const char *email,
544     size_t emaillen)
545 {
546 	if (x509_param_set1_internal(&param->id->email, &param->id->emaillen,
547 	    email, emaillen, 1))
548 		return 1;
549 	param->id->poisoned = 1;
550 	return 0;
551 }
552 
553 int
554 X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
555     size_t iplen)
556 {
557 	if (iplen != 4 && iplen != 16)
558 		goto err;
559 	if (x509_param_set1_internal((char **)&param->id->ip, &param->id->iplen,
560 		(char *)ip, iplen, 0))
561 		return 1;
562  err:
563 	param->id->poisoned = 1;
564 	return 0;
565 }
566 
567 int
568 X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
569 {
570 	unsigned char ipout[16];
571 	size_t iplen;
572 
573 	iplen = (size_t)a2i_ipadd(ipout, ipasc);
574 	return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
575 }
576 
577 int
578 X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
579 {
580 	return param->depth;
581 }
582 
583 const char *
584 X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
585 {
586 	return param->name;
587 }
588 
589 static const X509_VERIFY_PARAM_ID _empty_id = { NULL };
590 
591 #define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
592 
593 /*
594  * Default verify parameters: these are used for various applications and can
595  * be overridden by the user specified table.
596  */
597 
598 static const X509_VERIFY_PARAM default_table[] = {
599 	{
600 		.name = "default",
601 		.depth = 100,
602 		.trust = 0,  /* XXX This is not the default trust value */
603 		.id = vpm_empty_id
604 	},
605 	{
606 		.name = "pkcs7",
607 		.purpose = X509_PURPOSE_SMIME_SIGN,
608 		.trust = X509_TRUST_EMAIL,
609 		.depth = -1,
610 		.id = vpm_empty_id
611 	},
612 	{
613 		.name = "smime_sign",
614 		.purpose = X509_PURPOSE_SMIME_SIGN,
615 		.trust = X509_TRUST_EMAIL,
616 		.depth =  -1,
617 		.id = vpm_empty_id
618 	},
619 	{
620 		.name = "ssl_client",
621 		.purpose = X509_PURPOSE_SSL_CLIENT,
622 		.trust = X509_TRUST_SSL_CLIENT,
623 		.depth = -1,
624 		.id = vpm_empty_id
625 	},
626 	{
627 		.name = "ssl_server",
628 		.purpose = X509_PURPOSE_SSL_SERVER,
629 		.trust = X509_TRUST_SSL_SERVER,
630 		.depth = -1,
631 		.id = vpm_empty_id
632 	}
633 };
634 
635 static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
636 
637 static int
638 param_cmp(const X509_VERIFY_PARAM * const *a,
639     const X509_VERIFY_PARAM * const *b)
640 {
641 	return strcmp((*a)->name, (*b)->name);
642 }
643 
644 int
645 X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
646 {
647 	X509_VERIFY_PARAM *ptmp;
648 	if (!param_table) {
649 		param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
650 		if (!param_table)
651 			return 0;
652 	} else {
653 		size_t idx;
654 
655 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param))
656 		    != -1) {
657 			ptmp = sk_X509_VERIFY_PARAM_value(param_table,
658 			    idx);
659 			X509_VERIFY_PARAM_free(ptmp);
660 			(void)sk_X509_VERIFY_PARAM_delete(param_table,
661 			    idx);
662 		}
663 	}
664 	if (!sk_X509_VERIFY_PARAM_push(param_table, param))
665 		return 0;
666 	return 1;
667 }
668 
669 int
670 X509_VERIFY_PARAM_get_count(void)
671 {
672 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
673 	if (param_table)
674 		num += sk_X509_VERIFY_PARAM_num(param_table);
675 	return num;
676 }
677 
678 const X509_VERIFY_PARAM *
679 X509_VERIFY_PARAM_get0(int id)
680 {
681 	int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
682 	if (id < num)
683 		return default_table + id;
684 	return sk_X509_VERIFY_PARAM_value(param_table, id - num);
685 }
686 
687 const X509_VERIFY_PARAM *
688 X509_VERIFY_PARAM_lookup(const char *name)
689 {
690 	X509_VERIFY_PARAM pm;
691 	unsigned int i, limit;
692 
693 	pm.name = (char *)name;
694 	if (param_table) {
695 		size_t idx;
696 		if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1)
697 			return sk_X509_VERIFY_PARAM_value(param_table, idx);
698 	}
699 
700 	limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
701 	for (i = 0; i < limit; i++) {
702 		if (strcmp(default_table[i].name, name) == 0) {
703 			return &default_table[i];
704 		}
705 	}
706 	return NULL;
707 }
708 
709 void
710 X509_VERIFY_PARAM_table_cleanup(void)
711 {
712 	if (param_table)
713 		sk_X509_VERIFY_PARAM_pop_free(param_table,
714 		    X509_VERIFY_PARAM_free);
715 	param_table = NULL;
716 }
717