xref: /freebsd/crypto/openssl/ssl/ssl_cert.c (revision 6cf8931a2f9fa26b2d9bdba6f1915f655e6bf25f)
16f9291ceSJung-uk Kim /*
26f9291ceSJung-uk Kim  * ! \file ssl/ssl_cert.c
36f9291ceSJung-uk Kim  */
474664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
574664626SKris Kennaway  * All rights reserved.
674664626SKris Kennaway  *
774664626SKris Kennaway  * This package is an SSL implementation written
874664626SKris Kennaway  * by Eric Young (eay@cryptsoft.com).
974664626SKris Kennaway  * The implementation was written so as to conform with Netscapes SSL.
1074664626SKris Kennaway  *
1174664626SKris Kennaway  * This library is free for commercial and non-commercial use as long as
1274664626SKris Kennaway  * the following conditions are aheared to.  The following conditions
1374664626SKris Kennaway  * apply to all code found in this distribution, be it the RC4, RSA,
1474664626SKris Kennaway  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1574664626SKris Kennaway  * included with this distribution is covered by the same copyright terms
1674664626SKris Kennaway  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1774664626SKris Kennaway  *
1874664626SKris Kennaway  * Copyright remains Eric Young's, and as such any Copyright notices in
1974664626SKris Kennaway  * the code are not to be removed.
2074664626SKris Kennaway  * If this package is used in a product, Eric Young should be given attribution
2174664626SKris Kennaway  * as the author of the parts of the library used.
2274664626SKris Kennaway  * This can be in the form of a textual message at program startup or
2374664626SKris Kennaway  * in documentation (online or textual) provided with the package.
2474664626SKris Kennaway  *
2574664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
2674664626SKris Kennaway  * modification, are permitted provided that the following conditions
2774664626SKris Kennaway  * are met:
2874664626SKris Kennaway  * 1. Redistributions of source code must retain the copyright
2974664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
3074664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
3174664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
3274664626SKris Kennaway  *    documentation and/or other materials provided with the distribution.
3374664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this software
3474664626SKris Kennaway  *    must display the following acknowledgement:
3574664626SKris Kennaway  *    "This product includes cryptographic software written by
3674664626SKris Kennaway  *     Eric Young (eay@cryptsoft.com)"
3774664626SKris Kennaway  *    The word 'cryptographic' can be left out if the rouines from the library
3874664626SKris Kennaway  *    being used are not cryptographic related :-).
3974664626SKris Kennaway  * 4. If you include any Windows specific code (or a derivative thereof) from
4074664626SKris Kennaway  *    the apps directory (application code) you must include an acknowledgement:
4174664626SKris Kennaway  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4274664626SKris Kennaway  *
4374664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4474664626SKris Kennaway  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4574664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4674664626SKris Kennaway  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4774664626SKris Kennaway  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4874664626SKris Kennaway  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4974664626SKris Kennaway  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5074664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5174664626SKris Kennaway  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5274664626SKris Kennaway  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5374664626SKris Kennaway  * SUCH DAMAGE.
5474664626SKris Kennaway  *
5574664626SKris Kennaway  * The licence and distribution terms for any publically available version or
5674664626SKris Kennaway  * derivative of this code cannot be changed.  i.e. this code cannot simply be
5774664626SKris Kennaway  * copied and put under another distribution licence
5874664626SKris Kennaway  * [including the GNU Public Licence.]
5974664626SKris Kennaway  */
6074664626SKris Kennaway /* ====================================================================
611f13597dSJung-uk Kim  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
6274664626SKris Kennaway  *
6374664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
6474664626SKris Kennaway  * modification, are permitted provided that the following conditions
6574664626SKris Kennaway  * are met:
6674664626SKris Kennaway  *
6774664626SKris Kennaway  * 1. Redistributions of source code must retain the above copyright
6874664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
6974664626SKris Kennaway  *
7074664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
7174664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in
7274664626SKris Kennaway  *    the documentation and/or other materials provided with the
7374664626SKris Kennaway  *    distribution.
7474664626SKris Kennaway  *
7574664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this
7674664626SKris Kennaway  *    software must display the following acknowledgment:
7774664626SKris Kennaway  *    "This product includes software developed by the OpenSSL Project
78ed5d4f9aSSimon L. B. Nielsen  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
7974664626SKris Kennaway  *
8074664626SKris Kennaway  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
8174664626SKris Kennaway  *    endorse or promote products derived from this software without
8274664626SKris Kennaway  *    prior written permission. For written permission, please contact
83ed5d4f9aSSimon L. B. Nielsen  *    openssl-core@openssl.org.
8474664626SKris Kennaway  *
8574664626SKris Kennaway  * 5. Products derived from this software may not be called "OpenSSL"
8674664626SKris Kennaway  *    nor may "OpenSSL" appear in their names without prior written
8774664626SKris Kennaway  *    permission of the OpenSSL Project.
8874664626SKris Kennaway  *
8974664626SKris Kennaway  * 6. Redistributions of any form whatsoever must retain the following
9074664626SKris Kennaway  *    acknowledgment:
9174664626SKris Kennaway  *    "This product includes software developed by the OpenSSL Project
92ed5d4f9aSSimon L. B. Nielsen  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
9374664626SKris Kennaway  *
9474664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
9574664626SKris Kennaway  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9674664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
9774664626SKris Kennaway  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
9874664626SKris Kennaway  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9974664626SKris Kennaway  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
10074664626SKris Kennaway  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
10174664626SKris Kennaway  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
10274664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
10374664626SKris Kennaway  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
10474664626SKris Kennaway  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
10574664626SKris Kennaway  * OF THE POSSIBILITY OF SUCH DAMAGE.
10674664626SKris Kennaway  * ====================================================================
107ed5d4f9aSSimon L. B. Nielsen  *
108ed5d4f9aSSimon L. B. Nielsen  * This product includes cryptographic software written by Eric Young
109ed5d4f9aSSimon L. B. Nielsen  * (eay@cryptsoft.com).  This product includes software written by Tim
110ed5d4f9aSSimon L. B. Nielsen  * Hudson (tjh@cryptsoft.com).
111ed5d4f9aSSimon L. B. Nielsen  *
11274664626SKris Kennaway  */
1133b4e3dcbSSimon L. B. Nielsen /* ====================================================================
1143b4e3dcbSSimon L. B. Nielsen  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
1153b4e3dcbSSimon L. B. Nielsen  * ECC cipher suite support in OpenSSL originally developed by
1163b4e3dcbSSimon L. B. Nielsen  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
1173b4e3dcbSSimon L. B. Nielsen  */
11874664626SKris Kennaway 
11974664626SKris Kennaway #include <stdio.h>
120f579bf8eSKris Kennaway 
1215c87c606SMark Murray #include "e_os.h"
122f579bf8eSKris Kennaway #ifndef NO_SYS_TYPES_H
12374664626SKris Kennaway # include <sys/types.h>
124f579bf8eSKris Kennaway #endif
125f579bf8eSKris Kennaway 
1263b4e3dcbSSimon L. B. Nielsen #include "o_dir.h"
12774664626SKris Kennaway #include <openssl/objects.h>
12874664626SKris Kennaway #include <openssl/bio.h>
12974664626SKris Kennaway #include <openssl/pem.h>
130f579bf8eSKris Kennaway #include <openssl/x509v3.h>
1313b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_DH
1323b4e3dcbSSimon L. B. Nielsen # include <openssl/dh.h>
1333b4e3dcbSSimon L. B. Nielsen #endif
1343b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h>
13574664626SKris Kennaway #include "ssl_locl.h"
13674664626SKris Kennaway 
13774664626SKris Kennaway int SSL_get_ex_data_X509_STORE_CTX_idx(void)
13874664626SKris Kennaway {
1395c87c606SMark Murray     static volatile int ssl_x509_store_ctx_idx = -1;
140ed5d4f9aSSimon L. B. Nielsen     int got_write_lock = 0;
141ed5d4f9aSSimon L. B. Nielsen 
1427bded2dbSJung-uk Kim     if (((size_t)&ssl_x509_store_ctx_idx &
1437bded2dbSJung-uk Kim          (sizeof(ssl_x509_store_ctx_idx) - 1))
1447bded2dbSJung-uk Kim         == 0) {                 /* check alignment, practically always true */
1457bded2dbSJung-uk Kim         int ret;
1467bded2dbSJung-uk Kim 
1477bded2dbSJung-uk Kim         if ((ret = ssl_x509_store_ctx_idx) < 0) {
1487bded2dbSJung-uk Kim             CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
1497bded2dbSJung-uk Kim             if ((ret = ssl_x509_store_ctx_idx) < 0) {
1507bded2dbSJung-uk Kim                 ret = ssl_x509_store_ctx_idx =
1517bded2dbSJung-uk Kim                     X509_STORE_CTX_get_ex_new_index(0,
1527bded2dbSJung-uk Kim                                                     "SSL for verify callback",
1537bded2dbSJung-uk Kim                                                     NULL, NULL, NULL);
1547bded2dbSJung-uk Kim             }
1557bded2dbSJung-uk Kim             CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
1567bded2dbSJung-uk Kim         }
1577bded2dbSJung-uk Kim 
1587bded2dbSJung-uk Kim         return ret;
1597bded2dbSJung-uk Kim     } else {                    /* commonly eliminated */
1607bded2dbSJung-uk Kim 
161ed5d4f9aSSimon L. B. Nielsen         CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
1625c87c606SMark Murray 
1636f9291ceSJung-uk Kim         if (ssl_x509_store_ctx_idx < 0) {
164ed5d4f9aSSimon L. B. Nielsen             CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
1655c87c606SMark Murray             CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
166ed5d4f9aSSimon L. B. Nielsen             got_write_lock = 1;
16774664626SKris Kennaway 
1686f9291ceSJung-uk Kim             if (ssl_x509_store_ctx_idx < 0) {
1696f9291ceSJung-uk Kim                 ssl_x509_store_ctx_idx =
1707bded2dbSJung-uk Kim                     X509_STORE_CTX_get_ex_new_index(0,
1717bded2dbSJung-uk Kim                                                     "SSL for verify callback",
1726f9291ceSJung-uk Kim                                                     NULL, NULL, NULL);
17374664626SKris Kennaway             }
1745c87c606SMark Murray         }
175ed5d4f9aSSimon L. B. Nielsen 
176ed5d4f9aSSimon L. B. Nielsen         if (got_write_lock)
177ed5d4f9aSSimon L. B. Nielsen             CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
178ed5d4f9aSSimon L. B. Nielsen         else
179ed5d4f9aSSimon L. B. Nielsen             CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
180ed5d4f9aSSimon L. B. Nielsen 
1815c87c606SMark Murray         return ssl_x509_store_ctx_idx;
18274664626SKris Kennaway     }
1837bded2dbSJung-uk Kim }
18474664626SKris Kennaway 
1857bded2dbSJung-uk Kim void ssl_cert_set_default_md(CERT *cert)
1861f13597dSJung-uk Kim {
1871f13597dSJung-uk Kim     /* Set digest values to defaults */
1881f13597dSJung-uk Kim #ifndef OPENSSL_NO_DSA
18909286989SJung-uk Kim     cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
1901f13597dSJung-uk Kim #endif
1911f13597dSJung-uk Kim #ifndef OPENSSL_NO_RSA
1921f13597dSJung-uk Kim     cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
1931f13597dSJung-uk Kim     cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
1941f13597dSJung-uk Kim #endif
1951f13597dSJung-uk Kim #ifndef OPENSSL_NO_ECDSA
19609286989SJung-uk Kim     cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
1971f13597dSJung-uk Kim #endif
1981f13597dSJung-uk Kim }
1991f13597dSJung-uk Kim 
20074664626SKris Kennaway CERT *ssl_cert_new(void)
20174664626SKris Kennaway {
20274664626SKris Kennaway     CERT *ret;
20374664626SKris Kennaway 
204ddd58736SKris Kennaway     ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
2056f9291ceSJung-uk Kim     if (ret == NULL) {
20674664626SKris Kennaway         SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
20774664626SKris Kennaway         return (NULL);
20874664626SKris Kennaway     }
20974664626SKris Kennaway     memset(ret, 0, sizeof(CERT));
21074664626SKris Kennaway 
21174664626SKris Kennaway     ret->key = &(ret->pkeys[SSL_PKEY_RSA_ENC]);
21274664626SKris Kennaway     ret->references = 1;
2131f13597dSJung-uk Kim     ssl_cert_set_default_md(ret);
21474664626SKris Kennaway     return (ret);
21574664626SKris Kennaway }
21674664626SKris Kennaway 
21774664626SKris Kennaway CERT *ssl_cert_dup(CERT *cert)
21874664626SKris Kennaway {
21974664626SKris Kennaway     CERT *ret;
22074664626SKris Kennaway     int i;
22174664626SKris Kennaway 
222ddd58736SKris Kennaway     ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
2236f9291ceSJung-uk Kim     if (ret == NULL) {
22474664626SKris Kennaway         SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
22574664626SKris Kennaway         return (NULL);
22674664626SKris Kennaway     }
22774664626SKris Kennaway 
22874664626SKris Kennaway     memset(ret, 0, sizeof(CERT));
22974664626SKris Kennaway 
23080815a77SJung-uk Kim     ret->references = 1;
23174664626SKris Kennaway     ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]];
2326f9291ceSJung-uk Kim     /*
2336f9291ceSJung-uk Kim      * or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that
2346f9291ceSJung-uk Kim      * more readable
2356f9291ceSJung-uk Kim      */
23674664626SKris Kennaway 
23774664626SKris Kennaway     ret->valid = cert->valid;
2381f13597dSJung-uk Kim     ret->mask_k = cert->mask_k;
2391f13597dSJung-uk Kim     ret->mask_a = cert->mask_a;
2401f13597dSJung-uk Kim     ret->export_mask_k = cert->export_mask_k;
2411f13597dSJung-uk Kim     ret->export_mask_a = cert->export_mask_a;
24274664626SKris Kennaway 
2435c87c606SMark Murray #ifndef OPENSSL_NO_RSA
2446f9291ceSJung-uk Kim     if (cert->rsa_tmp != NULL) {
2455c87c606SMark Murray         RSA_up_ref(cert->rsa_tmp);
24674664626SKris Kennaway         ret->rsa_tmp = cert->rsa_tmp;
24774664626SKris Kennaway     }
24874664626SKris Kennaway     ret->rsa_tmp_cb = cert->rsa_tmp_cb;
24974664626SKris Kennaway #endif
25074664626SKris Kennaway 
2515c87c606SMark Murray #ifndef OPENSSL_NO_DH
2526f9291ceSJung-uk Kim     if (cert->dh_tmp != NULL) {
25374664626SKris Kennaway         ret->dh_tmp = DHparams_dup(cert->dh_tmp);
2546f9291ceSJung-uk Kim         if (ret->dh_tmp == NULL) {
255f579bf8eSKris Kennaway             SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
25674664626SKris Kennaway             goto err;
25774664626SKris Kennaway         }
2586f9291ceSJung-uk Kim         if (cert->dh_tmp->priv_key) {
259f579bf8eSKris Kennaway             BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
2606f9291ceSJung-uk Kim             if (!b) {
261f579bf8eSKris Kennaway                 SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
262f579bf8eSKris Kennaway                 goto err;
263f579bf8eSKris Kennaway             }
264f579bf8eSKris Kennaway             ret->dh_tmp->priv_key = b;
265f579bf8eSKris Kennaway         }
2666f9291ceSJung-uk Kim         if (cert->dh_tmp->pub_key) {
267f579bf8eSKris Kennaway             BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
2686f9291ceSJung-uk Kim             if (!b) {
269f579bf8eSKris Kennaway                 SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
270f579bf8eSKris Kennaway                 goto err;
271f579bf8eSKris Kennaway             }
272f579bf8eSKris Kennaway             ret->dh_tmp->pub_key = b;
273f579bf8eSKris Kennaway         }
27474664626SKris Kennaway     }
27574664626SKris Kennaway     ret->dh_tmp_cb = cert->dh_tmp_cb;
27674664626SKris Kennaway #endif
27774664626SKris Kennaway 
2783b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_ECDH
2796f9291ceSJung-uk Kim     if (cert->ecdh_tmp) {
2803b4e3dcbSSimon L. B. Nielsen         ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
2816f9291ceSJung-uk Kim         if (ret->ecdh_tmp == NULL) {
2823b4e3dcbSSimon L. B. Nielsen             SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
2833b4e3dcbSSimon L. B. Nielsen             goto err;
2843b4e3dcbSSimon L. B. Nielsen         }
2853b4e3dcbSSimon L. B. Nielsen     }
2863b4e3dcbSSimon L. B. Nielsen     ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
2877bded2dbSJung-uk Kim     ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
2883b4e3dcbSSimon L. B. Nielsen #endif
2893b4e3dcbSSimon L. B. Nielsen 
2906f9291ceSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
2917bded2dbSJung-uk Kim         CERT_PKEY *cpk = cert->pkeys + i;
2927bded2dbSJung-uk Kim         CERT_PKEY *rpk = ret->pkeys + i;
2937bded2dbSJung-uk Kim         if (cpk->x509 != NULL) {
2947bded2dbSJung-uk Kim             rpk->x509 = cpk->x509;
2957bded2dbSJung-uk Kim             CRYPTO_add(&rpk->x509->references, 1, CRYPTO_LOCK_X509);
29674664626SKris Kennaway         }
29774664626SKris Kennaway 
2987bded2dbSJung-uk Kim         if (cpk->privatekey != NULL) {
2997bded2dbSJung-uk Kim             rpk->privatekey = cpk->privatekey;
3007bded2dbSJung-uk Kim             CRYPTO_add(&cpk->privatekey->references, 1, CRYPTO_LOCK_EVP_PKEY);
30174664626SKris Kennaway         }
30274664626SKris Kennaway 
3037bded2dbSJung-uk Kim         if (cpk->chain) {
3047bded2dbSJung-uk Kim             rpk->chain = X509_chain_up_ref(cpk->chain);
3057bded2dbSJung-uk Kim             if (!rpk->chain) {
3067bded2dbSJung-uk Kim                 SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
3077bded2dbSJung-uk Kim                 goto err;
3087bded2dbSJung-uk Kim             }
3097bded2dbSJung-uk Kim         }
3107bded2dbSJung-uk Kim         rpk->valid_flags = 0;
3117bded2dbSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
3127bded2dbSJung-uk Kim         if (cert->pkeys[i].serverinfo != NULL) {
3137bded2dbSJung-uk Kim             /* Just copy everything. */
3147bded2dbSJung-uk Kim             ret->pkeys[i].serverinfo =
3157bded2dbSJung-uk Kim                 OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
3167bded2dbSJung-uk Kim             if (ret->pkeys[i].serverinfo == NULL) {
3177bded2dbSJung-uk Kim                 SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
318*6cf8931aSJung-uk Kim                 goto err;
3197bded2dbSJung-uk Kim             }
3207bded2dbSJung-uk Kim             ret->pkeys[i].serverinfo_length =
3217bded2dbSJung-uk Kim                 cert->pkeys[i].serverinfo_length;
3227bded2dbSJung-uk Kim             memcpy(ret->pkeys[i].serverinfo,
3237bded2dbSJung-uk Kim                    cert->pkeys[i].serverinfo,
3247bded2dbSJung-uk Kim                    cert->pkeys[i].serverinfo_length);
3257bded2dbSJung-uk Kim         }
3267bded2dbSJung-uk Kim #endif
3277bded2dbSJung-uk Kim     }
32874664626SKris Kennaway 
3296f9291ceSJung-uk Kim     /*
3306f9291ceSJung-uk Kim      * Set digests to defaults. NB: we don't copy existing values as they
3311f13597dSJung-uk Kim      * will be set during handshake.
3321f13597dSJung-uk Kim      */
3331f13597dSJung-uk Kim     ssl_cert_set_default_md(ret);
3347bded2dbSJung-uk Kim     /* Peer sigalgs set to NULL as we get these from handshake too */
3357bded2dbSJung-uk Kim     ret->peer_sigalgs = NULL;
3367bded2dbSJung-uk Kim     ret->peer_sigalgslen = 0;
3377bded2dbSJung-uk Kim     /* Configured sigalgs however we copy across */
3387bded2dbSJung-uk Kim 
3397bded2dbSJung-uk Kim     if (cert->conf_sigalgs) {
3407bded2dbSJung-uk Kim         ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
3417bded2dbSJung-uk Kim         if (!ret->conf_sigalgs)
3427bded2dbSJung-uk Kim             goto err;
3437bded2dbSJung-uk Kim         memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
3447bded2dbSJung-uk Kim         ret->conf_sigalgslen = cert->conf_sigalgslen;
3457bded2dbSJung-uk Kim     } else
3467bded2dbSJung-uk Kim         ret->conf_sigalgs = NULL;
3477bded2dbSJung-uk Kim 
3487bded2dbSJung-uk Kim     if (cert->client_sigalgs) {
3497bded2dbSJung-uk Kim         ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
3507bded2dbSJung-uk Kim         if (!ret->client_sigalgs)
3517bded2dbSJung-uk Kim             goto err;
3527bded2dbSJung-uk Kim         memcpy(ret->client_sigalgs, cert->client_sigalgs,
3537bded2dbSJung-uk Kim                cert->client_sigalgslen);
3547bded2dbSJung-uk Kim         ret->client_sigalgslen = cert->client_sigalgslen;
3557bded2dbSJung-uk Kim     } else
3567bded2dbSJung-uk Kim         ret->client_sigalgs = NULL;
3577bded2dbSJung-uk Kim     /* Shared sigalgs also NULL */
3587bded2dbSJung-uk Kim     ret->shared_sigalgs = NULL;
3597bded2dbSJung-uk Kim     /* Copy any custom client certificate types */
3607bded2dbSJung-uk Kim     if (cert->ctypes) {
3617bded2dbSJung-uk Kim         ret->ctypes = OPENSSL_malloc(cert->ctype_num);
3627bded2dbSJung-uk Kim         if (!ret->ctypes)
3637bded2dbSJung-uk Kim             goto err;
3647bded2dbSJung-uk Kim         memcpy(ret->ctypes, cert->ctypes, cert->ctype_num);
3657bded2dbSJung-uk Kim         ret->ctype_num = cert->ctype_num;
3667bded2dbSJung-uk Kim     }
3677bded2dbSJung-uk Kim 
3687bded2dbSJung-uk Kim     ret->cert_flags = cert->cert_flags;
3697bded2dbSJung-uk Kim 
3707bded2dbSJung-uk Kim     ret->cert_cb = cert->cert_cb;
3717bded2dbSJung-uk Kim     ret->cert_cb_arg = cert->cert_cb_arg;
3727bded2dbSJung-uk Kim 
3737bded2dbSJung-uk Kim     if (cert->verify_store) {
3747bded2dbSJung-uk Kim         CRYPTO_add(&cert->verify_store->references, 1,
3757bded2dbSJung-uk Kim                    CRYPTO_LOCK_X509_STORE);
3767bded2dbSJung-uk Kim         ret->verify_store = cert->verify_store;
3777bded2dbSJung-uk Kim     }
3787bded2dbSJung-uk Kim 
3797bded2dbSJung-uk Kim     if (cert->chain_store) {
3807bded2dbSJung-uk Kim         CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
3817bded2dbSJung-uk Kim         ret->chain_store = cert->chain_store;
3827bded2dbSJung-uk Kim     }
3837bded2dbSJung-uk Kim 
3847bded2dbSJung-uk Kim     ret->ciphers_raw = NULL;
3857bded2dbSJung-uk Kim 
3867bded2dbSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
3877bded2dbSJung-uk Kim     if (!custom_exts_copy(&ret->cli_ext, &cert->cli_ext))
3887bded2dbSJung-uk Kim         goto err;
3897bded2dbSJung-uk Kim     if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext))
3907bded2dbSJung-uk Kim         goto err;
3917bded2dbSJung-uk Kim #endif
39274664626SKris Kennaway 
39374664626SKris Kennaway     return (ret);
39474664626SKris Kennaway 
39574664626SKris Kennaway  err:
3965c87c606SMark Murray #ifndef OPENSSL_NO_RSA
39774664626SKris Kennaway     if (ret->rsa_tmp != NULL)
39874664626SKris Kennaway         RSA_free(ret->rsa_tmp);
39974664626SKris Kennaway #endif
4005c87c606SMark Murray #ifndef OPENSSL_NO_DH
40174664626SKris Kennaway     if (ret->dh_tmp != NULL)
40274664626SKris Kennaway         DH_free(ret->dh_tmp);
40374664626SKris Kennaway #endif
4043b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_ECDH
4053b4e3dcbSSimon L. B. Nielsen     if (ret->ecdh_tmp != NULL)
4063b4e3dcbSSimon L. B. Nielsen         EC_KEY_free(ret->ecdh_tmp);
4073b4e3dcbSSimon L. B. Nielsen #endif
40874664626SKris Kennaway 
4097bded2dbSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
4107bded2dbSJung-uk Kim     custom_exts_free(&ret->cli_ext);
4117bded2dbSJung-uk Kim     custom_exts_free(&ret->srv_ext);
4127bded2dbSJung-uk Kim #endif
4137bded2dbSJung-uk Kim 
4147bded2dbSJung-uk Kim     ssl_cert_clear_certs(ret);
41574664626SKris Kennaway 
41674664626SKris Kennaway     return NULL;
41774664626SKris Kennaway }
41874664626SKris Kennaway 
4197bded2dbSJung-uk Kim /* Free up and clear all certificates and chains */
4207bded2dbSJung-uk Kim 
4217bded2dbSJung-uk Kim void ssl_cert_clear_certs(CERT *c)
4227bded2dbSJung-uk Kim {
4237bded2dbSJung-uk Kim     int i;
4247bded2dbSJung-uk Kim     if (c == NULL)
4257bded2dbSJung-uk Kim         return;
4267bded2dbSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
4277bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
4287bded2dbSJung-uk Kim         if (cpk->x509) {
4297bded2dbSJung-uk Kim             X509_free(cpk->x509);
4307bded2dbSJung-uk Kim             cpk->x509 = NULL;
4317bded2dbSJung-uk Kim         }
4327bded2dbSJung-uk Kim         if (cpk->privatekey) {
4337bded2dbSJung-uk Kim             EVP_PKEY_free(cpk->privatekey);
4347bded2dbSJung-uk Kim             cpk->privatekey = NULL;
4357bded2dbSJung-uk Kim         }
4367bded2dbSJung-uk Kim         if (cpk->chain) {
4377bded2dbSJung-uk Kim             sk_X509_pop_free(cpk->chain, X509_free);
4387bded2dbSJung-uk Kim             cpk->chain = NULL;
4397bded2dbSJung-uk Kim         }
4407bded2dbSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
4417bded2dbSJung-uk Kim         if (cpk->serverinfo) {
4427bded2dbSJung-uk Kim             OPENSSL_free(cpk->serverinfo);
4437bded2dbSJung-uk Kim             cpk->serverinfo = NULL;
4447bded2dbSJung-uk Kim             cpk->serverinfo_length = 0;
4457bded2dbSJung-uk Kim         }
4467bded2dbSJung-uk Kim #endif
4477bded2dbSJung-uk Kim         /* Clear all flags apart from explicit sign */
4487bded2dbSJung-uk Kim         cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN;
4497bded2dbSJung-uk Kim     }
4507bded2dbSJung-uk Kim }
4517bded2dbSJung-uk Kim 
45274664626SKris Kennaway void ssl_cert_free(CERT *c)
45374664626SKris Kennaway {
45474664626SKris Kennaway     int i;
45574664626SKris Kennaway 
45674664626SKris Kennaway     if (c == NULL)
45774664626SKris Kennaway         return;
45874664626SKris Kennaway 
45974664626SKris Kennaway     i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT);
46074664626SKris Kennaway #ifdef REF_PRINT
46174664626SKris Kennaway     REF_PRINT("CERT", c);
46274664626SKris Kennaway #endif
4636f9291ceSJung-uk Kim     if (i > 0)
4646f9291ceSJung-uk Kim         return;
46574664626SKris Kennaway #ifdef REF_CHECK
4666f9291ceSJung-uk Kim     if (i < 0) {
46774664626SKris Kennaway         fprintf(stderr, "ssl_cert_free, bad reference count\n");
46874664626SKris Kennaway         abort();                /* ok */
46974664626SKris Kennaway     }
47074664626SKris Kennaway #endif
47174664626SKris Kennaway 
4725c87c606SMark Murray #ifndef OPENSSL_NO_RSA
4736f9291ceSJung-uk Kim     if (c->rsa_tmp)
4746f9291ceSJung-uk Kim         RSA_free(c->rsa_tmp);
47574664626SKris Kennaway #endif
4765c87c606SMark Murray #ifndef OPENSSL_NO_DH
4776f9291ceSJung-uk Kim     if (c->dh_tmp)
4786f9291ceSJung-uk Kim         DH_free(c->dh_tmp);
47974664626SKris Kennaway #endif
4803b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_ECDH
4816f9291ceSJung-uk Kim     if (c->ecdh_tmp)
4826f9291ceSJung-uk Kim         EC_KEY_free(c->ecdh_tmp);
4833b4e3dcbSSimon L. B. Nielsen #endif
48474664626SKris Kennaway 
4857bded2dbSJung-uk Kim     ssl_cert_clear_certs(c);
4867bded2dbSJung-uk Kim     if (c->peer_sigalgs)
4877bded2dbSJung-uk Kim         OPENSSL_free(c->peer_sigalgs);
4887bded2dbSJung-uk Kim     if (c->conf_sigalgs)
4897bded2dbSJung-uk Kim         OPENSSL_free(c->conf_sigalgs);
4907bded2dbSJung-uk Kim     if (c->client_sigalgs)
4917bded2dbSJung-uk Kim         OPENSSL_free(c->client_sigalgs);
4927bded2dbSJung-uk Kim     if (c->shared_sigalgs)
4937bded2dbSJung-uk Kim         OPENSSL_free(c->shared_sigalgs);
4947bded2dbSJung-uk Kim     if (c->ctypes)
4957bded2dbSJung-uk Kim         OPENSSL_free(c->ctypes);
4967bded2dbSJung-uk Kim     if (c->verify_store)
4977bded2dbSJung-uk Kim         X509_STORE_free(c->verify_store);
4987bded2dbSJung-uk Kim     if (c->chain_store)
4997bded2dbSJung-uk Kim         X509_STORE_free(c->chain_store);
5007bded2dbSJung-uk Kim     if (c->ciphers_raw)
5017bded2dbSJung-uk Kim         OPENSSL_free(c->ciphers_raw);
5027bded2dbSJung-uk Kim #ifndef OPENSSL_NO_TLSEXT
5037bded2dbSJung-uk Kim     custom_exts_free(&c->cli_ext);
5047bded2dbSJung-uk Kim     custom_exts_free(&c->srv_ext);
505b8721c16SJung-uk Kim     if (c->alpn_proposed)
506b8721c16SJung-uk Kim         OPENSSL_free(c->alpn_proposed);
50774664626SKris Kennaway #endif
508ddd58736SKris Kennaway     OPENSSL_free(c);
50974664626SKris Kennaway }
51074664626SKris Kennaway 
51174664626SKris Kennaway int ssl_cert_inst(CERT **o)
51274664626SKris Kennaway {
5136f9291ceSJung-uk Kim     /*
5146f9291ceSJung-uk Kim      * Create a CERT if there isn't already one (which cannot really happen,
5156f9291ceSJung-uk Kim      * as it is initially created in SSL_CTX_new; but the earlier code
5166f9291ceSJung-uk Kim      * usually allows for that one being non-existant, so we follow that
5176f9291ceSJung-uk Kim      * behaviour, as it might turn out that there actually is a reason for it
5186f9291ceSJung-uk Kim      * -- but I'm not sure that *all* of the existing code could cope with
5196f9291ceSJung-uk Kim      * s->cert being NULL, otherwise we could do without the initialization
5206f9291ceSJung-uk Kim      * in SSL_CTX_new).
52174664626SKris Kennaway      */
52274664626SKris Kennaway 
5236f9291ceSJung-uk Kim     if (o == NULL) {
52474664626SKris Kennaway         SSLerr(SSL_F_SSL_CERT_INST, ERR_R_PASSED_NULL_PARAMETER);
52574664626SKris Kennaway         return (0);
52674664626SKris Kennaway     }
5276f9291ceSJung-uk Kim     if (*o == NULL) {
5286f9291ceSJung-uk Kim         if ((*o = ssl_cert_new()) == NULL) {
52974664626SKris Kennaway             SSLerr(SSL_F_SSL_CERT_INST, ERR_R_MALLOC_FAILURE);
53074664626SKris Kennaway             return (0);
53174664626SKris Kennaway         }
53274664626SKris Kennaway     }
53374664626SKris Kennaway     return (1);
53474664626SKris Kennaway }
53574664626SKris Kennaway 
5367bded2dbSJung-uk Kim int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain)
5377bded2dbSJung-uk Kim {
5387bded2dbSJung-uk Kim     CERT_PKEY *cpk = c->key;
5397bded2dbSJung-uk Kim     if (!cpk)
5407bded2dbSJung-uk Kim         return 0;
5417bded2dbSJung-uk Kim     if (cpk->chain)
5427bded2dbSJung-uk Kim         sk_X509_pop_free(cpk->chain, X509_free);
5437bded2dbSJung-uk Kim     cpk->chain = chain;
5447bded2dbSJung-uk Kim     return 1;
5457bded2dbSJung-uk Kim }
5467bded2dbSJung-uk Kim 
5477bded2dbSJung-uk Kim int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain)
5487bded2dbSJung-uk Kim {
5497bded2dbSJung-uk Kim     STACK_OF(X509) *dchain;
5507bded2dbSJung-uk Kim     if (!chain)
5517bded2dbSJung-uk Kim         return ssl_cert_set0_chain(c, NULL);
5527bded2dbSJung-uk Kim     dchain = X509_chain_up_ref(chain);
5537bded2dbSJung-uk Kim     if (!dchain)
5547bded2dbSJung-uk Kim         return 0;
5557bded2dbSJung-uk Kim     if (!ssl_cert_set0_chain(c, dchain)) {
5567bded2dbSJung-uk Kim         sk_X509_pop_free(dchain, X509_free);
5577bded2dbSJung-uk Kim         return 0;
5587bded2dbSJung-uk Kim     }
5597bded2dbSJung-uk Kim     return 1;
5607bded2dbSJung-uk Kim }
5617bded2dbSJung-uk Kim 
5627bded2dbSJung-uk Kim int ssl_cert_add0_chain_cert(CERT *c, X509 *x)
5637bded2dbSJung-uk Kim {
5647bded2dbSJung-uk Kim     CERT_PKEY *cpk = c->key;
5657bded2dbSJung-uk Kim     if (!cpk)
5667bded2dbSJung-uk Kim         return 0;
5677bded2dbSJung-uk Kim     if (!cpk->chain)
5687bded2dbSJung-uk Kim         cpk->chain = sk_X509_new_null();
5697bded2dbSJung-uk Kim     if (!cpk->chain || !sk_X509_push(cpk->chain, x))
5707bded2dbSJung-uk Kim         return 0;
5717bded2dbSJung-uk Kim     return 1;
5727bded2dbSJung-uk Kim }
5737bded2dbSJung-uk Kim 
5747bded2dbSJung-uk Kim int ssl_cert_add1_chain_cert(CERT *c, X509 *x)
5757bded2dbSJung-uk Kim {
5767bded2dbSJung-uk Kim     if (!ssl_cert_add0_chain_cert(c, x))
5777bded2dbSJung-uk Kim         return 0;
5787bded2dbSJung-uk Kim     CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
5797bded2dbSJung-uk Kim     return 1;
5807bded2dbSJung-uk Kim }
5817bded2dbSJung-uk Kim 
5827bded2dbSJung-uk Kim int ssl_cert_select_current(CERT *c, X509 *x)
5837bded2dbSJung-uk Kim {
5847bded2dbSJung-uk Kim     int i;
5857bded2dbSJung-uk Kim     if (x == NULL)
5867bded2dbSJung-uk Kim         return 0;
5877bded2dbSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
5887bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
5897bded2dbSJung-uk Kim         if (cpk->x509 == x && cpk->privatekey) {
5907bded2dbSJung-uk Kim             c->key = cpk;
5917bded2dbSJung-uk Kim             return 1;
5927bded2dbSJung-uk Kim         }
5937bded2dbSJung-uk Kim     }
5947bded2dbSJung-uk Kim 
5957bded2dbSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
5967bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
5977bded2dbSJung-uk Kim         if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
5987bded2dbSJung-uk Kim             c->key = cpk;
5997bded2dbSJung-uk Kim             return 1;
6007bded2dbSJung-uk Kim         }
6017bded2dbSJung-uk Kim     }
6027bded2dbSJung-uk Kim     return 0;
6037bded2dbSJung-uk Kim }
6047bded2dbSJung-uk Kim 
6057bded2dbSJung-uk Kim int ssl_cert_set_current(CERT *c, long op)
6067bded2dbSJung-uk Kim {
6077bded2dbSJung-uk Kim     int i, idx;
6087bded2dbSJung-uk Kim     if (!c)
6097bded2dbSJung-uk Kim         return 0;
6107bded2dbSJung-uk Kim     if (op == SSL_CERT_SET_FIRST)
6117bded2dbSJung-uk Kim         idx = 0;
6127bded2dbSJung-uk Kim     else if (op == SSL_CERT_SET_NEXT) {
6137bded2dbSJung-uk Kim         idx = (int)(c->key - c->pkeys + 1);
6147bded2dbSJung-uk Kim         if (idx >= SSL_PKEY_NUM)
6157bded2dbSJung-uk Kim             return 0;
6167bded2dbSJung-uk Kim     } else
6177bded2dbSJung-uk Kim         return 0;
6187bded2dbSJung-uk Kim     for (i = idx; i < SSL_PKEY_NUM; i++) {
6197bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
6207bded2dbSJung-uk Kim         if (cpk->x509 && cpk->privatekey) {
6217bded2dbSJung-uk Kim             c->key = cpk;
6227bded2dbSJung-uk Kim             return 1;
6237bded2dbSJung-uk Kim         }
6247bded2dbSJung-uk Kim     }
6257bded2dbSJung-uk Kim     return 0;
6267bded2dbSJung-uk Kim }
6277bded2dbSJung-uk Kim 
6287bded2dbSJung-uk Kim void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
6297bded2dbSJung-uk Kim {
6307bded2dbSJung-uk Kim     c->cert_cb = cb;
6317bded2dbSJung-uk Kim     c->cert_cb_arg = arg;
6327bded2dbSJung-uk Kim }
6337bded2dbSJung-uk Kim 
63474664626SKris Kennaway SESS_CERT *ssl_sess_cert_new(void)
63574664626SKris Kennaway {
63674664626SKris Kennaway     SESS_CERT *ret;
63774664626SKris Kennaway 
638ddd58736SKris Kennaway     ret = OPENSSL_malloc(sizeof *ret);
6396f9291ceSJung-uk Kim     if (ret == NULL) {
64074664626SKris Kennaway         SSLerr(SSL_F_SSL_SESS_CERT_NEW, ERR_R_MALLOC_FAILURE);
64174664626SKris Kennaway         return NULL;
64274664626SKris Kennaway     }
64374664626SKris Kennaway 
64474664626SKris Kennaway     memset(ret, 0, sizeof *ret);
64574664626SKris Kennaway     ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]);
64674664626SKris Kennaway     ret->references = 1;
64774664626SKris Kennaway 
64874664626SKris Kennaway     return ret;
64974664626SKris Kennaway }
65074664626SKris Kennaway 
65174664626SKris Kennaway void ssl_sess_cert_free(SESS_CERT *sc)
65274664626SKris Kennaway {
65374664626SKris Kennaway     int i;
65474664626SKris Kennaway 
65574664626SKris Kennaway     if (sc == NULL)
65674664626SKris Kennaway         return;
65774664626SKris Kennaway 
65874664626SKris Kennaway     i = CRYPTO_add(&sc->references, -1, CRYPTO_LOCK_SSL_SESS_CERT);
65974664626SKris Kennaway #ifdef REF_PRINT
66074664626SKris Kennaway     REF_PRINT("SESS_CERT", sc);
66174664626SKris Kennaway #endif
66274664626SKris Kennaway     if (i > 0)
66374664626SKris Kennaway         return;
66474664626SKris Kennaway #ifdef REF_CHECK
6656f9291ceSJung-uk Kim     if (i < 0) {
66674664626SKris Kennaway         fprintf(stderr, "ssl_sess_cert_free, bad reference count\n");
66774664626SKris Kennaway         abort();                /* ok */
66874664626SKris Kennaway     }
66974664626SKris Kennaway #endif
67074664626SKris Kennaway 
67174664626SKris Kennaway     /* i == 0 */
67274664626SKris Kennaway     if (sc->cert_chain != NULL)
67374664626SKris Kennaway         sk_X509_pop_free(sc->cert_chain, X509_free);
6746f9291ceSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
67574664626SKris Kennaway         if (sc->peer_pkeys[i].x509 != NULL)
67674664626SKris Kennaway             X509_free(sc->peer_pkeys[i].x509);
6776f9291ceSJung-uk Kim #if 0                           /* We don't have the peer's private key.
6786f9291ceSJung-uk Kim                                  * These lines are just * here as a reminder
6796f9291ceSJung-uk Kim                                  * that we're still using a
6806f9291ceSJung-uk Kim                                  * not-quite-appropriate * data structure. */
68174664626SKris Kennaway         if (sc->peer_pkeys[i].privatekey != NULL)
68274664626SKris Kennaway             EVP_PKEY_free(sc->peer_pkeys[i].privatekey);
68374664626SKris Kennaway #endif
68474664626SKris Kennaway     }
68574664626SKris Kennaway 
6865c87c606SMark Murray #ifndef OPENSSL_NO_RSA
68774664626SKris Kennaway     if (sc->peer_rsa_tmp != NULL)
68874664626SKris Kennaway         RSA_free(sc->peer_rsa_tmp);
68974664626SKris Kennaway #endif
6905c87c606SMark Murray #ifndef OPENSSL_NO_DH
69174664626SKris Kennaway     if (sc->peer_dh_tmp != NULL)
69274664626SKris Kennaway         DH_free(sc->peer_dh_tmp);
69374664626SKris Kennaway #endif
6943b4e3dcbSSimon L. B. Nielsen #ifndef OPENSSL_NO_ECDH
6953b4e3dcbSSimon L. B. Nielsen     if (sc->peer_ecdh_tmp != NULL)
6963b4e3dcbSSimon L. B. Nielsen         EC_KEY_free(sc->peer_ecdh_tmp);
6973b4e3dcbSSimon L. B. Nielsen #endif
69874664626SKris Kennaway 
699ddd58736SKris Kennaway     OPENSSL_free(sc);
70074664626SKris Kennaway }
70174664626SKris Kennaway 
70274664626SKris Kennaway int ssl_set_peer_cert_type(SESS_CERT *sc, int type)
70374664626SKris Kennaway {
70474664626SKris Kennaway     sc->peer_cert_type = type;
70574664626SKris Kennaway     return (1);
70674664626SKris Kennaway }
70774664626SKris Kennaway 
70874664626SKris Kennaway int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
70974664626SKris Kennaway {
71074664626SKris Kennaway     X509 *x;
71174664626SKris Kennaway     int i;
7127bded2dbSJung-uk Kim     X509_STORE *verify_store;
71374664626SKris Kennaway     X509_STORE_CTX ctx;
71474664626SKris Kennaway 
7157bded2dbSJung-uk Kim     if (s->cert->verify_store)
7167bded2dbSJung-uk Kim         verify_store = s->cert->verify_store;
7177bded2dbSJung-uk Kim     else
7187bded2dbSJung-uk Kim         verify_store = s->ctx->cert_store;
7197bded2dbSJung-uk Kim 
72074664626SKris Kennaway     if ((sk == NULL) || (sk_X509_num(sk) == 0))
72174664626SKris Kennaway         return (0);
72274664626SKris Kennaway 
72374664626SKris Kennaway     x = sk_X509_value(sk, 0);
7247bded2dbSJung-uk Kim     if (!X509_STORE_CTX_init(&ctx, verify_store, x, sk)) {
7255c87c606SMark Murray         SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
7265c87c606SMark Murray         return (0);
7275c87c606SMark Murray     }
7287bded2dbSJung-uk Kim     /* Set suite B flags if needed */
7297bded2dbSJung-uk Kim     X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
7303b4e3dcbSSimon L. B. Nielsen #if 0
73174664626SKris Kennaway     if (SSL_get_verify_depth(s) >= 0)
73274664626SKris Kennaway         X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s));
7333b4e3dcbSSimon L. B. Nielsen #endif
734f579bf8eSKris Kennaway     X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
7355c87c606SMark Murray 
7366f9291ceSJung-uk Kim     /*
7376f9291ceSJung-uk Kim      * We need to inherit the verify parameters. These can be determined by
7386f9291ceSJung-uk Kim      * the context: if its a server it will verify SSL client certificates or
7396f9291ceSJung-uk Kim      * vice versa.
740f579bf8eSKris Kennaway      */
741f579bf8eSKris Kennaway 
7426f9291ceSJung-uk Kim     X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server");
7436f9291ceSJung-uk Kim     /*
7446f9291ceSJung-uk Kim      * Anything non-default in "param" should overwrite anything in the ctx.
7456a599222SSimon L. B. Nielsen      */
7466a599222SSimon L. B. Nielsen     X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param);
74774664626SKris Kennaway 
748a21b1b38SKris Kennaway     if (s->verify_callback)
749a21b1b38SKris Kennaway         X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
750a21b1b38SKris Kennaway 
75174664626SKris Kennaway     if (s->ctx->app_verify_callback != NULL)
7525c87c606SMark Murray #if 1                           /* new with OpenSSL 0.9.7 */
7535c87c606SMark Murray         i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
7545c87c606SMark Murray #else
75574664626SKris Kennaway         i = s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */
7565c87c606SMark Murray #endif
7576f9291ceSJung-uk Kim     else {
7585c87c606SMark Murray #ifndef OPENSSL_NO_X509_VERIFY
75974664626SKris Kennaway         i = X509_verify_cert(&ctx);
76074664626SKris Kennaway #else
76174664626SKris Kennaway         i = 0;
76274664626SKris Kennaway         ctx.error = X509_V_ERR_APPLICATION_VERIFICATION;
76374664626SKris Kennaway         SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, SSL_R_NO_VERIFY_CALLBACK);
76474664626SKris Kennaway #endif
76574664626SKris Kennaway     }
76674664626SKris Kennaway 
76774664626SKris Kennaway     s->verify_result = ctx.error;
76874664626SKris Kennaway     X509_STORE_CTX_cleanup(&ctx);
76974664626SKris Kennaway 
77074664626SKris Kennaway     return (i);
77174664626SKris Kennaway }
77274664626SKris Kennaway 
7736f9291ceSJung-uk Kim static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
7746f9291ceSJung-uk Kim                                STACK_OF(X509_NAME) *name_list)
77574664626SKris Kennaway {
77674664626SKris Kennaway     if (*ca_list != NULL)
77774664626SKris Kennaway         sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
77874664626SKris Kennaway 
779ced566fdSJacques Vidrine     *ca_list = name_list;
78074664626SKris Kennaway }
78174664626SKris Kennaway 
78274664626SKris Kennaway STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk)
78374664626SKris Kennaway {
78474664626SKris Kennaway     int i;
78574664626SKris Kennaway     STACK_OF(X509_NAME) *ret;
78674664626SKris Kennaway     X509_NAME *name;
78774664626SKris Kennaway 
78874664626SKris Kennaway     ret = sk_X509_NAME_new_null();
7896f9291ceSJung-uk Kim     for (i = 0; i < sk_X509_NAME_num(sk); i++) {
79074664626SKris Kennaway         name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
7916f9291ceSJung-uk Kim         if ((name == NULL) || !sk_X509_NAME_push(ret, name)) {
79274664626SKris Kennaway             sk_X509_NAME_pop_free(ret, X509_NAME_free);
79374664626SKris Kennaway             return (NULL);
79474664626SKris Kennaway         }
79574664626SKris Kennaway     }
79674664626SKris Kennaway     return (ret);
79774664626SKris Kennaway }
79874664626SKris Kennaway 
799ced566fdSJacques Vidrine void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
80074664626SKris Kennaway {
801ced566fdSJacques Vidrine     set_client_CA_list(&(s->client_CA), name_list);
80274664626SKris Kennaway }
80374664626SKris Kennaway 
804ced566fdSJacques Vidrine void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
80574664626SKris Kennaway {
806ced566fdSJacques Vidrine     set_client_CA_list(&(ctx->client_CA), name_list);
80774664626SKris Kennaway }
80874664626SKris Kennaway 
8093b4e3dcbSSimon L. B. Nielsen STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
81074664626SKris Kennaway {
81174664626SKris Kennaway     return (ctx->client_CA);
81274664626SKris Kennaway }
81374664626SKris Kennaway 
8143b4e3dcbSSimon L. B. Nielsen STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
81574664626SKris Kennaway {
8166f9291ceSJung-uk Kim     if (s->type == SSL_ST_CONNECT) { /* we are in the client */
8176f9291ceSJung-uk Kim         if (((s->version >> 8) == SSL3_VERSION_MAJOR) && (s->s3 != NULL))
81874664626SKris Kennaway             return (s->s3->tmp.ca_names);
81974664626SKris Kennaway         else
82074664626SKris Kennaway             return (NULL);
8216f9291ceSJung-uk Kim     } else {
82274664626SKris Kennaway         if (s->client_CA != NULL)
82374664626SKris Kennaway             return (s->client_CA);
82474664626SKris Kennaway         else
82574664626SKris Kennaway             return (s->ctx->client_CA);
82674664626SKris Kennaway     }
82774664626SKris Kennaway }
82874664626SKris Kennaway 
82974664626SKris Kennaway static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x)
83074664626SKris Kennaway {
83174664626SKris Kennaway     X509_NAME *name;
83274664626SKris Kennaway 
8336f9291ceSJung-uk Kim     if (x == NULL)
8346f9291ceSJung-uk Kim         return (0);
83574664626SKris Kennaway     if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL))
83674664626SKris Kennaway         return (0);
83774664626SKris Kennaway 
83874664626SKris Kennaway     if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
83974664626SKris Kennaway         return (0);
84074664626SKris Kennaway 
8416f9291ceSJung-uk Kim     if (!sk_X509_NAME_push(*sk, name)) {
84274664626SKris Kennaway         X509_NAME_free(name);
84374664626SKris Kennaway         return (0);
84474664626SKris Kennaway     }
84574664626SKris Kennaway     return (1);
84674664626SKris Kennaway }
84774664626SKris Kennaway 
84874664626SKris Kennaway int SSL_add_client_CA(SSL *ssl, X509 *x)
84974664626SKris Kennaway {
85074664626SKris Kennaway     return (add_client_CA(&(ssl->client_CA), x));
85174664626SKris Kennaway }
85274664626SKris Kennaway 
85374664626SKris Kennaway int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
85474664626SKris Kennaway {
85574664626SKris Kennaway     return (add_client_CA(&(ctx->client_CA), x));
85674664626SKris Kennaway }
85774664626SKris Kennaway 
858ddd58736SKris Kennaway static int xname_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
85974664626SKris Kennaway {
86074664626SKris Kennaway     return (X509_NAME_cmp(*a, *b));
86174664626SKris Kennaway }
86274664626SKris Kennaway 
8635c87c606SMark Murray #ifndef OPENSSL_NO_STDIO
8646f9291ceSJung-uk Kim /**
86574664626SKris Kennaway  * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
86674664626SKris Kennaway  * it doesn't really have anything to do with clients (except that a common use
86774664626SKris Kennaway  * for a stack of CAs is to send it to the client). Actually, it doesn't have
86874664626SKris Kennaway  * much to do with CAs, either, since it will load any old cert.
86974664626SKris Kennaway  * \param file the file containing one or more certs.
87074664626SKris Kennaway  * \return a ::STACK containing the certs.
87174664626SKris Kennaway  */
87274664626SKris Kennaway STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
87374664626SKris Kennaway {
87474664626SKris Kennaway     BIO *in;
87574664626SKris Kennaway     X509 *x = NULL;
87674664626SKris Kennaway     X509_NAME *xn = NULL;
8773b4e3dcbSSimon L. B. Nielsen     STACK_OF(X509_NAME) *ret = NULL, *sk;
87874664626SKris Kennaway 
879f579bf8eSKris Kennaway     sk = sk_X509_NAME_new(xname_cmp);
88074664626SKris Kennaway 
88174664626SKris Kennaway     in = BIO_new(BIO_s_file_internal());
88274664626SKris Kennaway 
8836f9291ceSJung-uk Kim     if ((sk == NULL) || (in == NULL)) {
88474664626SKris Kennaway         SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
88574664626SKris Kennaway         goto err;
88674664626SKris Kennaway     }
88774664626SKris Kennaway 
88874664626SKris Kennaway     if (!BIO_read_filename(in, file))
88974664626SKris Kennaway         goto err;
89074664626SKris Kennaway 
8916f9291ceSJung-uk Kim     for (;;) {
89274664626SKris Kennaway         if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
89374664626SKris Kennaway             break;
8946f9291ceSJung-uk Kim         if (ret == NULL) {
8953b4e3dcbSSimon L. B. Nielsen             ret = sk_X509_NAME_new_null();
8966f9291ceSJung-uk Kim             if (ret == NULL) {
8973b4e3dcbSSimon L. B. Nielsen                 SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
8983b4e3dcbSSimon L. B. Nielsen                 goto err;
8993b4e3dcbSSimon L. B. Nielsen             }
9003b4e3dcbSSimon L. B. Nielsen         }
9016f9291ceSJung-uk Kim         if ((xn = X509_get_subject_name(x)) == NULL)
9026f9291ceSJung-uk Kim             goto err;
90374664626SKris Kennaway         /* check for duplicates */
90474664626SKris Kennaway         xn = X509_NAME_dup(xn);
9056f9291ceSJung-uk Kim         if (xn == NULL)
9066f9291ceSJung-uk Kim             goto err;
90774664626SKris Kennaway         if (sk_X509_NAME_find(sk, xn) >= 0)
90874664626SKris Kennaway             X509_NAME_free(xn);
9096f9291ceSJung-uk Kim         else {
91074664626SKris Kennaway             sk_X509_NAME_push(sk, xn);
91174664626SKris Kennaway             sk_X509_NAME_push(ret, xn);
91274664626SKris Kennaway         }
91374664626SKris Kennaway     }
91474664626SKris Kennaway 
9156f9291ceSJung-uk Kim     if (0) {
91674664626SKris Kennaway  err:
9176f9291ceSJung-uk Kim         if (ret != NULL)
9186f9291ceSJung-uk Kim             sk_X509_NAME_pop_free(ret, X509_NAME_free);
91974664626SKris Kennaway         ret = NULL;
92074664626SKris Kennaway     }
9216f9291ceSJung-uk Kim     if (sk != NULL)
9226f9291ceSJung-uk Kim         sk_X509_NAME_free(sk);
9236f9291ceSJung-uk Kim     if (in != NULL)
9246f9291ceSJung-uk Kim         BIO_free(in);
9256f9291ceSJung-uk Kim     if (x != NULL)
9266f9291ceSJung-uk Kim         X509_free(x);
9273b4e3dcbSSimon L. B. Nielsen     if (ret != NULL)
9283b4e3dcbSSimon L. B. Nielsen         ERR_clear_error();
92974664626SKris Kennaway     return (ret);
93074664626SKris Kennaway }
93174664626SKris Kennaway #endif
93274664626SKris Kennaway 
9336f9291ceSJung-uk Kim /**
93474664626SKris Kennaway  * Add a file of certs to a stack.
93574664626SKris Kennaway  * \param stack the stack to add to.
93674664626SKris Kennaway  * \param file the file to add from. All certs in this file that are not
93774664626SKris Kennaway  * already in the stack will be added.
93874664626SKris Kennaway  * \return 1 for success, 0 for failure. Note that in the case of failure some
93974664626SKris Kennaway  * certs may have been added to \c stack.
94074664626SKris Kennaway  */
94174664626SKris Kennaway 
94274664626SKris Kennaway int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
94374664626SKris Kennaway                                         const char *file)
94474664626SKris Kennaway {
94574664626SKris Kennaway     BIO *in;
94674664626SKris Kennaway     X509 *x = NULL;
94774664626SKris Kennaway     X509_NAME *xn = NULL;
94874664626SKris Kennaway     int ret = 1;
949ddd58736SKris Kennaway     int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
95074664626SKris Kennaway 
951f579bf8eSKris Kennaway     oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
95274664626SKris Kennaway 
95374664626SKris Kennaway     in = BIO_new(BIO_s_file_internal());
95474664626SKris Kennaway 
9556f9291ceSJung-uk Kim     if (in == NULL) {
9566f9291ceSJung-uk Kim         SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,
9576f9291ceSJung-uk Kim                ERR_R_MALLOC_FAILURE);
95874664626SKris Kennaway         goto err;
95974664626SKris Kennaway     }
96074664626SKris Kennaway 
96174664626SKris Kennaway     if (!BIO_read_filename(in, file))
96274664626SKris Kennaway         goto err;
96374664626SKris Kennaway 
9646f9291ceSJung-uk Kim     for (;;) {
96574664626SKris Kennaway         if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
96674664626SKris Kennaway             break;
9676f9291ceSJung-uk Kim         if ((xn = X509_get_subject_name(x)) == NULL)
9686f9291ceSJung-uk Kim             goto err;
96974664626SKris Kennaway         xn = X509_NAME_dup(xn);
9706f9291ceSJung-uk Kim         if (xn == NULL)
9716f9291ceSJung-uk Kim             goto err;
97274664626SKris Kennaway         if (sk_X509_NAME_find(stack, xn) >= 0)
97374664626SKris Kennaway             X509_NAME_free(xn);
97474664626SKris Kennaway         else
97574664626SKris Kennaway             sk_X509_NAME_push(stack, xn);
97674664626SKris Kennaway     }
97774664626SKris Kennaway 
978a3ddd25aSSimon L. B. Nielsen     ERR_clear_error();
979a3ddd25aSSimon L. B. Nielsen 
9806f9291ceSJung-uk Kim     if (0) {
98174664626SKris Kennaway  err:
98274664626SKris Kennaway         ret = 0;
98374664626SKris Kennaway     }
98474664626SKris Kennaway     if (in != NULL)
98574664626SKris Kennaway         BIO_free(in);
98674664626SKris Kennaway     if (x != NULL)
98774664626SKris Kennaway         X509_free(x);
98874664626SKris Kennaway 
989db522d3aSSimon L. B. Nielsen     (void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
99074664626SKris Kennaway 
99174664626SKris Kennaway     return ret;
99274664626SKris Kennaway }
99374664626SKris Kennaway 
9946f9291ceSJung-uk Kim /**
99574664626SKris Kennaway  * Add a directory of certs to a stack.
99674664626SKris Kennaway  * \param stack the stack to append to.
99774664626SKris Kennaway  * \param dir the directory to append from. All files in this directory will be
99874664626SKris Kennaway  * examined as potential certs. Any that are acceptable to
99974664626SKris Kennaway  * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be
100074664626SKris Kennaway  * included.
100174664626SKris Kennaway  * \return 1 for success, 0 for failure. Note that in the case of failure some
100274664626SKris Kennaway  * certs may have been added to \c stack.
100374664626SKris Kennaway  */
100474664626SKris Kennaway 
100574664626SKris Kennaway int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
100674664626SKris Kennaway                                        const char *dir)
100774664626SKris Kennaway {
10083b4e3dcbSSimon L. B. Nielsen     OPENSSL_DIR_CTX *d = NULL;
10093b4e3dcbSSimon L. B. Nielsen     const char *filename;
101074664626SKris Kennaway     int ret = 0;
101174664626SKris Kennaway 
101274664626SKris Kennaway     CRYPTO_w_lock(CRYPTO_LOCK_READDIR);
101374664626SKris Kennaway 
101474664626SKris Kennaway     /* Note that a side effect is that the CAs will be sorted by name */
101574664626SKris Kennaway 
10166f9291ceSJung-uk Kim     while ((filename = OPENSSL_DIR_read(&d, dir))) {
101774664626SKris Kennaway         char buf[1024];
1018ddd58736SKris Kennaway         int r;
101974664626SKris Kennaway 
10206f9291ceSJung-uk Kim         if (strlen(dir) + strlen(filename) + 2 > sizeof buf) {
10216f9291ceSJung-uk Kim             SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,
10226f9291ceSJung-uk Kim                    SSL_R_PATH_TOO_LONG);
102374664626SKris Kennaway             goto err;
102474664626SKris Kennaway         }
10253b4e3dcbSSimon L. B. Nielsen #ifdef OPENSSL_SYS_VMS
10263b4e3dcbSSimon L. B. Nielsen         r = BIO_snprintf(buf, sizeof buf, "%s%s", dir, filename);
10273b4e3dcbSSimon L. B. Nielsen #else
10283b4e3dcbSSimon L. B. Nielsen         r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
10293b4e3dcbSSimon L. B. Nielsen #endif
10303b4e3dcbSSimon L. B. Nielsen         if (r <= 0 || r >= (int)sizeof(buf))
1031ddd58736SKris Kennaway             goto err;
103274664626SKris Kennaway         if (!SSL_add_file_cert_subjects_to_stack(stack, buf))
103374664626SKris Kennaway             goto err;
103474664626SKris Kennaway     }
103574664626SKris Kennaway 
10366f9291ceSJung-uk Kim     if (errno) {
10375c87c606SMark Murray         SYSerr(SYS_F_OPENDIR, get_last_sys_error());
10383b4e3dcbSSimon L. B. Nielsen         ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
10395c87c606SMark Murray         SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
10405c87c606SMark Murray         goto err;
10415c87c606SMark Murray     }
10425c87c606SMark Murray 
10435c87c606SMark Murray     ret = 1;
10445c87c606SMark Murray 
10455c87c606SMark Murray  err:
10466f9291ceSJung-uk Kim     if (d)
10476f9291ceSJung-uk Kim         OPENSSL_DIR_end(&d);
10485c87c606SMark Murray     CRYPTO_w_unlock(CRYPTO_LOCK_READDIR);
10495c87c606SMark Murray     return ret;
10505c87c606SMark Murray }
10517bded2dbSJung-uk Kim 
10527bded2dbSJung-uk Kim /* Add a certificate to a BUF_MEM structure */
10537bded2dbSJung-uk Kim 
10547bded2dbSJung-uk Kim static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
10557bded2dbSJung-uk Kim {
10567bded2dbSJung-uk Kim     int n;
10577bded2dbSJung-uk Kim     unsigned char *p;
10587bded2dbSJung-uk Kim 
10597bded2dbSJung-uk Kim     n = i2d_X509(x, NULL);
1060b8721c16SJung-uk Kim     if (n < 0 || !BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
10617bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF, ERR_R_BUF_LIB);
10627bded2dbSJung-uk Kim         return 0;
10637bded2dbSJung-uk Kim     }
10647bded2dbSJung-uk Kim     p = (unsigned char *)&(buf->data[*l]);
10657bded2dbSJung-uk Kim     l2n3(n, p);
1066b8721c16SJung-uk Kim     n = i2d_X509(x, &p);
1067b8721c16SJung-uk Kim     if (n < 0) {
1068b8721c16SJung-uk Kim         /* Shouldn't happen */
1069b8721c16SJung-uk Kim         SSLerr(SSL_F_SSL_ADD_CERT_TO_BUF, ERR_R_BUF_LIB);
1070b8721c16SJung-uk Kim         return 0;
1071b8721c16SJung-uk Kim     }
10727bded2dbSJung-uk Kim     *l += n + 3;
10737bded2dbSJung-uk Kim 
10747bded2dbSJung-uk Kim     return 1;
10757bded2dbSJung-uk Kim }
10767bded2dbSJung-uk Kim 
10777bded2dbSJung-uk Kim /* Add certificate chain to internal SSL BUF_MEM strcuture */
10787bded2dbSJung-uk Kim int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
10797bded2dbSJung-uk Kim {
10807bded2dbSJung-uk Kim     BUF_MEM *buf = s->init_buf;
10817bded2dbSJung-uk Kim     int no_chain;
10827bded2dbSJung-uk Kim     int i;
10837bded2dbSJung-uk Kim 
10847bded2dbSJung-uk Kim     X509 *x;
10857bded2dbSJung-uk Kim     STACK_OF(X509) *extra_certs;
10867bded2dbSJung-uk Kim     X509_STORE *chain_store;
10877bded2dbSJung-uk Kim 
10887bded2dbSJung-uk Kim     if (cpk)
10897bded2dbSJung-uk Kim         x = cpk->x509;
10907bded2dbSJung-uk Kim     else
10917bded2dbSJung-uk Kim         x = NULL;
10927bded2dbSJung-uk Kim 
10937bded2dbSJung-uk Kim     if (s->cert->chain_store)
10947bded2dbSJung-uk Kim         chain_store = s->cert->chain_store;
10957bded2dbSJung-uk Kim     else
10967bded2dbSJung-uk Kim         chain_store = s->ctx->cert_store;
10977bded2dbSJung-uk Kim 
10987bded2dbSJung-uk Kim     /*
10997bded2dbSJung-uk Kim      * If we have a certificate specific chain use it, else use parent ctx.
11007bded2dbSJung-uk Kim      */
11017bded2dbSJung-uk Kim     if (cpk && cpk->chain)
11027bded2dbSJung-uk Kim         extra_certs = cpk->chain;
11037bded2dbSJung-uk Kim     else
11047bded2dbSJung-uk Kim         extra_certs = s->ctx->extra_certs;
11057bded2dbSJung-uk Kim 
11067bded2dbSJung-uk Kim     if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
11077bded2dbSJung-uk Kim         no_chain = 1;
11087bded2dbSJung-uk Kim     else
11097bded2dbSJung-uk Kim         no_chain = 0;
11107bded2dbSJung-uk Kim 
11117bded2dbSJung-uk Kim     /* TLSv1 sends a chain with nothing in it, instead of an alert */
11127bded2dbSJung-uk Kim     if (!BUF_MEM_grow_clean(buf, 10)) {
11137bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_BUF_LIB);
11147bded2dbSJung-uk Kim         return 0;
11157bded2dbSJung-uk Kim     }
11167bded2dbSJung-uk Kim     if (x != NULL) {
11177bded2dbSJung-uk Kim         if (no_chain) {
11187bded2dbSJung-uk Kim             if (!ssl_add_cert_to_buf(buf, l, x))
11197bded2dbSJung-uk Kim                 return 0;
11207bded2dbSJung-uk Kim         } else {
11217bded2dbSJung-uk Kim             X509_STORE_CTX xs_ctx;
11227bded2dbSJung-uk Kim 
11237bded2dbSJung-uk Kim             if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) {
11247bded2dbSJung-uk Kim                 SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB);
11257bded2dbSJung-uk Kim                 return (0);
11267bded2dbSJung-uk Kim             }
11277bded2dbSJung-uk Kim             X509_verify_cert(&xs_ctx);
11287bded2dbSJung-uk Kim             /* Don't leave errors in the queue */
11297bded2dbSJung-uk Kim             ERR_clear_error();
11307bded2dbSJung-uk Kim             for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
11317bded2dbSJung-uk Kim                 x = sk_X509_value(xs_ctx.chain, i);
11327bded2dbSJung-uk Kim 
11337bded2dbSJung-uk Kim                 if (!ssl_add_cert_to_buf(buf, l, x)) {
11347bded2dbSJung-uk Kim                     X509_STORE_CTX_cleanup(&xs_ctx);
11357bded2dbSJung-uk Kim                     return 0;
11367bded2dbSJung-uk Kim                 }
11377bded2dbSJung-uk Kim             }
11387bded2dbSJung-uk Kim             X509_STORE_CTX_cleanup(&xs_ctx);
11397bded2dbSJung-uk Kim         }
11407bded2dbSJung-uk Kim     }
11417bded2dbSJung-uk Kim     for (i = 0; i < sk_X509_num(extra_certs); i++) {
11427bded2dbSJung-uk Kim         x = sk_X509_value(extra_certs, i);
11437bded2dbSJung-uk Kim         if (!ssl_add_cert_to_buf(buf, l, x))
11447bded2dbSJung-uk Kim             return 0;
11457bded2dbSJung-uk Kim     }
11467bded2dbSJung-uk Kim 
11477bded2dbSJung-uk Kim     return 1;
11487bded2dbSJung-uk Kim }
11497bded2dbSJung-uk Kim 
11507bded2dbSJung-uk Kim /* Build a certificate chain for current certificate */
11517bded2dbSJung-uk Kim int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags)
11527bded2dbSJung-uk Kim {
11537bded2dbSJung-uk Kim     CERT_PKEY *cpk = c->key;
11547bded2dbSJung-uk Kim     X509_STORE_CTX xs_ctx;
11557bded2dbSJung-uk Kim     STACK_OF(X509) *chain = NULL, *untrusted = NULL;
11567bded2dbSJung-uk Kim     X509 *x;
11577bded2dbSJung-uk Kim     int i, rv = 0;
11587bded2dbSJung-uk Kim     unsigned long error;
11597bded2dbSJung-uk Kim 
11607bded2dbSJung-uk Kim     if (!cpk->x509) {
11617bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
11627bded2dbSJung-uk Kim         goto err;
11637bded2dbSJung-uk Kim     }
11647bded2dbSJung-uk Kim     /* Rearranging and check the chain: add everything to a store */
11657bded2dbSJung-uk Kim     if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
11667bded2dbSJung-uk Kim         chain_store = X509_STORE_new();
11677bded2dbSJung-uk Kim         if (!chain_store)
11687bded2dbSJung-uk Kim             goto err;
11697bded2dbSJung-uk Kim         for (i = 0; i < sk_X509_num(cpk->chain); i++) {
11707bded2dbSJung-uk Kim             x = sk_X509_value(cpk->chain, i);
11717bded2dbSJung-uk Kim             if (!X509_STORE_add_cert(chain_store, x)) {
11727bded2dbSJung-uk Kim                 error = ERR_peek_last_error();
11737bded2dbSJung-uk Kim                 if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
11747bded2dbSJung-uk Kim                     ERR_GET_REASON(error) !=
11757bded2dbSJung-uk Kim                     X509_R_CERT_ALREADY_IN_HASH_TABLE)
11767bded2dbSJung-uk Kim                     goto err;
11777bded2dbSJung-uk Kim                 ERR_clear_error();
11787bded2dbSJung-uk Kim             }
11797bded2dbSJung-uk Kim         }
11807bded2dbSJung-uk Kim         /* Add EE cert too: it might be self signed */
11817bded2dbSJung-uk Kim         if (!X509_STORE_add_cert(chain_store, cpk->x509)) {
11827bded2dbSJung-uk Kim             error = ERR_peek_last_error();
11837bded2dbSJung-uk Kim             if (ERR_GET_LIB(error) != ERR_LIB_X509 ||
11847bded2dbSJung-uk Kim                 ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE)
11857bded2dbSJung-uk Kim                 goto err;
11867bded2dbSJung-uk Kim             ERR_clear_error();
11877bded2dbSJung-uk Kim         }
11887bded2dbSJung-uk Kim     } else {
11897bded2dbSJung-uk Kim         if (c->chain_store)
11907bded2dbSJung-uk Kim             chain_store = c->chain_store;
11917bded2dbSJung-uk Kim 
11927bded2dbSJung-uk Kim         if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
11937bded2dbSJung-uk Kim             untrusted = cpk->chain;
11947bded2dbSJung-uk Kim     }
11957bded2dbSJung-uk Kim 
11967bded2dbSJung-uk Kim     if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) {
11977bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
11987bded2dbSJung-uk Kim         goto err;
11997bded2dbSJung-uk Kim     }
12007bded2dbSJung-uk Kim     /* Set suite B flags if needed */
12017bded2dbSJung-uk Kim     X509_STORE_CTX_set_flags(&xs_ctx,
12027bded2dbSJung-uk Kim                              c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
12037bded2dbSJung-uk Kim 
12047bded2dbSJung-uk Kim     i = X509_verify_cert(&xs_ctx);
12057bded2dbSJung-uk Kim     if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
12067bded2dbSJung-uk Kim         if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
12077bded2dbSJung-uk Kim             ERR_clear_error();
12087bded2dbSJung-uk Kim         i = 1;
12097bded2dbSJung-uk Kim         rv = 2;
12107bded2dbSJung-uk Kim     }
12117bded2dbSJung-uk Kim     if (i > 0)
12127bded2dbSJung-uk Kim         chain = X509_STORE_CTX_get1_chain(&xs_ctx);
12137bded2dbSJung-uk Kim     if (i <= 0) {
12147bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
12157bded2dbSJung-uk Kim         i = X509_STORE_CTX_get_error(&xs_ctx);
12167bded2dbSJung-uk Kim         ERR_add_error_data(2, "Verify error:",
12177bded2dbSJung-uk Kim                            X509_verify_cert_error_string(i));
12187bded2dbSJung-uk Kim 
12197bded2dbSJung-uk Kim         X509_STORE_CTX_cleanup(&xs_ctx);
12207bded2dbSJung-uk Kim         goto err;
12217bded2dbSJung-uk Kim     }
12227bded2dbSJung-uk Kim     X509_STORE_CTX_cleanup(&xs_ctx);
12237bded2dbSJung-uk Kim     if (cpk->chain)
12247bded2dbSJung-uk Kim         sk_X509_pop_free(cpk->chain, X509_free);
12257bded2dbSJung-uk Kim     /* Remove EE certificate from chain */
12267bded2dbSJung-uk Kim     x = sk_X509_shift(chain);
12277bded2dbSJung-uk Kim     X509_free(x);
12287bded2dbSJung-uk Kim     if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
12297bded2dbSJung-uk Kim         if (sk_X509_num(chain) > 0) {
12307bded2dbSJung-uk Kim             /* See if last cert is self signed */
12317bded2dbSJung-uk Kim             x = sk_X509_value(chain, sk_X509_num(chain) - 1);
12327bded2dbSJung-uk Kim             X509_check_purpose(x, -1, 0);
12337bded2dbSJung-uk Kim             if (x->ex_flags & EXFLAG_SS) {
12347bded2dbSJung-uk Kim                 x = sk_X509_pop(chain);
12357bded2dbSJung-uk Kim                 X509_free(x);
12367bded2dbSJung-uk Kim             }
12377bded2dbSJung-uk Kim         }
12387bded2dbSJung-uk Kim     }
12397bded2dbSJung-uk Kim     cpk->chain = chain;
12407bded2dbSJung-uk Kim     if (rv == 0)
12417bded2dbSJung-uk Kim         rv = 1;
12427bded2dbSJung-uk Kim  err:
12437bded2dbSJung-uk Kim     if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
12447bded2dbSJung-uk Kim         X509_STORE_free(chain_store);
12457bded2dbSJung-uk Kim 
12467bded2dbSJung-uk Kim     return rv;
12477bded2dbSJung-uk Kim }
12487bded2dbSJung-uk Kim 
12497bded2dbSJung-uk Kim int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
12507bded2dbSJung-uk Kim {
12517bded2dbSJung-uk Kim     X509_STORE **pstore;
12527bded2dbSJung-uk Kim     if (chain)
12537bded2dbSJung-uk Kim         pstore = &c->chain_store;
12547bded2dbSJung-uk Kim     else
12557bded2dbSJung-uk Kim         pstore = &c->verify_store;
12567bded2dbSJung-uk Kim     if (*pstore)
12577bded2dbSJung-uk Kim         X509_STORE_free(*pstore);
12587bded2dbSJung-uk Kim     *pstore = store;
12597bded2dbSJung-uk Kim     if (ref && store)
12607bded2dbSJung-uk Kim         CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
12617bded2dbSJung-uk Kim     return 1;
12627bded2dbSJung-uk Kim }
1263