xref: /freebsd/crypto/openssl/ssl/ssl_cert.c (revision 9a3ae0cdef9ac9a4b8c5cc66305d9a516ce8d4a0)
16f9291ceSJung-uk Kim /*
2*9a3ae0cdSJung-uk Kim  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
474664626SKris Kennaway  *
5e71b7053SJung-uk Kim  * Licensed under the OpenSSL license (the "License").  You may not use
6e71b7053SJung-uk Kim  * this file except in compliance with the License.  You can obtain a copy
7e71b7053SJung-uk Kim  * in the file LICENSE in the source distribution or at
8e71b7053SJung-uk Kim  * https://www.openssl.org/source/license.html
93b4e3dcbSSimon L. B. Nielsen  */
1074664626SKris Kennaway 
1174664626SKris Kennaway #include <stdio.h>
1274664626SKris Kennaway #include <sys/types.h>
13f579bf8eSKris Kennaway 
14e71b7053SJung-uk Kim #include "internal/nelem.h"
15e71b7053SJung-uk Kim #include "internal/o_dir.h"
1674664626SKris Kennaway #include <openssl/bio.h>
1774664626SKris Kennaway #include <openssl/pem.h>
18f579bf8eSKris Kennaway #include <openssl/x509v3.h>
193b4e3dcbSSimon L. B. Nielsen #include <openssl/dh.h>
203b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h>
21e71b7053SJung-uk Kim #include <openssl/crypto.h>
22e71b7053SJung-uk Kim #include "internal/refcount.h"
2317f01e99SJung-uk Kim #include "ssl_local.h"
24e71b7053SJung-uk Kim #include "ssl_cert_table.h"
25e71b7053SJung-uk Kim #include "internal/thread_once.h"
26e71b7053SJung-uk Kim 
27e71b7053SJung-uk Kim static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
28e71b7053SJung-uk Kim                                          int op, int bits, int nid, void *other,
29e71b7053SJung-uk Kim                                          void *ex);
30e71b7053SJung-uk Kim 
31e71b7053SJung-uk Kim static CRYPTO_ONCE ssl_x509_store_ctx_once = CRYPTO_ONCE_STATIC_INIT;
32e71b7053SJung-uk Kim static volatile int ssl_x509_store_ctx_idx = -1;
33e71b7053SJung-uk Kim 
34e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init)
35e71b7053SJung-uk Kim {
36e71b7053SJung-uk Kim     ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index(0,
37e71b7053SJung-uk Kim                                                              "SSL for verify callback",
38e71b7053SJung-uk Kim                                                              NULL, NULL, NULL);
39e71b7053SJung-uk Kim     return ssl_x509_store_ctx_idx >= 0;
40e71b7053SJung-uk Kim }
4174664626SKris Kennaway 
4274664626SKris Kennaway int SSL_get_ex_data_X509_STORE_CTX_idx(void)
4374664626SKris Kennaway {
44ed5d4f9aSSimon L. B. Nielsen 
45e71b7053SJung-uk Kim     if (!RUN_ONCE(&ssl_x509_store_ctx_once, ssl_x509_store_ctx_init))
46e71b7053SJung-uk Kim         return -1;
475c87c606SMark Murray     return ssl_x509_store_ctx_idx;
4874664626SKris Kennaway }
491f13597dSJung-uk Kim 
5074664626SKris Kennaway CERT *ssl_cert_new(void)
5174664626SKris Kennaway {
52e71b7053SJung-uk Kim     CERT *ret = OPENSSL_zalloc(sizeof(*ret));
5374664626SKris Kennaway 
546f9291ceSJung-uk Kim     if (ret == NULL) {
5574664626SKris Kennaway         SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
56e71b7053SJung-uk Kim         return NULL;
5774664626SKris Kennaway     }
5874664626SKris Kennaway 
59e71b7053SJung-uk Kim     ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
6074664626SKris Kennaway     ret->references = 1;
61e71b7053SJung-uk Kim     ret->sec_cb = ssl_security_default_callback;
62e71b7053SJung-uk Kim     ret->sec_level = OPENSSL_TLS_SECURITY_LEVEL;
63e71b7053SJung-uk Kim     ret->sec_ex = NULL;
64e71b7053SJung-uk Kim     ret->lock = CRYPTO_THREAD_lock_new();
65e71b7053SJung-uk Kim     if (ret->lock == NULL) {
66e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_CERT_NEW, ERR_R_MALLOC_FAILURE);
67e71b7053SJung-uk Kim         OPENSSL_free(ret);
68e71b7053SJung-uk Kim         return NULL;
69e71b7053SJung-uk Kim     }
70e71b7053SJung-uk Kim 
71e71b7053SJung-uk Kim     return ret;
7274664626SKris Kennaway }
7374664626SKris Kennaway 
7474664626SKris Kennaway CERT *ssl_cert_dup(CERT *cert)
7574664626SKris Kennaway {
76e71b7053SJung-uk Kim     CERT *ret = OPENSSL_zalloc(sizeof(*ret));
7774664626SKris Kennaway     int i;
7874664626SKris Kennaway 
796f9291ceSJung-uk Kim     if (ret == NULL) {
8074664626SKris Kennaway         SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
81e71b7053SJung-uk Kim         return NULL;
8274664626SKris Kennaway     }
8374664626SKris Kennaway 
8480815a77SJung-uk Kim     ret->references = 1;
85e71b7053SJung-uk Kim     ret->key = &ret->pkeys[cert->key - cert->pkeys];
86e71b7053SJung-uk Kim     ret->lock = CRYPTO_THREAD_lock_new();
87e71b7053SJung-uk Kim     if (ret->lock == NULL) {
88e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
89e71b7053SJung-uk Kim         OPENSSL_free(ret);
90e71b7053SJung-uk Kim         return NULL;
9174664626SKris Kennaway     }
925c87c606SMark Murray #ifndef OPENSSL_NO_DH
936f9291ceSJung-uk Kim     if (cert->dh_tmp != NULL) {
94e71b7053SJung-uk Kim         ret->dh_tmp = cert->dh_tmp;
95e71b7053SJung-uk Kim         EVP_PKEY_up_ref(ret->dh_tmp);
9674664626SKris Kennaway     }
9774664626SKris Kennaway     ret->dh_tmp_cb = cert->dh_tmp_cb;
98e71b7053SJung-uk Kim     ret->dh_tmp_auto = cert->dh_tmp_auto;
993b4e3dcbSSimon L. B. Nielsen #endif
1003b4e3dcbSSimon L. B. Nielsen 
1016f9291ceSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
1027bded2dbSJung-uk Kim         CERT_PKEY *cpk = cert->pkeys + i;
1037bded2dbSJung-uk Kim         CERT_PKEY *rpk = ret->pkeys + i;
1047bded2dbSJung-uk Kim         if (cpk->x509 != NULL) {
1057bded2dbSJung-uk Kim             rpk->x509 = cpk->x509;
106e71b7053SJung-uk Kim             X509_up_ref(rpk->x509);
10774664626SKris Kennaway         }
10874664626SKris Kennaway 
1097bded2dbSJung-uk Kim         if (cpk->privatekey != NULL) {
1107bded2dbSJung-uk Kim             rpk->privatekey = cpk->privatekey;
111e71b7053SJung-uk Kim             EVP_PKEY_up_ref(cpk->privatekey);
11274664626SKris Kennaway         }
11374664626SKris Kennaway 
1147bded2dbSJung-uk Kim         if (cpk->chain) {
1157bded2dbSJung-uk Kim             rpk->chain = X509_chain_up_ref(cpk->chain);
1167bded2dbSJung-uk Kim             if (!rpk->chain) {
1177bded2dbSJung-uk Kim                 SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
1187bded2dbSJung-uk Kim                 goto err;
1197bded2dbSJung-uk Kim             }
1207bded2dbSJung-uk Kim         }
1217bded2dbSJung-uk Kim         if (cert->pkeys[i].serverinfo != NULL) {
1227bded2dbSJung-uk Kim             /* Just copy everything. */
1237bded2dbSJung-uk Kim             ret->pkeys[i].serverinfo =
1247bded2dbSJung-uk Kim                 OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
1257bded2dbSJung-uk Kim             if (ret->pkeys[i].serverinfo == NULL) {
1267bded2dbSJung-uk Kim                 SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE);
1276cf8931aSJung-uk Kim                 goto err;
1287bded2dbSJung-uk Kim             }
129e71b7053SJung-uk Kim             ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length;
1307bded2dbSJung-uk Kim             memcpy(ret->pkeys[i].serverinfo,
131e71b7053SJung-uk Kim                    cert->pkeys[i].serverinfo, cert->pkeys[i].serverinfo_length);
1327bded2dbSJung-uk Kim         }
1337bded2dbSJung-uk Kim     }
13474664626SKris Kennaway 
135e71b7053SJung-uk Kim     /* Configured sigalgs copied across */
1367bded2dbSJung-uk Kim     if (cert->conf_sigalgs) {
137e71b7053SJung-uk Kim         ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen
138e71b7053SJung-uk Kim                                            * sizeof(*cert->conf_sigalgs));
139e71b7053SJung-uk Kim         if (ret->conf_sigalgs == NULL)
1407bded2dbSJung-uk Kim             goto err;
141e71b7053SJung-uk Kim         memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
142e71b7053SJung-uk Kim                cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs));
1437bded2dbSJung-uk Kim         ret->conf_sigalgslen = cert->conf_sigalgslen;
1447bded2dbSJung-uk Kim     } else
1457bded2dbSJung-uk Kim         ret->conf_sigalgs = NULL;
1467bded2dbSJung-uk Kim 
1477bded2dbSJung-uk Kim     if (cert->client_sigalgs) {
148e71b7053SJung-uk Kim         ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen
149e71b7053SJung-uk Kim                                              * sizeof(*cert->client_sigalgs));
150e71b7053SJung-uk Kim         if (ret->client_sigalgs == NULL)
1517bded2dbSJung-uk Kim             goto err;
1527bded2dbSJung-uk Kim         memcpy(ret->client_sigalgs, cert->client_sigalgs,
153e71b7053SJung-uk Kim                cert->client_sigalgslen * sizeof(*cert->client_sigalgs));
1547bded2dbSJung-uk Kim         ret->client_sigalgslen = cert->client_sigalgslen;
1557bded2dbSJung-uk Kim     } else
1567bded2dbSJung-uk Kim         ret->client_sigalgs = NULL;
1577bded2dbSJung-uk Kim     /* Copy any custom client certificate types */
158e71b7053SJung-uk Kim     if (cert->ctype) {
159e71b7053SJung-uk Kim         ret->ctype = OPENSSL_memdup(cert->ctype, cert->ctype_len);
160e71b7053SJung-uk Kim         if (ret->ctype == NULL)
1617bded2dbSJung-uk Kim             goto err;
162e71b7053SJung-uk Kim         ret->ctype_len = cert->ctype_len;
1637bded2dbSJung-uk Kim     }
1647bded2dbSJung-uk Kim 
1657bded2dbSJung-uk Kim     ret->cert_flags = cert->cert_flags;
1667bded2dbSJung-uk Kim 
1677bded2dbSJung-uk Kim     ret->cert_cb = cert->cert_cb;
1687bded2dbSJung-uk Kim     ret->cert_cb_arg = cert->cert_cb_arg;
1697bded2dbSJung-uk Kim 
1707bded2dbSJung-uk Kim     if (cert->verify_store) {
171e71b7053SJung-uk Kim         X509_STORE_up_ref(cert->verify_store);
1727bded2dbSJung-uk Kim         ret->verify_store = cert->verify_store;
1737bded2dbSJung-uk Kim     }
1747bded2dbSJung-uk Kim 
1757bded2dbSJung-uk Kim     if (cert->chain_store) {
176e71b7053SJung-uk Kim         X509_STORE_up_ref(cert->chain_store);
1777bded2dbSJung-uk Kim         ret->chain_store = cert->chain_store;
1787bded2dbSJung-uk Kim     }
1797bded2dbSJung-uk Kim 
180e71b7053SJung-uk Kim     ret->sec_cb = cert->sec_cb;
181e71b7053SJung-uk Kim     ret->sec_level = cert->sec_level;
182e71b7053SJung-uk Kim     ret->sec_ex = cert->sec_ex;
1837bded2dbSJung-uk Kim 
184e71b7053SJung-uk Kim     if (!custom_exts_copy(&ret->custext, &cert->custext))
1857bded2dbSJung-uk Kim         goto err;
186e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK
187e71b7053SJung-uk Kim     if (cert->psk_identity_hint) {
188e71b7053SJung-uk Kim         ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint);
189e71b7053SJung-uk Kim         if (ret->psk_identity_hint == NULL)
1907bded2dbSJung-uk Kim             goto err;
191e71b7053SJung-uk Kim     }
1927bded2dbSJung-uk Kim #endif
193e71b7053SJung-uk Kim     return ret;
19474664626SKris Kennaway 
19574664626SKris Kennaway  err:
196e71b7053SJung-uk Kim     ssl_cert_free(ret);
19774664626SKris Kennaway 
19874664626SKris Kennaway     return NULL;
19974664626SKris Kennaway }
20074664626SKris Kennaway 
2017bded2dbSJung-uk Kim /* Free up and clear all certificates and chains */
2027bded2dbSJung-uk Kim 
2037bded2dbSJung-uk Kim void ssl_cert_clear_certs(CERT *c)
2047bded2dbSJung-uk Kim {
2057bded2dbSJung-uk Kim     int i;
2067bded2dbSJung-uk Kim     if (c == NULL)
2077bded2dbSJung-uk Kim         return;
2087bded2dbSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
2097bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
2107bded2dbSJung-uk Kim         X509_free(cpk->x509);
2117bded2dbSJung-uk Kim         cpk->x509 = NULL;
2127bded2dbSJung-uk Kim         EVP_PKEY_free(cpk->privatekey);
2137bded2dbSJung-uk Kim         cpk->privatekey = NULL;
2147bded2dbSJung-uk Kim         sk_X509_pop_free(cpk->chain, X509_free);
2157bded2dbSJung-uk Kim         cpk->chain = NULL;
2167bded2dbSJung-uk Kim         OPENSSL_free(cpk->serverinfo);
2177bded2dbSJung-uk Kim         cpk->serverinfo = NULL;
2187bded2dbSJung-uk Kim         cpk->serverinfo_length = 0;
2197bded2dbSJung-uk Kim     }
2207bded2dbSJung-uk Kim }
2217bded2dbSJung-uk Kim 
22274664626SKris Kennaway void ssl_cert_free(CERT *c)
22374664626SKris Kennaway {
22474664626SKris Kennaway     int i;
22574664626SKris Kennaway 
22674664626SKris Kennaway     if (c == NULL)
22774664626SKris Kennaway         return;
228e71b7053SJung-uk Kim     CRYPTO_DOWN_REF(&c->references, &i, c->lock);
229e71b7053SJung-uk Kim     REF_PRINT_COUNT("CERT", c);
2306f9291ceSJung-uk Kim     if (i > 0)
2316f9291ceSJung-uk Kim         return;
232e71b7053SJung-uk Kim     REF_ASSERT_ISNT(i < 0);
23374664626SKris Kennaway 
2345c87c606SMark Murray #ifndef OPENSSL_NO_DH
235e71b7053SJung-uk Kim     EVP_PKEY_free(c->dh_tmp);
2363b4e3dcbSSimon L. B. Nielsen #endif
23774664626SKris Kennaway 
2387bded2dbSJung-uk Kim     ssl_cert_clear_certs(c);
2397bded2dbSJung-uk Kim     OPENSSL_free(c->conf_sigalgs);
2407bded2dbSJung-uk Kim     OPENSSL_free(c->client_sigalgs);
241e71b7053SJung-uk Kim     OPENSSL_free(c->ctype);
2427bded2dbSJung-uk Kim     X509_STORE_free(c->verify_store);
2437bded2dbSJung-uk Kim     X509_STORE_free(c->chain_store);
244e71b7053SJung-uk Kim     custom_exts_free(&c->custext);
245e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK
246e71b7053SJung-uk Kim     OPENSSL_free(c->psk_identity_hint);
24774664626SKris Kennaway #endif
248e71b7053SJung-uk Kim     CRYPTO_THREAD_lock_free(c->lock);
249ddd58736SKris Kennaway     OPENSSL_free(c);
25074664626SKris Kennaway }
25174664626SKris Kennaway 
252e71b7053SJung-uk Kim int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
25374664626SKris Kennaway {
254e71b7053SJung-uk Kim     int i, r;
255e71b7053SJung-uk Kim     CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
2567bded2dbSJung-uk Kim     if (!cpk)
2577bded2dbSJung-uk Kim         return 0;
258e71b7053SJung-uk Kim     for (i = 0; i < sk_X509_num(chain); i++) {
259e71b7053SJung-uk Kim         r = ssl_security_cert(s, ctx, sk_X509_value(chain, i), 0, 0);
260e71b7053SJung-uk Kim         if (r != 1) {
261e71b7053SJung-uk Kim             SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r);
262e71b7053SJung-uk Kim             return 0;
263e71b7053SJung-uk Kim         }
264e71b7053SJung-uk Kim     }
2657bded2dbSJung-uk Kim     sk_X509_pop_free(cpk->chain, X509_free);
2667bded2dbSJung-uk Kim     cpk->chain = chain;
2677bded2dbSJung-uk Kim     return 1;
2687bded2dbSJung-uk Kim }
2697bded2dbSJung-uk Kim 
270e71b7053SJung-uk Kim int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
2717bded2dbSJung-uk Kim {
2727bded2dbSJung-uk Kim     STACK_OF(X509) *dchain;
2737bded2dbSJung-uk Kim     if (!chain)
274e71b7053SJung-uk Kim         return ssl_cert_set0_chain(s, ctx, NULL);
2757bded2dbSJung-uk Kim     dchain = X509_chain_up_ref(chain);
2767bded2dbSJung-uk Kim     if (!dchain)
2777bded2dbSJung-uk Kim         return 0;
278e71b7053SJung-uk Kim     if (!ssl_cert_set0_chain(s, ctx, dchain)) {
2797bded2dbSJung-uk Kim         sk_X509_pop_free(dchain, X509_free);
2807bded2dbSJung-uk Kim         return 0;
2817bded2dbSJung-uk Kim     }
2827bded2dbSJung-uk Kim     return 1;
2837bded2dbSJung-uk Kim }
2847bded2dbSJung-uk Kim 
285e71b7053SJung-uk Kim int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
2867bded2dbSJung-uk Kim {
287e71b7053SJung-uk Kim     int r;
288e71b7053SJung-uk Kim     CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
2897bded2dbSJung-uk Kim     if (!cpk)
2907bded2dbSJung-uk Kim         return 0;
291e71b7053SJung-uk Kim     r = ssl_security_cert(s, ctx, x, 0, 0);
292e71b7053SJung-uk Kim     if (r != 1) {
293e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_CERT_ADD0_CHAIN_CERT, r);
294e71b7053SJung-uk Kim         return 0;
295e71b7053SJung-uk Kim     }
2967bded2dbSJung-uk Kim     if (!cpk->chain)
2977bded2dbSJung-uk Kim         cpk->chain = sk_X509_new_null();
2987bded2dbSJung-uk Kim     if (!cpk->chain || !sk_X509_push(cpk->chain, x))
2997bded2dbSJung-uk Kim         return 0;
3007bded2dbSJung-uk Kim     return 1;
3017bded2dbSJung-uk Kim }
3027bded2dbSJung-uk Kim 
303e71b7053SJung-uk Kim int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
3047bded2dbSJung-uk Kim {
305e71b7053SJung-uk Kim     if (!ssl_cert_add0_chain_cert(s, ctx, x))
3067bded2dbSJung-uk Kim         return 0;
307e71b7053SJung-uk Kim     X509_up_ref(x);
3087bded2dbSJung-uk Kim     return 1;
3097bded2dbSJung-uk Kim }
3107bded2dbSJung-uk Kim 
3117bded2dbSJung-uk Kim int ssl_cert_select_current(CERT *c, X509 *x)
3127bded2dbSJung-uk Kim {
3137bded2dbSJung-uk Kim     int i;
3147bded2dbSJung-uk Kim     if (x == NULL)
3157bded2dbSJung-uk Kim         return 0;
3167bded2dbSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
3177bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
3187bded2dbSJung-uk Kim         if (cpk->x509 == x && cpk->privatekey) {
3197bded2dbSJung-uk Kim             c->key = cpk;
3207bded2dbSJung-uk Kim             return 1;
3217bded2dbSJung-uk Kim         }
3227bded2dbSJung-uk Kim     }
3237bded2dbSJung-uk Kim 
3247bded2dbSJung-uk Kim     for (i = 0; i < SSL_PKEY_NUM; i++) {
3257bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
3267bded2dbSJung-uk Kim         if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
3277bded2dbSJung-uk Kim             c->key = cpk;
3287bded2dbSJung-uk Kim             return 1;
3297bded2dbSJung-uk Kim         }
3307bded2dbSJung-uk Kim     }
3317bded2dbSJung-uk Kim     return 0;
3327bded2dbSJung-uk Kim }
3337bded2dbSJung-uk Kim 
3347bded2dbSJung-uk Kim int ssl_cert_set_current(CERT *c, long op)
3357bded2dbSJung-uk Kim {
3367bded2dbSJung-uk Kim     int i, idx;
3377bded2dbSJung-uk Kim     if (!c)
3387bded2dbSJung-uk Kim         return 0;
3397bded2dbSJung-uk Kim     if (op == SSL_CERT_SET_FIRST)
3407bded2dbSJung-uk Kim         idx = 0;
3417bded2dbSJung-uk Kim     else if (op == SSL_CERT_SET_NEXT) {
3427bded2dbSJung-uk Kim         idx = (int)(c->key - c->pkeys + 1);
3437bded2dbSJung-uk Kim         if (idx >= SSL_PKEY_NUM)
3447bded2dbSJung-uk Kim             return 0;
3457bded2dbSJung-uk Kim     } else
3467bded2dbSJung-uk Kim         return 0;
3477bded2dbSJung-uk Kim     for (i = idx; i < SSL_PKEY_NUM; i++) {
3487bded2dbSJung-uk Kim         CERT_PKEY *cpk = c->pkeys + i;
3497bded2dbSJung-uk Kim         if (cpk->x509 && cpk->privatekey) {
3507bded2dbSJung-uk Kim             c->key = cpk;
3517bded2dbSJung-uk Kim             return 1;
3527bded2dbSJung-uk Kim         }
3537bded2dbSJung-uk Kim     }
3547bded2dbSJung-uk Kim     return 0;
3557bded2dbSJung-uk Kim }
3567bded2dbSJung-uk Kim 
3577bded2dbSJung-uk Kim void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
3587bded2dbSJung-uk Kim {
3597bded2dbSJung-uk Kim     c->cert_cb = cb;
3607bded2dbSJung-uk Kim     c->cert_cb_arg = arg;
3617bded2dbSJung-uk Kim }
3627bded2dbSJung-uk Kim 
36374664626SKris Kennaway int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
36474664626SKris Kennaway {
36574664626SKris Kennaway     X509 *x;
366e71b7053SJung-uk Kim     int i = 0;
3677bded2dbSJung-uk Kim     X509_STORE *verify_store;
368e71b7053SJung-uk Kim     X509_STORE_CTX *ctx = NULL;
369e71b7053SJung-uk Kim     X509_VERIFY_PARAM *param;
370e71b7053SJung-uk Kim 
371e71b7053SJung-uk Kim     if ((sk == NULL) || (sk_X509_num(sk) == 0))
372e71b7053SJung-uk Kim         return 0;
37374664626SKris Kennaway 
3747bded2dbSJung-uk Kim     if (s->cert->verify_store)
3757bded2dbSJung-uk Kim         verify_store = s->cert->verify_store;
3767bded2dbSJung-uk Kim     else
3777bded2dbSJung-uk Kim         verify_store = s->ctx->cert_store;
3787bded2dbSJung-uk Kim 
379e71b7053SJung-uk Kim     ctx = X509_STORE_CTX_new();
380e71b7053SJung-uk Kim     if (ctx == NULL) {
381e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
382e71b7053SJung-uk Kim         return 0;
383e71b7053SJung-uk Kim     }
38474664626SKris Kennaway 
38574664626SKris Kennaway     x = sk_X509_value(sk, 0);
386e71b7053SJung-uk Kim     if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
3875c87c606SMark Murray         SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
388e71b7053SJung-uk Kim         goto end;
3895c87c606SMark Murray     }
390e71b7053SJung-uk Kim     param = X509_STORE_CTX_get0_param(ctx);
391e71b7053SJung-uk Kim     /*
392e71b7053SJung-uk Kim      * XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
393e71b7053SJung-uk Kim      * point, for now a single @SECLEVEL sets the same policy for TLS crypto
394e71b7053SJung-uk Kim      * and PKI authentication.
395e71b7053SJung-uk Kim      */
396e71b7053SJung-uk Kim     X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
397e71b7053SJung-uk Kim 
3987bded2dbSJung-uk Kim     /* Set suite B flags if needed */
399e71b7053SJung-uk Kim     X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s));
400e71b7053SJung-uk Kim     if (!X509_STORE_CTX_set_ex_data
401e71b7053SJung-uk Kim         (ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s)) {
402e71b7053SJung-uk Kim         goto end;
403e71b7053SJung-uk Kim     }
404e71b7053SJung-uk Kim 
405e71b7053SJung-uk Kim     /* Verify via DANE if enabled */
406e71b7053SJung-uk Kim     if (DANETLS_ENABLED(&s->dane))
407e71b7053SJung-uk Kim         X509_STORE_CTX_set0_dane(ctx, &s->dane);
4085c87c606SMark Murray 
4096f9291ceSJung-uk Kim     /*
4106f9291ceSJung-uk Kim      * We need to inherit the verify parameters. These can be determined by
4116f9291ceSJung-uk Kim      * the context: if its a server it will verify SSL client certificates or
4126f9291ceSJung-uk Kim      * vice versa.
413f579bf8eSKris Kennaway      */
414f579bf8eSKris Kennaway 
415e71b7053SJung-uk Kim     X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
4166f9291ceSJung-uk Kim     /*
417e71b7053SJung-uk Kim      * Anything non-default in "s->param" should overwrite anything in the ctx.
4186a599222SSimon L. B. Nielsen      */
419e71b7053SJung-uk Kim     X509_VERIFY_PARAM_set1(param, s->param);
42074664626SKris Kennaway 
421a21b1b38SKris Kennaway     if (s->verify_callback)
422e71b7053SJung-uk Kim         X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
423a21b1b38SKris Kennaway 
42474664626SKris Kennaway     if (s->ctx->app_verify_callback != NULL)
425e71b7053SJung-uk Kim         i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
426e71b7053SJung-uk Kim     else
427e71b7053SJung-uk Kim         i = X509_verify_cert(ctx);
428e71b7053SJung-uk Kim 
429e71b7053SJung-uk Kim     s->verify_result = X509_STORE_CTX_get_error(ctx);
430e71b7053SJung-uk Kim     sk_X509_pop_free(s->verified_chain, X509_free);
431e71b7053SJung-uk Kim     s->verified_chain = NULL;
432e71b7053SJung-uk Kim     if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
433e71b7053SJung-uk Kim         s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
434e71b7053SJung-uk Kim         if (s->verified_chain == NULL) {
435e71b7053SJung-uk Kim             SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
43674664626SKris Kennaway             i = 0;
437e71b7053SJung-uk Kim         }
43874664626SKris Kennaway     }
43974664626SKris Kennaway 
440e71b7053SJung-uk Kim     /* Move peername from the store context params to the SSL handle's */
441e71b7053SJung-uk Kim     X509_VERIFY_PARAM_move_peername(s->param, param);
44274664626SKris Kennaway 
443e71b7053SJung-uk Kim  end:
444e71b7053SJung-uk Kim     X509_STORE_CTX_free(ctx);
445e71b7053SJung-uk Kim     return i;
44674664626SKris Kennaway }
44774664626SKris Kennaway 
448e71b7053SJung-uk Kim static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
4496f9291ceSJung-uk Kim                         STACK_OF(X509_NAME) *name_list)
45074664626SKris Kennaway {
45174664626SKris Kennaway     sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
452ced566fdSJacques Vidrine     *ca_list = name_list;
45374664626SKris Kennaway }
45474664626SKris Kennaway 
455e71b7053SJung-uk Kim STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
45674664626SKris Kennaway {
45774664626SKris Kennaway     int i;
458e71b7053SJung-uk Kim     const int num = sk_X509_NAME_num(sk);
45974664626SKris Kennaway     STACK_OF(X509_NAME) *ret;
46074664626SKris Kennaway     X509_NAME *name;
46174664626SKris Kennaway 
462e71b7053SJung-uk Kim     ret = sk_X509_NAME_new_reserve(NULL, num);
463e71b7053SJung-uk Kim     if (ret == NULL) {
464e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
465e71b7053SJung-uk Kim         return NULL;
466e71b7053SJung-uk Kim     }
467e71b7053SJung-uk Kim     for (i = 0; i < num; i++) {
46874664626SKris Kennaway         name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
469e71b7053SJung-uk Kim         if (name == NULL) {
470e71b7053SJung-uk Kim             SSLerr(SSL_F_SSL_DUP_CA_LIST, ERR_R_MALLOC_FAILURE);
47174664626SKris Kennaway             sk_X509_NAME_pop_free(ret, X509_NAME_free);
472e71b7053SJung-uk Kim             return NULL;
47374664626SKris Kennaway         }
474e71b7053SJung-uk Kim         sk_X509_NAME_push(ret, name);   /* Cannot fail after reserve call */
47574664626SKris Kennaway     }
476e71b7053SJung-uk Kim     return ret;
47774664626SKris Kennaway }
47874664626SKris Kennaway 
479e71b7053SJung-uk Kim void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
48074664626SKris Kennaway {
481e71b7053SJung-uk Kim     set0_CA_list(&s->ca_names, name_list);
482e71b7053SJung-uk Kim }
483e71b7053SJung-uk Kim 
484e71b7053SJung-uk Kim void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
485e71b7053SJung-uk Kim {
486e71b7053SJung-uk Kim     set0_CA_list(&ctx->ca_names, name_list);
487e71b7053SJung-uk Kim }
488e71b7053SJung-uk Kim 
489e71b7053SJung-uk Kim const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx)
490e71b7053SJung-uk Kim {
491e71b7053SJung-uk Kim     return ctx->ca_names;
492e71b7053SJung-uk Kim }
493e71b7053SJung-uk Kim 
494e71b7053SJung-uk Kim const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s)
495e71b7053SJung-uk Kim {
496e71b7053SJung-uk Kim     return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names;
49774664626SKris Kennaway }
49874664626SKris Kennaway 
499ced566fdSJacques Vidrine void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
50074664626SKris Kennaway {
501c9cf7b5cSJung-uk Kim     set0_CA_list(&ctx->client_ca_names, name_list);
50274664626SKris Kennaway }
50374664626SKris Kennaway 
5043b4e3dcbSSimon L. B. Nielsen STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
50574664626SKris Kennaway {
506c9cf7b5cSJung-uk Kim     return ctx->client_ca_names;
507e71b7053SJung-uk Kim }
508e71b7053SJung-uk Kim 
509e71b7053SJung-uk Kim void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
510e71b7053SJung-uk Kim {
511c9cf7b5cSJung-uk Kim     set0_CA_list(&s->client_ca_names, name_list);
512e71b7053SJung-uk Kim }
513e71b7053SJung-uk Kim 
514e71b7053SJung-uk Kim const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s)
515e71b7053SJung-uk Kim {
516e71b7053SJung-uk Kim     return s->s3 != NULL ? s->s3->tmp.peer_ca_names : NULL;
51774664626SKris Kennaway }
51874664626SKris Kennaway 
5193b4e3dcbSSimon L. B. Nielsen STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
52074664626SKris Kennaway {
521e71b7053SJung-uk Kim     if (!s->server)
522e71b7053SJung-uk Kim         return s->s3 != NULL ?  s->s3->tmp.peer_ca_names : NULL;
523c9cf7b5cSJung-uk Kim     return s->client_ca_names != NULL ?  s->client_ca_names
524c9cf7b5cSJung-uk Kim                                       : s->ctx->client_ca_names;
52574664626SKris Kennaway }
52674664626SKris Kennaway 
527e71b7053SJung-uk Kim static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x)
52874664626SKris Kennaway {
52974664626SKris Kennaway     X509_NAME *name;
53074664626SKris Kennaway 
5316f9291ceSJung-uk Kim     if (x == NULL)
532e71b7053SJung-uk Kim         return 0;
533e71b7053SJung-uk Kim     if (*sk == NULL && ((*sk = sk_X509_NAME_new_null()) == NULL))
534e71b7053SJung-uk Kim         return 0;
53574664626SKris Kennaway 
53674664626SKris Kennaway     if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
537e71b7053SJung-uk Kim         return 0;
53874664626SKris Kennaway 
5396f9291ceSJung-uk Kim     if (!sk_X509_NAME_push(*sk, name)) {
54074664626SKris Kennaway         X509_NAME_free(name);
541e71b7053SJung-uk Kim         return 0;
54274664626SKris Kennaway     }
543e71b7053SJung-uk Kim     return 1;
54474664626SKris Kennaway }
54574664626SKris Kennaway 
546e71b7053SJung-uk Kim int SSL_add1_to_CA_list(SSL *ssl, const X509 *x)
547e71b7053SJung-uk Kim {
548e71b7053SJung-uk Kim     return add_ca_name(&ssl->ca_names, x);
549e71b7053SJung-uk Kim }
550e71b7053SJung-uk Kim 
551e71b7053SJung-uk Kim int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x)
552e71b7053SJung-uk Kim {
553e71b7053SJung-uk Kim     return add_ca_name(&ctx->ca_names, x);
554e71b7053SJung-uk Kim }
555e71b7053SJung-uk Kim 
556e71b7053SJung-uk Kim /*
557e71b7053SJung-uk Kim  * The following two are older names are to be replaced with
558e71b7053SJung-uk Kim  * SSL(_CTX)_add1_to_CA_list
559e71b7053SJung-uk Kim  */
56074664626SKris Kennaway int SSL_add_client_CA(SSL *ssl, X509 *x)
56174664626SKris Kennaway {
562c9cf7b5cSJung-uk Kim     return add_ca_name(&ssl->client_ca_names, x);
56374664626SKris Kennaway }
56474664626SKris Kennaway 
56574664626SKris Kennaway int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
56674664626SKris Kennaway {
567c9cf7b5cSJung-uk Kim     return add_ca_name(&ctx->client_ca_names, x);
56874664626SKris Kennaway }
56974664626SKris Kennaway 
570e71b7053SJung-uk Kim static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
57174664626SKris Kennaway {
572e71b7053SJung-uk Kim     unsigned char *abuf = NULL, *bbuf = NULL;
573e71b7053SJung-uk Kim     int alen, blen, ret;
574e71b7053SJung-uk Kim 
575e71b7053SJung-uk Kim     /* X509_NAME_cmp() itself casts away constness in this way, so
576e71b7053SJung-uk Kim      * assume it's safe:
577e71b7053SJung-uk Kim      */
578e71b7053SJung-uk Kim     alen = i2d_X509_NAME((X509_NAME *)a, &abuf);
579e71b7053SJung-uk Kim     blen = i2d_X509_NAME((X509_NAME *)b, &bbuf);
580e71b7053SJung-uk Kim 
581e71b7053SJung-uk Kim     if (alen < 0 || blen < 0)
582e71b7053SJung-uk Kim         ret = -2;
583e71b7053SJung-uk Kim     else if (alen != blen)
584e71b7053SJung-uk Kim         ret = alen - blen;
585e71b7053SJung-uk Kim     else /* alen == blen */
586e71b7053SJung-uk Kim         ret = memcmp(abuf, bbuf, alen);
587e71b7053SJung-uk Kim 
588e71b7053SJung-uk Kim     OPENSSL_free(abuf);
589e71b7053SJung-uk Kim     OPENSSL_free(bbuf);
590e71b7053SJung-uk Kim 
591e71b7053SJung-uk Kim     return ret;
59274664626SKris Kennaway }
59374664626SKris Kennaway 
594e71b7053SJung-uk Kim static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
595e71b7053SJung-uk Kim {
596e71b7053SJung-uk Kim     return xname_cmp(*a, *b);
597e71b7053SJung-uk Kim }
598e71b7053SJung-uk Kim 
599e71b7053SJung-uk Kim static unsigned long xname_hash(const X509_NAME *a)
600e71b7053SJung-uk Kim {
601e71b7053SJung-uk Kim     return X509_NAME_hash((X509_NAME *)a);
602e71b7053SJung-uk Kim }
603e71b7053SJung-uk Kim 
60474664626SKris Kennaway STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
60574664626SKris Kennaway {
606e71b7053SJung-uk Kim     BIO *in = BIO_new(BIO_s_file());
60774664626SKris Kennaway     X509 *x = NULL;
60874664626SKris Kennaway     X509_NAME *xn = NULL;
609e71b7053SJung-uk Kim     STACK_OF(X509_NAME) *ret = NULL;
610e71b7053SJung-uk Kim     LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
61174664626SKris Kennaway 
612e71b7053SJung-uk Kim     if ((name_hash == NULL) || (in == NULL)) {
61374664626SKris Kennaway         SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
61474664626SKris Kennaway         goto err;
61574664626SKris Kennaway     }
61674664626SKris Kennaway 
61774664626SKris Kennaway     if (!BIO_read_filename(in, file))
61874664626SKris Kennaway         goto err;
61974664626SKris Kennaway 
6206f9291ceSJung-uk Kim     for (;;) {
62174664626SKris Kennaway         if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
62274664626SKris Kennaway             break;
6236f9291ceSJung-uk Kim         if (ret == NULL) {
6243b4e3dcbSSimon L. B. Nielsen             ret = sk_X509_NAME_new_null();
6256f9291ceSJung-uk Kim             if (ret == NULL) {
6263b4e3dcbSSimon L. B. Nielsen                 SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
6273b4e3dcbSSimon L. B. Nielsen                 goto err;
6283b4e3dcbSSimon L. B. Nielsen             }
6293b4e3dcbSSimon L. B. Nielsen         }
6306f9291ceSJung-uk Kim         if ((xn = X509_get_subject_name(x)) == NULL)
6316f9291ceSJung-uk Kim             goto err;
63274664626SKris Kennaway         /* check for duplicates */
63374664626SKris Kennaway         xn = X509_NAME_dup(xn);
6346f9291ceSJung-uk Kim         if (xn == NULL)
6356f9291ceSJung-uk Kim             goto err;
636e71b7053SJung-uk Kim         if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) {
637e71b7053SJung-uk Kim             /* Duplicate. */
63874664626SKris Kennaway             X509_NAME_free(xn);
639e71b7053SJung-uk Kim             xn = NULL;
640e71b7053SJung-uk Kim         } else {
641e71b7053SJung-uk Kim             lh_X509_NAME_insert(name_hash, xn);
642e71b7053SJung-uk Kim             if (!sk_X509_NAME_push(ret, xn))
643e71b7053SJung-uk Kim                 goto err;
64474664626SKris Kennaway         }
64574664626SKris Kennaway     }
646e71b7053SJung-uk Kim     goto done;
64774664626SKris Kennaway 
64874664626SKris Kennaway  err:
649e71b7053SJung-uk Kim     X509_NAME_free(xn);
6506f9291ceSJung-uk Kim     sk_X509_NAME_pop_free(ret, X509_NAME_free);
65174664626SKris Kennaway     ret = NULL;
652e71b7053SJung-uk Kim  done:
6536f9291ceSJung-uk Kim     BIO_free(in);
6546f9291ceSJung-uk Kim     X509_free(x);
655e71b7053SJung-uk Kim     lh_X509_NAME_free(name_hash);
6563b4e3dcbSSimon L. B. Nielsen     if (ret != NULL)
6573b4e3dcbSSimon L. B. Nielsen         ERR_clear_error();
658e71b7053SJung-uk Kim     return ret;
65974664626SKris Kennaway }
66074664626SKris Kennaway 
66174664626SKris Kennaway int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
66274664626SKris Kennaway                                         const char *file)
66374664626SKris Kennaway {
66474664626SKris Kennaway     BIO *in;
66574664626SKris Kennaway     X509 *x = NULL;
66674664626SKris Kennaway     X509_NAME *xn = NULL;
66774664626SKris Kennaway     int ret = 1;
668ddd58736SKris Kennaway     int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
66974664626SKris Kennaway 
670e71b7053SJung-uk Kim     oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
67174664626SKris Kennaway 
672e71b7053SJung-uk Kim     in = BIO_new(BIO_s_file());
67374664626SKris Kennaway 
6746f9291ceSJung-uk Kim     if (in == NULL) {
675e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK, ERR_R_MALLOC_FAILURE);
67674664626SKris Kennaway         goto err;
67774664626SKris Kennaway     }
67874664626SKris Kennaway 
67974664626SKris Kennaway     if (!BIO_read_filename(in, file))
68074664626SKris Kennaway         goto err;
68174664626SKris Kennaway 
6826f9291ceSJung-uk Kim     for (;;) {
68374664626SKris Kennaway         if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
68474664626SKris Kennaway             break;
6856f9291ceSJung-uk Kim         if ((xn = X509_get_subject_name(x)) == NULL)
6866f9291ceSJung-uk Kim             goto err;
68774664626SKris Kennaway         xn = X509_NAME_dup(xn);
6886f9291ceSJung-uk Kim         if (xn == NULL)
6896f9291ceSJung-uk Kim             goto err;
690e71b7053SJung-uk Kim         if (sk_X509_NAME_find(stack, xn) >= 0) {
691e71b7053SJung-uk Kim             /* Duplicate. */
69274664626SKris Kennaway             X509_NAME_free(xn);
693e71b7053SJung-uk Kim         } else if (!sk_X509_NAME_push(stack, xn)) {
694e71b7053SJung-uk Kim             X509_NAME_free(xn);
695e71b7053SJung-uk Kim             goto err;
696e71b7053SJung-uk Kim         }
69774664626SKris Kennaway     }
69874664626SKris Kennaway 
699a3ddd25aSSimon L. B. Nielsen     ERR_clear_error();
700e71b7053SJung-uk Kim     goto done;
701a3ddd25aSSimon L. B. Nielsen 
70274664626SKris Kennaway  err:
70374664626SKris Kennaway     ret = 0;
704e71b7053SJung-uk Kim  done:
70574664626SKris Kennaway     BIO_free(in);
70674664626SKris Kennaway     X509_free(x);
707db522d3aSSimon L. B. Nielsen     (void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
70874664626SKris Kennaway     return ret;
70974664626SKris Kennaway }
71074664626SKris Kennaway 
71174664626SKris Kennaway int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
71274664626SKris Kennaway                                        const char *dir)
71374664626SKris Kennaway {
7143b4e3dcbSSimon L. B. Nielsen     OPENSSL_DIR_CTX *d = NULL;
7153b4e3dcbSSimon L. B. Nielsen     const char *filename;
71674664626SKris Kennaway     int ret = 0;
71774664626SKris Kennaway 
71874664626SKris Kennaway     /* Note that a side effect is that the CAs will be sorted by name */
71974664626SKris Kennaway 
7206f9291ceSJung-uk Kim     while ((filename = OPENSSL_DIR_read(&d, dir))) {
72174664626SKris Kennaway         char buf[1024];
722ddd58736SKris Kennaway         int r;
72374664626SKris Kennaway 
724dee36b4fSJung-uk Kim         if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
7256f9291ceSJung-uk Kim             SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK,
7266f9291ceSJung-uk Kim                    SSL_R_PATH_TOO_LONG);
72774664626SKris Kennaway             goto err;
72874664626SKris Kennaway         }
7293b4e3dcbSSimon L. B. Nielsen #ifdef OPENSSL_SYS_VMS
730dee36b4fSJung-uk Kim         r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename);
7313b4e3dcbSSimon L. B. Nielsen #else
732dee36b4fSJung-uk Kim         r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
7333b4e3dcbSSimon L. B. Nielsen #endif
7343b4e3dcbSSimon L. B. Nielsen         if (r <= 0 || r >= (int)sizeof(buf))
735ddd58736SKris Kennaway             goto err;
73674664626SKris Kennaway         if (!SSL_add_file_cert_subjects_to_stack(stack, buf))
73774664626SKris Kennaway             goto err;
73874664626SKris Kennaway     }
73974664626SKris Kennaway 
7406f9291ceSJung-uk Kim     if (errno) {
7415c87c606SMark Murray         SYSerr(SYS_F_OPENDIR, get_last_sys_error());
7423b4e3dcbSSimon L. B. Nielsen         ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
7435c87c606SMark Murray         SSLerr(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK, ERR_R_SYS_LIB);
7445c87c606SMark Murray         goto err;
7455c87c606SMark Murray     }
7465c87c606SMark Murray 
7475c87c606SMark Murray     ret = 1;
7485c87c606SMark Murray 
7495c87c606SMark Murray  err:
7506f9291ceSJung-uk Kim     if (d)
7516f9291ceSJung-uk Kim         OPENSSL_DIR_end(&d);
752e71b7053SJung-uk Kim 
7535c87c606SMark Murray     return ret;
7545c87c606SMark Murray }
7557bded2dbSJung-uk Kim 
7567bded2dbSJung-uk Kim /* Build a certificate chain for current certificate */
757e71b7053SJung-uk Kim int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
7587bded2dbSJung-uk Kim {
759e71b7053SJung-uk Kim     CERT *c = s ? s->cert : ctx->cert;
7607bded2dbSJung-uk Kim     CERT_PKEY *cpk = c->key;
761e71b7053SJung-uk Kim     X509_STORE *chain_store = NULL;
762e71b7053SJung-uk Kim     X509_STORE_CTX *xs_ctx = NULL;
7637bded2dbSJung-uk Kim     STACK_OF(X509) *chain = NULL, *untrusted = NULL;
7647bded2dbSJung-uk Kim     X509 *x;
7657bded2dbSJung-uk Kim     int i, rv = 0;
7667bded2dbSJung-uk Kim 
7677bded2dbSJung-uk Kim     if (!cpk->x509) {
7687bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_NO_CERTIFICATE_SET);
7697bded2dbSJung-uk Kim         goto err;
7707bded2dbSJung-uk Kim     }
7717bded2dbSJung-uk Kim     /* Rearranging and check the chain: add everything to a store */
7727bded2dbSJung-uk Kim     if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
7737bded2dbSJung-uk Kim         chain_store = X509_STORE_new();
774e71b7053SJung-uk Kim         if (chain_store == NULL)
7757bded2dbSJung-uk Kim             goto err;
7767bded2dbSJung-uk Kim         for (i = 0; i < sk_X509_num(cpk->chain); i++) {
7777bded2dbSJung-uk Kim             x = sk_X509_value(cpk->chain, i);
778e71b7053SJung-uk Kim             if (!X509_STORE_add_cert(chain_store, x))
7797bded2dbSJung-uk Kim                 goto err;
7807bded2dbSJung-uk Kim         }
7817bded2dbSJung-uk Kim         /* Add EE cert too: it might be self signed */
782e71b7053SJung-uk Kim         if (!X509_STORE_add_cert(chain_store, cpk->x509))
7837bded2dbSJung-uk Kim             goto err;
7847bded2dbSJung-uk Kim     } else {
7857bded2dbSJung-uk Kim         if (c->chain_store)
7867bded2dbSJung-uk Kim             chain_store = c->chain_store;
787e71b7053SJung-uk Kim         else if (s)
788e71b7053SJung-uk Kim             chain_store = s->ctx->cert_store;
789e71b7053SJung-uk Kim         else
790e71b7053SJung-uk Kim             chain_store = ctx->cert_store;
7917bded2dbSJung-uk Kim 
7927bded2dbSJung-uk Kim         if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
7937bded2dbSJung-uk Kim             untrusted = cpk->chain;
7947bded2dbSJung-uk Kim     }
7957bded2dbSJung-uk Kim 
796e71b7053SJung-uk Kim     xs_ctx = X509_STORE_CTX_new();
797e71b7053SJung-uk Kim     if (xs_ctx == NULL) {
798e71b7053SJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
799e71b7053SJung-uk Kim         goto err;
800e71b7053SJung-uk Kim     }
801e71b7053SJung-uk Kim     if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
8027bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
8037bded2dbSJung-uk Kim         goto err;
8047bded2dbSJung-uk Kim     }
8057bded2dbSJung-uk Kim     /* Set suite B flags if needed */
806e71b7053SJung-uk Kim     X509_STORE_CTX_set_flags(xs_ctx,
8077bded2dbSJung-uk Kim                              c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
8087bded2dbSJung-uk Kim 
809e71b7053SJung-uk Kim     i = X509_verify_cert(xs_ctx);
8107bded2dbSJung-uk Kim     if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
8117bded2dbSJung-uk Kim         if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
8127bded2dbSJung-uk Kim             ERR_clear_error();
8137bded2dbSJung-uk Kim         i = 1;
8147bded2dbSJung-uk Kim         rv = 2;
8157bded2dbSJung-uk Kim     }
8167bded2dbSJung-uk Kim     if (i > 0)
817e71b7053SJung-uk Kim         chain = X509_STORE_CTX_get1_chain(xs_ctx);
8187bded2dbSJung-uk Kim     if (i <= 0) {
8197bded2dbSJung-uk Kim         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
820e71b7053SJung-uk Kim         i = X509_STORE_CTX_get_error(xs_ctx);
8217bded2dbSJung-uk Kim         ERR_add_error_data(2, "Verify error:",
8227bded2dbSJung-uk Kim                            X509_verify_cert_error_string(i));
8237bded2dbSJung-uk Kim 
8247bded2dbSJung-uk Kim         goto err;
8257bded2dbSJung-uk Kim     }
8267bded2dbSJung-uk Kim     /* Remove EE certificate from chain */
8277bded2dbSJung-uk Kim     x = sk_X509_shift(chain);
8287bded2dbSJung-uk Kim     X509_free(x);
8297bded2dbSJung-uk Kim     if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
8307bded2dbSJung-uk Kim         if (sk_X509_num(chain) > 0) {
8317bded2dbSJung-uk Kim             /* See if last cert is self signed */
8327bded2dbSJung-uk Kim             x = sk_X509_value(chain, sk_X509_num(chain) - 1);
833e71b7053SJung-uk Kim             if (X509_get_extension_flags(x) & EXFLAG_SS) {
8347bded2dbSJung-uk Kim                 x = sk_X509_pop(chain);
8357bded2dbSJung-uk Kim                 X509_free(x);
8367bded2dbSJung-uk Kim             }
8377bded2dbSJung-uk Kim         }
8387bded2dbSJung-uk Kim     }
839e71b7053SJung-uk Kim     /*
840e71b7053SJung-uk Kim      * Check security level of all CA certificates: EE will have been checked
841e71b7053SJung-uk Kim      * already.
842e71b7053SJung-uk Kim      */
843e71b7053SJung-uk Kim     for (i = 0; i < sk_X509_num(chain); i++) {
844e71b7053SJung-uk Kim         x = sk_X509_value(chain, i);
845e71b7053SJung-uk Kim         rv = ssl_security_cert(s, ctx, x, 0, 0);
846e71b7053SJung-uk Kim         if (rv != 1) {
847e71b7053SJung-uk Kim             SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, rv);
848e71b7053SJung-uk Kim             sk_X509_pop_free(chain, X509_free);
849e71b7053SJung-uk Kim             rv = 0;
850e71b7053SJung-uk Kim             goto err;
851e71b7053SJung-uk Kim         }
852e71b7053SJung-uk Kim     }
853e71b7053SJung-uk Kim     sk_X509_pop_free(cpk->chain, X509_free);
8547bded2dbSJung-uk Kim     cpk->chain = chain;
8557bded2dbSJung-uk Kim     if (rv == 0)
8567bded2dbSJung-uk Kim         rv = 1;
8577bded2dbSJung-uk Kim  err:
8587bded2dbSJung-uk Kim     if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
8597bded2dbSJung-uk Kim         X509_STORE_free(chain_store);
860e71b7053SJung-uk Kim     X509_STORE_CTX_free(xs_ctx);
8617bded2dbSJung-uk Kim 
8627bded2dbSJung-uk Kim     return rv;
8637bded2dbSJung-uk Kim }
8647bded2dbSJung-uk Kim 
8657bded2dbSJung-uk Kim int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
8667bded2dbSJung-uk Kim {
8677bded2dbSJung-uk Kim     X509_STORE **pstore;
8687bded2dbSJung-uk Kim     if (chain)
8697bded2dbSJung-uk Kim         pstore = &c->chain_store;
8707bded2dbSJung-uk Kim     else
8717bded2dbSJung-uk Kim         pstore = &c->verify_store;
8727bded2dbSJung-uk Kim     X509_STORE_free(*pstore);
8737bded2dbSJung-uk Kim     *pstore = store;
8747bded2dbSJung-uk Kim     if (ref && store)
875e71b7053SJung-uk Kim         X509_STORE_up_ref(store);
8767bded2dbSJung-uk Kim     return 1;
8777bded2dbSJung-uk Kim }
878e71b7053SJung-uk Kim 
879*9a3ae0cdSJung-uk Kim int ssl_get_security_level_bits(const SSL *s, const SSL_CTX *ctx, int *levelp)
880*9a3ae0cdSJung-uk Kim {
881*9a3ae0cdSJung-uk Kim     int level;
882*9a3ae0cdSJung-uk Kim     static const int minbits_table[5 + 1] = { 0, 80, 112, 128, 192, 256 };
883*9a3ae0cdSJung-uk Kim 
884*9a3ae0cdSJung-uk Kim     if (ctx != NULL)
885*9a3ae0cdSJung-uk Kim         level = SSL_CTX_get_security_level(ctx);
886*9a3ae0cdSJung-uk Kim     else
887*9a3ae0cdSJung-uk Kim         level = SSL_get_security_level(s);
888*9a3ae0cdSJung-uk Kim 
889*9a3ae0cdSJung-uk Kim     if (level > 5)
890*9a3ae0cdSJung-uk Kim         level = 5;
891*9a3ae0cdSJung-uk Kim     else if (level < 0)
892*9a3ae0cdSJung-uk Kim         level = 0;
893*9a3ae0cdSJung-uk Kim 
894*9a3ae0cdSJung-uk Kim     if (levelp != NULL)
895*9a3ae0cdSJung-uk Kim         *levelp = level;
896*9a3ae0cdSJung-uk Kim 
897*9a3ae0cdSJung-uk Kim     return minbits_table[level];
898*9a3ae0cdSJung-uk Kim }
899*9a3ae0cdSJung-uk Kim 
900e71b7053SJung-uk Kim static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
901e71b7053SJung-uk Kim                                          int op, int bits, int nid, void *other,
902e71b7053SJung-uk Kim                                          void *ex)
903e71b7053SJung-uk Kim {
904e71b7053SJung-uk Kim     int level, minbits;
905e71b7053SJung-uk Kim 
906*9a3ae0cdSJung-uk Kim     minbits = ssl_get_security_level_bits(s, ctx, &level);
907*9a3ae0cdSJung-uk Kim 
908*9a3ae0cdSJung-uk Kim     if (level == 0) {
909e71b7053SJung-uk Kim         /*
910e71b7053SJung-uk Kim          * No EDH keys weaker than 1024-bits even at level 0, otherwise,
911e71b7053SJung-uk Kim          * anything goes.
912e71b7053SJung-uk Kim          */
913e71b7053SJung-uk Kim         if (op == SSL_SECOP_TMP_DH && bits < 80)
914e71b7053SJung-uk Kim             return 0;
915e71b7053SJung-uk Kim         return 1;
916e71b7053SJung-uk Kim     }
917e71b7053SJung-uk Kim     switch (op) {
918e71b7053SJung-uk Kim     case SSL_SECOP_CIPHER_SUPPORTED:
919e71b7053SJung-uk Kim     case SSL_SECOP_CIPHER_SHARED:
920e71b7053SJung-uk Kim     case SSL_SECOP_CIPHER_CHECK:
921e71b7053SJung-uk Kim         {
922e71b7053SJung-uk Kim             const SSL_CIPHER *c = other;
923e71b7053SJung-uk Kim             /* No ciphers below security level */
924e71b7053SJung-uk Kim             if (bits < minbits)
925e71b7053SJung-uk Kim                 return 0;
926e71b7053SJung-uk Kim             /* No unauthenticated ciphersuites */
927e71b7053SJung-uk Kim             if (c->algorithm_auth & SSL_aNULL)
928e71b7053SJung-uk Kim                 return 0;
929e71b7053SJung-uk Kim             /* No MD5 mac ciphersuites */
930e71b7053SJung-uk Kim             if (c->algorithm_mac & SSL_MD5)
931e71b7053SJung-uk Kim                 return 0;
932e71b7053SJung-uk Kim             /* SHA1 HMAC is 160 bits of security */
933e71b7053SJung-uk Kim             if (minbits > 160 && c->algorithm_mac & SSL_SHA1)
934e71b7053SJung-uk Kim                 return 0;
935e71b7053SJung-uk Kim             /* Level 2: no RC4 */
936e71b7053SJung-uk Kim             if (level >= 2 && c->algorithm_enc == SSL_RC4)
937e71b7053SJung-uk Kim                 return 0;
938e71b7053SJung-uk Kim             /* Level 3: forward secure ciphersuites only */
939c9cf7b5cSJung-uk Kim             if (level >= 3 && c->min_tls != TLS1_3_VERSION &&
940c9cf7b5cSJung-uk Kim                                !(c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)))
941e71b7053SJung-uk Kim                 return 0;
942e71b7053SJung-uk Kim             break;
943e71b7053SJung-uk Kim         }
944e71b7053SJung-uk Kim     case SSL_SECOP_VERSION:
945e71b7053SJung-uk Kim         if (!SSL_IS_DTLS(s)) {
946e71b7053SJung-uk Kim             /* SSLv3 not allowed at level 2 */
947e71b7053SJung-uk Kim             if (nid <= SSL3_VERSION && level >= 2)
948e71b7053SJung-uk Kim                 return 0;
949e71b7053SJung-uk Kim             /* TLS v1.1 and above only for level 3 */
950e71b7053SJung-uk Kim             if (nid <= TLS1_VERSION && level >= 3)
951e71b7053SJung-uk Kim                 return 0;
952e71b7053SJung-uk Kim             /* TLS v1.2 only for level 4 and above */
953e71b7053SJung-uk Kim             if (nid <= TLS1_1_VERSION && level >= 4)
954e71b7053SJung-uk Kim                 return 0;
955e71b7053SJung-uk Kim         } else {
956e71b7053SJung-uk Kim             /* DTLS v1.2 only for level 4 and above */
957e71b7053SJung-uk Kim             if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
958e71b7053SJung-uk Kim                 return 0;
959e71b7053SJung-uk Kim         }
960e71b7053SJung-uk Kim         break;
961e71b7053SJung-uk Kim 
962e71b7053SJung-uk Kim     case SSL_SECOP_COMPRESSION:
963e71b7053SJung-uk Kim         if (level >= 2)
964e71b7053SJung-uk Kim             return 0;
965e71b7053SJung-uk Kim         break;
966e71b7053SJung-uk Kim     case SSL_SECOP_TICKET:
967e71b7053SJung-uk Kim         if (level >= 3)
968e71b7053SJung-uk Kim             return 0;
969e71b7053SJung-uk Kim         break;
970e71b7053SJung-uk Kim     default:
971e71b7053SJung-uk Kim         if (bits < minbits)
972e71b7053SJung-uk Kim             return 0;
973e71b7053SJung-uk Kim     }
974e71b7053SJung-uk Kim     return 1;
975e71b7053SJung-uk Kim }
976e71b7053SJung-uk Kim 
977e71b7053SJung-uk Kim int ssl_security(const SSL *s, int op, int bits, int nid, void *other)
978e71b7053SJung-uk Kim {
979e71b7053SJung-uk Kim     return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex);
980e71b7053SJung-uk Kim }
981e71b7053SJung-uk Kim 
982e71b7053SJung-uk Kim int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
983e71b7053SJung-uk Kim {
984e71b7053SJung-uk Kim     return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other,
985e71b7053SJung-uk Kim                              ctx->cert->sec_ex);
986e71b7053SJung-uk Kim }
987e71b7053SJung-uk Kim 
988e71b7053SJung-uk Kim int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
989e71b7053SJung-uk Kim {
990e71b7053SJung-uk Kim     size_t i;
991e71b7053SJung-uk Kim 
992e71b7053SJung-uk Kim     for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
993e71b7053SJung-uk Kim         if (ssl_cert_info[i].nid == nid) {
994e71b7053SJung-uk Kim             *pidx = i;
995e71b7053SJung-uk Kim             return 1;
996e71b7053SJung-uk Kim         }
997e71b7053SJung-uk Kim     }
998e71b7053SJung-uk Kim 
999e71b7053SJung-uk Kim     return 0;
1000e71b7053SJung-uk Kim }
1001e71b7053SJung-uk Kim 
1002e71b7053SJung-uk Kim const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
1003e71b7053SJung-uk Kim {
1004e71b7053SJung-uk Kim     int nid = EVP_PKEY_id(pk);
1005e71b7053SJung-uk Kim     size_t tmpidx;
1006e71b7053SJung-uk Kim 
1007e71b7053SJung-uk Kim     if (nid == NID_undef)
1008e71b7053SJung-uk Kim         return NULL;
1009e71b7053SJung-uk Kim 
1010e71b7053SJung-uk Kim     if (!ssl_cert_lookup_by_nid(nid, &tmpidx))
1011e71b7053SJung-uk Kim         return NULL;
1012e71b7053SJung-uk Kim 
1013e71b7053SJung-uk Kim     if (pidx != NULL)
1014e71b7053SJung-uk Kim         *pidx = tmpidx;
1015e71b7053SJung-uk Kim 
1016e71b7053SJung-uk Kim     return &ssl_cert_info[tmpidx];
1017e71b7053SJung-uk Kim }
1018e71b7053SJung-uk Kim 
1019e71b7053SJung-uk Kim const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
1020e71b7053SJung-uk Kim {
1021e71b7053SJung-uk Kim     if (idx >= OSSL_NELEM(ssl_cert_info))
1022e71b7053SJung-uk Kim         return NULL;
1023e71b7053SJung-uk Kim     return &ssl_cert_info[idx];
1024e71b7053SJung-uk Kim }
1025