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