xref: /openbsd-src/lib/libssl/ssl_cert.c (revision 689a9b7ed5fef180f7acf0aa1f578d59f05879ab)
1*689a9b7eSbeck /* $OpenBSD: ssl_cert.c,v 1.108 2024/02/03 15:58:33 beck Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
58913ec974Sbeck /* ====================================================================
590a5d6edeSdjm  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
60913ec974Sbeck  *
61913ec974Sbeck  * Redistribution and use in source and binary forms, with or without
62913ec974Sbeck  * modification, are permitted provided that the following conditions
63913ec974Sbeck  * are met:
64913ec974Sbeck  *
65913ec974Sbeck  * 1. Redistributions of source code must retain the above copyright
66913ec974Sbeck  *    notice, this list of conditions and the following disclaimer.
67913ec974Sbeck  *
68913ec974Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
69913ec974Sbeck  *    notice, this list of conditions and the following disclaimer in
70913ec974Sbeck  *    the documentation and/or other materials provided with the
71913ec974Sbeck  *    distribution.
72913ec974Sbeck  *
73913ec974Sbeck  * 3. All advertising materials mentioning features or use of this
74913ec974Sbeck  *    software must display the following acknowledgment:
75913ec974Sbeck  *    "This product includes software developed by the OpenSSL Project
764fcf65c5Sdjm  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77913ec974Sbeck  *
78913ec974Sbeck  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79913ec974Sbeck  *    endorse or promote products derived from this software without
80913ec974Sbeck  *    prior written permission. For written permission, please contact
814fcf65c5Sdjm  *    openssl-core@openssl.org.
82913ec974Sbeck  *
83913ec974Sbeck  * 5. Products derived from this software may not be called "OpenSSL"
84913ec974Sbeck  *    nor may "OpenSSL" appear in their names without prior written
85913ec974Sbeck  *    permission of the OpenSSL Project.
86913ec974Sbeck  *
87913ec974Sbeck  * 6. Redistributions of any form whatsoever must retain the following
88913ec974Sbeck  *    acknowledgment:
89913ec974Sbeck  *    "This product includes software developed by the OpenSSL Project
904fcf65c5Sdjm  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91913ec974Sbeck  *
92913ec974Sbeck  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93913ec974Sbeck  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94913ec974Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95913ec974Sbeck  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96913ec974Sbeck  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97913ec974Sbeck  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98913ec974Sbeck  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99913ec974Sbeck  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100913ec974Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101913ec974Sbeck  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102913ec974Sbeck  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103913ec974Sbeck  * OF THE POSSIBILITY OF SUCH DAMAGE.
104913ec974Sbeck  * ====================================================================
1054fcf65c5Sdjm  *
1064fcf65c5Sdjm  * This product includes cryptographic software written by Eric Young
1074fcf65c5Sdjm  * (eay@cryptsoft.com).  This product includes software written by Tim
1084fcf65c5Sdjm  * Hudson (tjh@cryptsoft.com).
1094fcf65c5Sdjm  *
1104fcf65c5Sdjm  */
1114fcf65c5Sdjm /* ====================================================================
1124fcf65c5Sdjm  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
1134fcf65c5Sdjm  * ECC cipher suite support in OpenSSL originally developed by
1144fcf65c5Sdjm  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
115913ec974Sbeck  */
1165b37fcf3Sryker 
117913ec974Sbeck #include <sys/types.h>
118ba5406e9Sbeck 
119c5899dbcSjsing #include <dirent.h>
1202fa0eb27Smpi #include <stdio.h>
1212fa0eb27Smpi #include <unistd.h>
1222fa0eb27Smpi 
123913ec974Sbeck #include <openssl/bio.h>
124c5899dbcSjsing #include <openssl/bn.h>
125c5899dbcSjsing #include <openssl/dh.h>
126c5899dbcSjsing #include <openssl/objects.h>
127c5899dbcSjsing #include <openssl/opensslconf.h>
128913ec974Sbeck #include <openssl/pem.h>
129ba5406e9Sbeck #include <openssl/x509v3.h>
130c5899dbcSjsing 
131c9675a23Stb #include "ssl_local.h"
1325b37fcf3Sryker 
13335fb0677Sjsing int
SSL_get_ex_data_X509_STORE_CTX_idx(void)13435fb0677Sjsing SSL_get_ex_data_X509_STORE_CTX_idx(void)
135913ec974Sbeck {
136da347917Sbeck 	static volatile int ssl_x509_store_ctx_idx = -1;
1374fcf65c5Sdjm 	int got_write_lock = 0;
1384fcf65c5Sdjm 
1394fcf65c5Sdjm 	CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
140da347917Sbeck 
14135fb0677Sjsing 	if (ssl_x509_store_ctx_idx < 0) {
1424fcf65c5Sdjm 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
143da347917Sbeck 		CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
1444fcf65c5Sdjm 		got_write_lock = 1;
145913ec974Sbeck 
14635fb0677Sjsing 		if (ssl_x509_store_ctx_idx < 0) {
1472dd17783Sjsing 			ssl_x509_store_ctx_idx =
1482dd17783Sjsing 			    X509_STORE_CTX_get_ex_new_index(
149913ec974Sbeck 				0, "SSL for verify callback", NULL, NULL, NULL);
150913ec974Sbeck 		}
151da347917Sbeck 	}
1524fcf65c5Sdjm 
1534fcf65c5Sdjm 	if (got_write_lock)
1544fcf65c5Sdjm 		CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
1554fcf65c5Sdjm 	else
1564fcf65c5Sdjm 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
1574fcf65c5Sdjm 
158da347917Sbeck 	return ssl_x509_store_ctx_idx;
159913ec974Sbeck }
16071e04849Sbeck LSSL_ALIAS(SSL_get_ex_data_X509_STORE_CTX_idx);
161913ec974Sbeck 
162ef36d1f9Sjsing SSL_CERT *
ssl_cert_new(void)163dbea66cdSguenther ssl_cert_new(void)
1645b37fcf3Sryker {
165ef36d1f9Sjsing 	SSL_CERT *ret;
1665b37fcf3Sryker 
167ef36d1f9Sjsing 	ret = calloc(1, sizeof(SSL_CERT));
16835fb0677Sjsing 	if (ret == NULL) {
169c9d7abb7Sbeck 		SSLerrorx(ERR_R_MALLOC_FAILURE);
1705b37fcf3Sryker 		return (NULL);
1715b37fcf3Sryker 	}
17216933562Sjsing 	ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
1735b37fcf3Sryker 	ret->references = 1;
1748096e1d5Stb 	ret->security_cb = ssl_security_default_cb;
1758096e1d5Stb 	ret->security_level = OPENSSL_TLS_SECURITY_LEVEL;
1768096e1d5Stb 	ret->security_ex_data = NULL;
1775b37fcf3Sryker 	return (ret);
1785b37fcf3Sryker }
1795b37fcf3Sryker 
180ef36d1f9Sjsing SSL_CERT *
ssl_cert_dup(SSL_CERT * cert)181ef36d1f9Sjsing ssl_cert_dup(SSL_CERT *cert)
182913ec974Sbeck {
183ef36d1f9Sjsing 	SSL_CERT *ret;
184913ec974Sbeck 	int i;
185913ec974Sbeck 
186ef36d1f9Sjsing 	ret = calloc(1, sizeof(SSL_CERT));
18735fb0677Sjsing 	if (ret == NULL) {
188c9d7abb7Sbeck 		SSLerrorx(ERR_R_MALLOC_FAILURE);
189913ec974Sbeck 		return (NULL);
190913ec974Sbeck 	}
191913ec974Sbeck 
192574f5b78Sguenther 	/*
193574f5b78Sguenther 	 * same as ret->key = ret->pkeys + (cert->key - cert->pkeys),
194574f5b78Sguenther 	 * if you find that more readable
195574f5b78Sguenther 	 */
196913ec974Sbeck 	ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
197913ec974Sbeck 
198913ec974Sbeck 	ret->valid = cert->valid;
1990a5d6edeSdjm 	ret->mask_k = cert->mask_k;
2000a5d6edeSdjm 	ret->mask_a = cert->mask_a;
201913ec974Sbeck 
202c0b85757Sjsing 	if (cert->dhe_params != NULL) {
203c0b85757Sjsing 		ret->dhe_params = DHparams_dup(cert->dhe_params);
204c0b85757Sjsing 		if (ret->dhe_params == NULL) {
205c9d7abb7Sbeck 			SSLerrorx(ERR_R_DH_LIB);
206913ec974Sbeck 			goto err;
207913ec974Sbeck 		}
208913ec974Sbeck 	}
209c0b85757Sjsing 	ret->dhe_params_cb = cert->dhe_params_cb;
210c0b85757Sjsing 	ret->dhe_params_auto = cert->dhe_params_auto;
211913ec974Sbeck 
21235fb0677Sjsing 	for (i = 0; i < SSL_PKEY_NUM; i++) {
21335fb0677Sjsing 		if (cert->pkeys[i].x509 != NULL) {
214913ec974Sbeck 			ret->pkeys[i].x509 = cert->pkeys[i].x509;
215526e2352Stb 			X509_up_ref(ret->pkeys[i].x509);
216913ec974Sbeck 		}
217913ec974Sbeck 
21835fb0677Sjsing 		if (cert->pkeys[i].privatekey != NULL) {
219913ec974Sbeck 			ret->pkeys[i].privatekey = cert->pkeys[i].privatekey;
2205c273ab3Stb 			EVP_PKEY_up_ref(ret->pkeys[i].privatekey);
22135fb0677Sjsing 			switch (i) {
222574f5b78Sguenther 				/*
223574f5b78Sguenther 				 * If there was anything special to do for
224913ec974Sbeck 				 * certain types of keys, we'd do it here.
225574f5b78Sguenther 				 * (Nothing at the moment, I think.)
226574f5b78Sguenther 				 */
227913ec974Sbeck 
22816933562Sjsing 			case SSL_PKEY_RSA:
229913ec974Sbeck 				/* We have an RSA key. */
230913ec974Sbeck 				break;
231913ec974Sbeck 
2324fcf65c5Sdjm 			case SSL_PKEY_ECC:
2334fcf65c5Sdjm 				/* We have an ECC key */
2344fcf65c5Sdjm 				break;
2354fcf65c5Sdjm 
236913ec974Sbeck 			default:
237913ec974Sbeck 				/* Can't happen. */
238c9d7abb7Sbeck 				SSLerrorx(SSL_R_LIBRARY_BUG);
239913ec974Sbeck 			}
240913ec974Sbeck 		}
241eef9ac4dSjsing 
242eef9ac4dSjsing 		if (cert->pkeys[i].chain != NULL) {
243eef9ac4dSjsing 			if ((ret->pkeys[i].chain =
244eef9ac4dSjsing 			    X509_chain_up_ref(cert->pkeys[i].chain)) == NULL)
245eef9ac4dSjsing 				goto err;
246eef9ac4dSjsing 		}
247913ec974Sbeck 	}
248913ec974Sbeck 
249257dedccStb 	ret->security_cb = cert->security_cb;
250257dedccStb 	ret->security_level = cert->security_level;
251257dedccStb 	ret->security_ex_data = cert->security_ex_data;
252257dedccStb 
253574f5b78Sguenther 	/*
254574f5b78Sguenther 	 * ret->extra_certs *should* exist, but currently the own certificate
255574f5b78Sguenther 	 * chain is held inside SSL_CTX
256574f5b78Sguenther 	 */
257913ec974Sbeck 
258913ec974Sbeck 	ret->references = 1;
259913ec974Sbeck 
260913ec974Sbeck 	return (ret);
261913ec974Sbeck 
262913ec974Sbeck  err:
263c0b85757Sjsing 	DH_free(ret->dhe_params);
264913ec974Sbeck 
26535fb0677Sjsing 	for (i = 0; i < SSL_PKEY_NUM; i++) {
266913ec974Sbeck 		X509_free(ret->pkeys[i].x509);
267913ec974Sbeck 		EVP_PKEY_free(ret->pkeys[i].privatekey);
268eef9ac4dSjsing 		sk_X509_pop_free(ret->pkeys[i].chain, X509_free);
269913ec974Sbeck 	}
270ade01c78Slogan 	free (ret);
271913ec974Sbeck 	return NULL;
272913ec974Sbeck }
273913ec974Sbeck 
274913ec974Sbeck 
27535fb0677Sjsing void
ssl_cert_free(SSL_CERT * c)276ef36d1f9Sjsing ssl_cert_free(SSL_CERT *c)
2775b37fcf3Sryker {
2785b37fcf3Sryker 	int i;
2795b37fcf3Sryker 
280913ec974Sbeck 	if (c == NULL)
281913ec974Sbeck 		return;
282913ec974Sbeck 
2835b37fcf3Sryker 	i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT);
28435fb0677Sjsing 	if (i > 0)
28535fb0677Sjsing 		return;
2865b37fcf3Sryker 
287c0b85757Sjsing 	DH_free(c->dhe_params);
2885b37fcf3Sryker 
28935fb0677Sjsing 	for (i = 0; i < SSL_PKEY_NUM; i++) {
2905b37fcf3Sryker 		X509_free(c->pkeys[i].x509);
2915b37fcf3Sryker 		EVP_PKEY_free(c->pkeys[i].privatekey);
292eef9ac4dSjsing 		sk_X509_pop_free(c->pkeys[i].chain, X509_free);
2935b37fcf3Sryker 	}
2944fb7e9cfSjsing 
2956f3a6cb1Sbeck 	free(c);
2965b37fcf3Sryker }
2975b37fcf3Sryker 
298ba90dbc1Stb SSL_CERT *
ssl_get0_cert(SSL_CTX * ctx,SSL * ssl)299ba90dbc1Stb ssl_get0_cert(SSL_CTX *ctx, SSL *ssl)
300ba90dbc1Stb {
301ba90dbc1Stb 	if (ssl != NULL)
302ba90dbc1Stb 		return ssl->cert;
303ba90dbc1Stb 
3046f7f653bSjsing 	return ctx->cert;
305ba90dbc1Stb }
306ba90dbc1Stb 
307eef9ac4dSjsing int
ssl_cert_set0_chain(SSL_CTX * ctx,SSL * ssl,STACK_OF (X509)* chain)3085dbcc7f0Stb ssl_cert_set0_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain)
309eef9ac4dSjsing {
3105dbcc7f0Stb 	SSL_CERT *ssl_cert;
3115dbcc7f0Stb 	SSL_CERT_PKEY *cpk;
3125dbcc7f0Stb 	X509 *x509;
3135dbcc7f0Stb 	int ssl_err;
3145dbcc7f0Stb 	int i;
3155dbcc7f0Stb 
3165dbcc7f0Stb 	if ((ssl_cert = ssl_get0_cert(ctx, ssl)) == NULL)
317eef9ac4dSjsing 		return 0;
318eef9ac4dSjsing 
3195dbcc7f0Stb 	if ((cpk = ssl_cert->key) == NULL)
3205dbcc7f0Stb 		return 0;
3215dbcc7f0Stb 
3225dbcc7f0Stb 	for (i = 0; i < sk_X509_num(chain); i++) {
3235dbcc7f0Stb 		x509 = sk_X509_value(chain, i);
3245dbcc7f0Stb 		if (!ssl_security_cert(ctx, ssl, x509, 0, &ssl_err)) {
3255dbcc7f0Stb 			SSLerrorx(ssl_err);
3265dbcc7f0Stb 			return 0;
3275dbcc7f0Stb 		}
3285dbcc7f0Stb 	}
3295dbcc7f0Stb 
3305dbcc7f0Stb 	sk_X509_pop_free(cpk->chain, X509_free);
3315dbcc7f0Stb 	cpk->chain = chain;
332eef9ac4dSjsing 
333eef9ac4dSjsing 	return 1;
334eef9ac4dSjsing }
335eef9ac4dSjsing 
336eef9ac4dSjsing int
ssl_cert_set1_chain(SSL_CTX * ctx,SSL * ssl,STACK_OF (X509)* chain)3375dbcc7f0Stb ssl_cert_set1_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain)
338eef9ac4dSjsing {
339eef9ac4dSjsing 	STACK_OF(X509) *new_chain = NULL;
340eef9ac4dSjsing 
341eef9ac4dSjsing 	if (chain != NULL) {
342eef9ac4dSjsing 		if ((new_chain = X509_chain_up_ref(chain)) == NULL)
343eef9ac4dSjsing 			return 0;
344eef9ac4dSjsing 	}
3455dbcc7f0Stb 	if (!ssl_cert_set0_chain(ctx, ssl, new_chain)) {
346eef9ac4dSjsing 		sk_X509_pop_free(new_chain, X509_free);
347eef9ac4dSjsing 		return 0;
348eef9ac4dSjsing 	}
349eef9ac4dSjsing 
350eef9ac4dSjsing 	return 1;
351eef9ac4dSjsing }
352eef9ac4dSjsing 
353eef9ac4dSjsing int
ssl_cert_add0_chain_cert(SSL_CTX * ctx,SSL * ssl,X509 * cert)354dc2a950bStb ssl_cert_add0_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert)
355eef9ac4dSjsing {
356dc2a950bStb 	SSL_CERT *ssl_cert;
357dc2a950bStb 	SSL_CERT_PKEY *cpk;
358dc2a950bStb 	int ssl_err;
359dc2a950bStb 
360dc2a950bStb 	if ((ssl_cert = ssl_get0_cert(ctx, ssl)) == NULL)
361eef9ac4dSjsing 		return 0;
362eef9ac4dSjsing 
363dc2a950bStb 	if ((cpk = ssl_cert->key) == NULL)
364dc2a950bStb 		return 0;
365dc2a950bStb 
366dc2a950bStb 	if (!ssl_security_cert(ctx, ssl, cert, 0, &ssl_err)) {
367dc2a950bStb 		SSLerrorx(ssl_err);
368eef9ac4dSjsing 		return 0;
369eef9ac4dSjsing 	}
370dc2a950bStb 
371dc2a950bStb 	if (cpk->chain == NULL) {
372dc2a950bStb 		if ((cpk->chain = sk_X509_new_null()) == NULL)
373dc2a950bStb 			return 0;
374dc2a950bStb 	}
375dc2a950bStb 	if (!sk_X509_push(cpk->chain, cert))
376eef9ac4dSjsing 		return 0;
377eef9ac4dSjsing 
378eef9ac4dSjsing 	return 1;
379eef9ac4dSjsing }
380eef9ac4dSjsing 
381eef9ac4dSjsing int
ssl_cert_add1_chain_cert(SSL_CTX * ctx,SSL * ssl,X509 * cert)382dc2a950bStb ssl_cert_add1_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert)
383eef9ac4dSjsing {
384dc2a950bStb 	if (!ssl_cert_add0_chain_cert(ctx, ssl, cert))
385eef9ac4dSjsing 		return 0;
386eef9ac4dSjsing 
387eef9ac4dSjsing 	X509_up_ref(cert);
388eef9ac4dSjsing 
389eef9ac4dSjsing 	return 1;
390eef9ac4dSjsing }
391eef9ac4dSjsing 
39235fb0677Sjsing int
ssl_verify_cert_chain(SSL * s,STACK_OF (X509)* certs)393a7ac21abSjsing ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *certs)
3945b37fcf3Sryker {
3951d13974eStb 	X509_STORE_CTX *ctx = NULL;
396eb88d233Stb 	X509_VERIFY_PARAM *param;
397a7ac21abSjsing 	X509 *cert;
3981d13974eStb 	int ret = 0;
3995b37fcf3Sryker 
400a7ac21abSjsing 	if (sk_X509_num(certs) < 1)
4011d13974eStb 		goto err;
4021d13974eStb 
4031d13974eStb 	if ((ctx = X509_STORE_CTX_new()) == NULL)
4041d13974eStb 		goto err;
4055b37fcf3Sryker 
406a7ac21abSjsing 	cert = sk_X509_value(certs, 0);
407a7ac21abSjsing 	if (!X509_STORE_CTX_init(ctx, s->ctx->cert_store, cert, certs)) {
408c9d7abb7Sbeck 		SSLerror(s, ERR_R_X509_LIB);
4091d13974eStb 		goto err;
410da347917Sbeck 	}
4111d13974eStb 	X509_STORE_CTX_set_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
412da347917Sbeck 
413574f5b78Sguenther 	/*
414574f5b78Sguenther 	 * We need to inherit the verify parameters. These can be
415574f5b78Sguenther 	 * determined by the context: if its a server it will verify
416574f5b78Sguenther 	 * SSL client certificates or vice versa.
417ba5406e9Sbeck 	 */
4181d13974eStb 	X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
419f8ac70f1Sjsing 
420eb88d233Stb 	param = X509_STORE_CTX_get0_param(ctx);
421eb88d233Stb 
422eb88d233Stb 	X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
423eb88d233Stb 
424574f5b78Sguenther 	/*
425574f5b78Sguenther 	 * Anything non-default in "param" should overwrite anything
426574f5b78Sguenther 	 * in the ctx.
4270a5d6edeSdjm 	 */
428eb88d233Stb 	X509_VERIFY_PARAM_set1(param, s->param);
4295b37fcf3Sryker 
4306f7f653bSjsing 	if (s->verify_callback)
4316f7f653bSjsing 		X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
432da347917Sbeck 
4336f7f653bSjsing 	if (s->ctx->app_verify_callback != NULL)
4346f7f653bSjsing 		ret = s->ctx->app_verify_callback(ctx,
4356f7f653bSjsing 		    s->ctx->app_verify_arg);
436f8ac70f1Sjsing 	else
4371d13974eStb 		ret = X509_verify_cert(ctx);
4385b37fcf3Sryker 
4391d13974eStb 	s->verify_result = X509_STORE_CTX_get_error(ctx);
44057f93a0cStb 	sk_X509_pop_free(s->s3->hs.verified_chain, X509_free);
44157f93a0cStb 	s->s3->hs.verified_chain = NULL;
4424a18b5baSbeck 	if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
44357f93a0cStb 		s->s3->hs.verified_chain = X509_STORE_CTX_get1_chain(ctx);
44457f93a0cStb 		if (s->s3->hs.verified_chain == NULL) {
4454a18b5baSbeck 			SSLerrorx(ERR_R_MALLOC_FAILURE);
4464a18b5baSbeck 			ret = 0;
4474a18b5baSbeck 		}
4484a18b5baSbeck 	}
4491d13974eStb 
4501d13974eStb  err:
4511d13974eStb 	X509_STORE_CTX_free(ctx);
4525b37fcf3Sryker 
453f8ac70f1Sjsing 	return (ret);
4545b37fcf3Sryker }
4555b37fcf3Sryker 
45635fb0677Sjsing static void
set_client_CA_list(STACK_OF (X509_NAME)** ca_list,STACK_OF (X509_NAME)* name_list)4572dd17783Sjsing set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
4582dd17783Sjsing     STACK_OF(X509_NAME) *name_list)
4595b37fcf3Sryker {
460913ec974Sbeck 	sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
4616278d030Smarkus 	*ca_list = name_list;
4625b37fcf3Sryker }
4635b37fcf3Sryker 
STACK_OF(X509_NAME)464dbea66cdSguenther STACK_OF(X509_NAME) *
4650a4fabb9Stb SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
4665b37fcf3Sryker {
4675b37fcf3Sryker 	int i;
468913ec974Sbeck 	STACK_OF(X509_NAME) *ret;
4698a9e94f3Stb 	X509_NAME *name = NULL;
4705b37fcf3Sryker 
4718a9e94f3Stb 	if ((ret = sk_X509_NAME_new_null()) == NULL)
4728a9e94f3Stb 		goto err;
4738a9e94f3Stb 
47435fb0677Sjsing 	for (i = 0; i < sk_X509_NAME_num(sk); i++) {
4758a9e94f3Stb 		if ((name = X509_NAME_dup(sk_X509_NAME_value(sk, i))) == NULL)
4768a9e94f3Stb 			goto err;
4778a9e94f3Stb 		if (!sk_X509_NAME_push(ret, name))
4788a9e94f3Stb 			goto err;
4795b37fcf3Sryker 	}
4805b37fcf3Sryker 	return (ret);
4818a9e94f3Stb 
4828a9e94f3Stb  err:
4838a9e94f3Stb 	X509_NAME_free(name);
4848a9e94f3Stb 	sk_X509_NAME_pop_free(ret, X509_NAME_free);
4858a9e94f3Stb 	return NULL;
4865b37fcf3Sryker }
48771e04849Sbeck LSSL_ALIAS(SSL_dup_CA_list);
4885b37fcf3Sryker 
48935fb0677Sjsing void
SSL_set_client_CA_list(SSL * s,STACK_OF (X509_NAME)* name_list)49035fb0677Sjsing SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
4915b37fcf3Sryker {
4926f7f653bSjsing 	set_client_CA_list(&(s->client_CA), name_list);
4935b37fcf3Sryker }
49471e04849Sbeck LSSL_ALIAS(SSL_set_client_CA_list);
4955b37fcf3Sryker 
49635fb0677Sjsing void
SSL_CTX_set_client_CA_list(SSL_CTX * ctx,STACK_OF (X509_NAME)* name_list)49735fb0677Sjsing SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
4985b37fcf3Sryker {
4996f7f653bSjsing 	set_client_CA_list(&(ctx->client_CA), name_list);
5005b37fcf3Sryker }
50171e04849Sbeck LSSL_ALIAS(SSL_CTX_set_client_CA_list);
5025b37fcf3Sryker 
STACK_OF(X509_NAME)503dbea66cdSguenther STACK_OF(X509_NAME) *
504dbea66cdSguenther SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
5055b37fcf3Sryker {
5066f7f653bSjsing 	return (ctx->client_CA);
5075b37fcf3Sryker }
50871e04849Sbeck LSSL_ALIAS(SSL_CTX_get_client_CA_list);
5095b37fcf3Sryker 
STACK_OF(X509_NAME)510dbea66cdSguenther STACK_OF(X509_NAME) *
511dbea66cdSguenther SSL_get_client_CA_list(const SSL *s)
5125b37fcf3Sryker {
513b0828d45Stb 	if (!s->server) {
5142dd17783Sjsing 		/* We are in the client. */
515370b9647Sbcook 		if ((s->version >> 8) == SSL3_VERSION_MAJOR)
51602876cc3Sjsing 			return (s->s3->hs.tls12.ca_names);
5175b37fcf3Sryker 		else
5185b37fcf3Sryker 			return (NULL);
51935fb0677Sjsing 	} else {
5206f7f653bSjsing 		if (s->client_CA != NULL)
5216f7f653bSjsing 			return (s->client_CA);
5225b37fcf3Sryker 		else
5236f7f653bSjsing 			return (s->ctx->client_CA);
5245b37fcf3Sryker 	}
5255b37fcf3Sryker }
52671e04849Sbeck LSSL_ALIAS(SSL_get_client_CA_list);
5275b37fcf3Sryker 
52835fb0677Sjsing static int
add_client_CA(STACK_OF (X509_NAME)** sk,X509 * x)52935fb0677Sjsing add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x)
5305b37fcf3Sryker {
5315b37fcf3Sryker 	X509_NAME *name;
5325b37fcf3Sryker 
53335fb0677Sjsing 	if (x == NULL)
53435fb0677Sjsing 		return (0);
535913ec974Sbeck 	if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL))
5365b37fcf3Sryker 		return (0);
5375b37fcf3Sryker 
5385b37fcf3Sryker 	if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
5395b37fcf3Sryker 		return (0);
5405b37fcf3Sryker 
54135fb0677Sjsing 	if (!sk_X509_NAME_push(*sk, name)) {
5425b37fcf3Sryker 		X509_NAME_free(name);
5435b37fcf3Sryker 		return (0);
5445b37fcf3Sryker 	}
5455b37fcf3Sryker 	return (1);
5465b37fcf3Sryker }
5475b37fcf3Sryker 
54835fb0677Sjsing int
SSL_add_client_CA(SSL * ssl,X509 * x)54935fb0677Sjsing SSL_add_client_CA(SSL *ssl, X509 *x)
5505b37fcf3Sryker {
5516f7f653bSjsing 	return (add_client_CA(&(ssl->client_CA), x));
5525b37fcf3Sryker }
55371e04849Sbeck LSSL_ALIAS(SSL_add_client_CA);
5545b37fcf3Sryker 
55535fb0677Sjsing int
SSL_CTX_add_client_CA(SSL_CTX * ctx,X509 * x)55635fb0677Sjsing SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
5575b37fcf3Sryker {
5586f7f653bSjsing 	return (add_client_CA(&(ctx->client_CA), x));
5595b37fcf3Sryker }
56071e04849Sbeck LSSL_ALIAS(SSL_CTX_add_client_CA);
5615b37fcf3Sryker 
56235fb0677Sjsing static int
xname_cmp(const X509_NAME * const * a,const X509_NAME * const * b)56335fb0677Sjsing xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
5645b37fcf3Sryker {
5655b37fcf3Sryker 	return (X509_NAME_cmp(*a, *b));
5665b37fcf3Sryker }
5675b37fcf3Sryker 
568913ec974Sbeck /*!
569913ec974Sbeck  * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
570913ec974Sbeck  * it doesn't really have anything to do with clients (except that a common use
571913ec974Sbeck  * for a stack of CAs is to send it to the client). Actually, it doesn't have
572913ec974Sbeck  * much to do with CAs, either, since it will load any old cert.
573913ec974Sbeck  * \param file the file containing one or more certs.
574913ec974Sbeck  * \return a ::STACK containing the certs.
575913ec974Sbeck  */
STACK_OF(X509_NAME)576dbea66cdSguenther STACK_OF(X509_NAME) *
577dbea66cdSguenther SSL_load_client_CA_file(const char *file)
5785b37fcf3Sryker {
5795b37fcf3Sryker 	BIO *in;
5805b37fcf3Sryker 	X509 *x = NULL;
5815b37fcf3Sryker 	X509_NAME *xn = NULL;
5826d388760Sdjm 	STACK_OF(X509_NAME) *ret = NULL, *sk;
5835b37fcf3Sryker 
584ba5406e9Sbeck 	sk = sk_X509_NAME_new(xname_cmp);
5855b37fcf3Sryker 
586590ebd80Stb 	in = BIO_new(BIO_s_file());
5875b37fcf3Sryker 
58835fb0677Sjsing 	if ((sk == NULL) || (in == NULL)) {
589c9d7abb7Sbeck 		SSLerrorx(ERR_R_MALLOC_FAILURE);
5905b37fcf3Sryker 		goto err;
5915b37fcf3Sryker 	}
5925b37fcf3Sryker 
5935b37fcf3Sryker 	if (!BIO_read_filename(in, file))
5945b37fcf3Sryker 		goto err;
5955b37fcf3Sryker 
59635fb0677Sjsing 	for (;;) {
597913ec974Sbeck 		if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
5985b37fcf3Sryker 			break;
59935fb0677Sjsing 		if (ret == NULL) {
6006d388760Sdjm 			ret = sk_X509_NAME_new_null();
60135fb0677Sjsing 			if (ret == NULL) {
602c9d7abb7Sbeck 				SSLerrorx(ERR_R_MALLOC_FAILURE);
6036d388760Sdjm 				goto err;
6046d388760Sdjm 			}
6056d388760Sdjm 		}
6067110bbb1Stb 		if ((xn = X509_get_subject_name(x)) == NULL)
6077110bbb1Stb 			goto err;
6085b37fcf3Sryker 		/* check for duplicates */
6095b37fcf3Sryker 		xn = X509_NAME_dup(xn);
61035fb0677Sjsing 		if (xn == NULL)
61135fb0677Sjsing 			goto err;
612913ec974Sbeck 		if (sk_X509_NAME_find(sk, xn) >= 0)
6135b37fcf3Sryker 			X509_NAME_free(xn);
61435fb0677Sjsing 		else {
61504ef99eeSinoguchi 			if (!sk_X509_NAME_push(sk, xn))
61604ef99eeSinoguchi 				goto err;
61704ef99eeSinoguchi 			if (!sk_X509_NAME_push(ret, xn))
61804ef99eeSinoguchi 				goto err;
6195b37fcf3Sryker 		}
6205b37fcf3Sryker 	}
6215b37fcf3Sryker 
62235fb0677Sjsing 	if (0) {
6235b37fcf3Sryker  err:
62435fb0677Sjsing 		sk_X509_NAME_pop_free(ret, X509_NAME_free);
6255b37fcf3Sryker 		ret = NULL;
6265b37fcf3Sryker 	}
62735fb0677Sjsing 	sk_X509_NAME_free(sk);
62835fb0677Sjsing 	BIO_free(in);
62935fb0677Sjsing 	X509_free(x);
6306d388760Sdjm 	if (ret != NULL)
6316d388760Sdjm 		ERR_clear_error();
6323a878bc4Sjsing 
6335b37fcf3Sryker 	return (ret);
6345b37fcf3Sryker }
63571e04849Sbeck LSSL_ALIAS(SSL_load_client_CA_file);
6365b37fcf3Sryker 
637913ec974Sbeck /*!
638913ec974Sbeck  * Add a file of certs to a stack.
639913ec974Sbeck  * \param stack the stack to add to.
640913ec974Sbeck  * \param file the file to add from. All certs in this file that are not
641913ec974Sbeck  * already in the stack will be added.
642913ec974Sbeck  * \return 1 for success, 0 for failure. Note that in the case of failure some
643913ec974Sbeck  * certs may have been added to \c stack.
644913ec974Sbeck  */
645913ec974Sbeck 
64635fb0677Sjsing int
SSL_add_file_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * file)64735fb0677Sjsing SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
648913ec974Sbeck     const char *file)
649913ec974Sbeck {
650913ec974Sbeck 	BIO *in;
651913ec974Sbeck 	X509 *x = NULL;
652913ec974Sbeck 	X509_NAME *xn = NULL;
653913ec974Sbeck 	int ret = 1;
654c109e398Sbeck 	int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b);
655913ec974Sbeck 
656ba5406e9Sbeck 	oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
657913ec974Sbeck 
658590ebd80Stb 	in = BIO_new(BIO_s_file());
659913ec974Sbeck 
66035fb0677Sjsing 	if (in == NULL) {
661c9d7abb7Sbeck 		SSLerrorx(ERR_R_MALLOC_FAILURE);
662913ec974Sbeck 		goto err;
663913ec974Sbeck 	}
664913ec974Sbeck 
665913ec974Sbeck 	if (!BIO_read_filename(in, file))
666913ec974Sbeck 		goto err;
667913ec974Sbeck 
66835fb0677Sjsing 	for (;;) {
669913ec974Sbeck 		if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
670913ec974Sbeck 			break;
6719e52ca1eStb 		if ((xn = X509_get_subject_name(x)) == NULL)
6729e52ca1eStb 			goto err;
673913ec974Sbeck 		xn = X509_NAME_dup(xn);
67435fb0677Sjsing 		if (xn == NULL)
67535fb0677Sjsing 			goto err;
676913ec974Sbeck 		if (sk_X509_NAME_find(stack, xn) >= 0)
677913ec974Sbeck 			X509_NAME_free(xn);
678913ec974Sbeck 		else
67904ef99eeSinoguchi 			if (!sk_X509_NAME_push(stack, xn))
68004ef99eeSinoguchi 				goto err;
681913ec974Sbeck 	}
682913ec974Sbeck 
6830a5d6edeSdjm 	ERR_clear_error();
6840a5d6edeSdjm 
68535fb0677Sjsing 	if (0) {
686913ec974Sbeck  err:
687913ec974Sbeck 		ret = 0;
688913ec974Sbeck 	}
689913ec974Sbeck 	BIO_free(in);
690913ec974Sbeck 	X509_free(x);
691913ec974Sbeck 
6924fcf65c5Sdjm 	(void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
693913ec974Sbeck 
694913ec974Sbeck 	return ret;
695913ec974Sbeck }
69671e04849Sbeck LSSL_ALIAS(SSL_add_file_cert_subjects_to_stack);
697913ec974Sbeck 
698913ec974Sbeck /*!
699913ec974Sbeck  * Add a directory of certs to a stack.
700913ec974Sbeck  * \param stack the stack to append to.
701913ec974Sbeck  * \param dir the directory to append from. All files in this directory will be
702913ec974Sbeck  * examined as potential certs. Any that are acceptable to
7032dd17783Sjsing  * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will
7042dd17783Sjsing  * be included.
705913ec974Sbeck  * \return 1 for success, 0 for failure. Note that in the case of failure some
706913ec974Sbeck  * certs may have been added to \c stack.
707913ec974Sbeck  */
708913ec974Sbeck 
70935fb0677Sjsing int
SSL_add_dir_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * dir)7102dd17783Sjsing SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir)
711913ec974Sbeck {
712858e1332Sbeck 	DIR *dirp = NULL;
713858e1332Sbeck 	char *path = NULL;
714913ec974Sbeck 	int ret = 0;
715913ec974Sbeck 
716858e1332Sbeck 	dirp = opendir(dir);
717858e1332Sbeck 	if (dirp) {
718858e1332Sbeck 		struct dirent *dp;
719858e1332Sbeck 		while ((dp = readdir(dirp)) != NULL) {
720858e1332Sbeck 			if (asprintf(&path, "%s/%s", dir, dp->d_name) != -1) {
7212dd17783Sjsing 				ret = SSL_add_file_cert_subjects_to_stack(
7222dd17783Sjsing 				    stack, path);
723858e1332Sbeck 				free(path);
724913ec974Sbeck 			}
725858e1332Sbeck 			if (!ret)
726858e1332Sbeck 				break;
727913ec974Sbeck 		}
728858e1332Sbeck 		(void) closedir(dirp);
729858e1332Sbeck 	}
730858e1332Sbeck 	if (!ret) {
7315067ae9fSbeck  		SYSerror(errno);
7320f637b92Sbeck 		ERR_asprintf_error_data("opendir ('%s')", dir);
733c9d7abb7Sbeck 		SSLerrorx(ERR_R_SYS_LIB);
734da347917Sbeck 	}
735da347917Sbeck 	return ret;
736da347917Sbeck }
73771e04849Sbeck LSSL_ALIAS(SSL_add_dir_cert_subjects_to_stack);
738