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