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