16f9291ceSJung-uk Kim /*
2*b077aed3SPierre Pronchery * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
474664626SKris Kennaway *
5*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (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>
18*b077aed3SPierre Pronchery #include <openssl/store.h>
19f579bf8eSKris Kennaway #include <openssl/x509v3.h>
203b4e3dcbSSimon L. B. Nielsen #include <openssl/dh.h>
213b4e3dcbSSimon L. B. Nielsen #include <openssl/bn.h>
22e71b7053SJung-uk Kim #include <openssl/crypto.h>
23e71b7053SJung-uk Kim #include "internal/refcount.h"
2417f01e99SJung-uk Kim #include "ssl_local.h"
25e71b7053SJung-uk Kim #include "ssl_cert_table.h"
26e71b7053SJung-uk Kim #include "internal/thread_once.h"
27*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO
28*b077aed3SPierre Pronchery # include <sys/stat.h>
29*b077aed3SPierre Pronchery # ifdef _WIN32
30*b077aed3SPierre Pronchery # define stat _stat
31*b077aed3SPierre Pronchery # endif
32*b077aed3SPierre Pronchery # ifndef S_ISDIR
33*b077aed3SPierre Pronchery # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR)
34*b077aed3SPierre Pronchery # endif
35*b077aed3SPierre Pronchery #endif
36*b077aed3SPierre Pronchery
37e71b7053SJung-uk Kim
38e71b7053SJung-uk Kim static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
39e71b7053SJung-uk Kim int op, int bits, int nid, void *other,
40e71b7053SJung-uk Kim void *ex);
41e71b7053SJung-uk Kim
42e71b7053SJung-uk Kim static CRYPTO_ONCE ssl_x509_store_ctx_once = CRYPTO_ONCE_STATIC_INIT;
43e71b7053SJung-uk Kim static volatile int ssl_x509_store_ctx_idx = -1;
44e71b7053SJung-uk Kim
DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init)45e71b7053SJung-uk Kim DEFINE_RUN_ONCE_STATIC(ssl_x509_store_ctx_init)
46e71b7053SJung-uk Kim {
47e71b7053SJung-uk Kim ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index(0,
48e71b7053SJung-uk Kim "SSL for verify callback",
49e71b7053SJung-uk Kim NULL, NULL, NULL);
50e71b7053SJung-uk Kim return ssl_x509_store_ctx_idx >= 0;
51e71b7053SJung-uk Kim }
5274664626SKris Kennaway
SSL_get_ex_data_X509_STORE_CTX_idx(void)5374664626SKris Kennaway int SSL_get_ex_data_X509_STORE_CTX_idx(void)
5474664626SKris Kennaway {
55ed5d4f9aSSimon L. B. Nielsen
56e71b7053SJung-uk Kim if (!RUN_ONCE(&ssl_x509_store_ctx_once, ssl_x509_store_ctx_init))
57e71b7053SJung-uk Kim return -1;
585c87c606SMark Murray return ssl_x509_store_ctx_idx;
5974664626SKris Kennaway }
601f13597dSJung-uk Kim
ssl_cert_new(void)6174664626SKris Kennaway CERT *ssl_cert_new(void)
6274664626SKris Kennaway {
63e71b7053SJung-uk Kim CERT *ret = OPENSSL_zalloc(sizeof(*ret));
6474664626SKris Kennaway
656f9291ceSJung-uk Kim if (ret == NULL) {
66*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
67e71b7053SJung-uk Kim return NULL;
6874664626SKris Kennaway }
6974664626SKris Kennaway
70e71b7053SJung-uk Kim ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
7174664626SKris Kennaway ret->references = 1;
72e71b7053SJung-uk Kim ret->sec_cb = ssl_security_default_callback;
73e71b7053SJung-uk Kim ret->sec_level = OPENSSL_TLS_SECURITY_LEVEL;
74e71b7053SJung-uk Kim ret->sec_ex = NULL;
75e71b7053SJung-uk Kim ret->lock = CRYPTO_THREAD_lock_new();
76e71b7053SJung-uk Kim if (ret->lock == NULL) {
77*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
78e71b7053SJung-uk Kim OPENSSL_free(ret);
79e71b7053SJung-uk Kim return NULL;
80e71b7053SJung-uk Kim }
81e71b7053SJung-uk Kim
82e71b7053SJung-uk Kim return ret;
8374664626SKris Kennaway }
8474664626SKris Kennaway
ssl_cert_dup(CERT * cert)8574664626SKris Kennaway CERT *ssl_cert_dup(CERT *cert)
8674664626SKris Kennaway {
87e71b7053SJung-uk Kim CERT *ret = OPENSSL_zalloc(sizeof(*ret));
8874664626SKris Kennaway int i;
8974664626SKris Kennaway
906f9291ceSJung-uk Kim if (ret == NULL) {
91*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
92e71b7053SJung-uk Kim return NULL;
9374664626SKris Kennaway }
9474664626SKris Kennaway
9580815a77SJung-uk Kim ret->references = 1;
96e71b7053SJung-uk Kim ret->key = &ret->pkeys[cert->key - cert->pkeys];
97e71b7053SJung-uk Kim ret->lock = CRYPTO_THREAD_lock_new();
98e71b7053SJung-uk Kim if (ret->lock == NULL) {
99*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
100e71b7053SJung-uk Kim OPENSSL_free(ret);
101e71b7053SJung-uk Kim return NULL;
10274664626SKris Kennaway }
103*b077aed3SPierre Pronchery
1046f9291ceSJung-uk Kim if (cert->dh_tmp != NULL) {
105e71b7053SJung-uk Kim ret->dh_tmp = cert->dh_tmp;
106e71b7053SJung-uk Kim EVP_PKEY_up_ref(ret->dh_tmp);
10774664626SKris Kennaway }
108*b077aed3SPierre Pronchery
10974664626SKris Kennaway ret->dh_tmp_cb = cert->dh_tmp_cb;
110e71b7053SJung-uk Kim ret->dh_tmp_auto = cert->dh_tmp_auto;
1113b4e3dcbSSimon L. B. Nielsen
1126f9291ceSJung-uk Kim for (i = 0; i < SSL_PKEY_NUM; i++) {
1137bded2dbSJung-uk Kim CERT_PKEY *cpk = cert->pkeys + i;
1147bded2dbSJung-uk Kim CERT_PKEY *rpk = ret->pkeys + i;
1157bded2dbSJung-uk Kim if (cpk->x509 != NULL) {
1167bded2dbSJung-uk Kim rpk->x509 = cpk->x509;
117e71b7053SJung-uk Kim X509_up_ref(rpk->x509);
11874664626SKris Kennaway }
11974664626SKris Kennaway
1207bded2dbSJung-uk Kim if (cpk->privatekey != NULL) {
1217bded2dbSJung-uk Kim rpk->privatekey = cpk->privatekey;
122e71b7053SJung-uk Kim EVP_PKEY_up_ref(cpk->privatekey);
12374664626SKris Kennaway }
12474664626SKris Kennaway
1257bded2dbSJung-uk Kim if (cpk->chain) {
1267bded2dbSJung-uk Kim rpk->chain = X509_chain_up_ref(cpk->chain);
1277bded2dbSJung-uk Kim if (!rpk->chain) {
128*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
1297bded2dbSJung-uk Kim goto err;
1307bded2dbSJung-uk Kim }
1317bded2dbSJung-uk Kim }
1327bded2dbSJung-uk Kim if (cert->pkeys[i].serverinfo != NULL) {
1337bded2dbSJung-uk Kim /* Just copy everything. */
1347bded2dbSJung-uk Kim ret->pkeys[i].serverinfo =
1357bded2dbSJung-uk Kim OPENSSL_malloc(cert->pkeys[i].serverinfo_length);
1367bded2dbSJung-uk Kim if (ret->pkeys[i].serverinfo == NULL) {
137*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
1386cf8931aSJung-uk Kim goto err;
1397bded2dbSJung-uk Kim }
140e71b7053SJung-uk Kim ret->pkeys[i].serverinfo_length = cert->pkeys[i].serverinfo_length;
1417bded2dbSJung-uk Kim memcpy(ret->pkeys[i].serverinfo,
142e71b7053SJung-uk Kim cert->pkeys[i].serverinfo, cert->pkeys[i].serverinfo_length);
1437bded2dbSJung-uk Kim }
1447bded2dbSJung-uk Kim }
14574664626SKris Kennaway
146e71b7053SJung-uk Kim /* Configured sigalgs copied across */
1477bded2dbSJung-uk Kim if (cert->conf_sigalgs) {
148e71b7053SJung-uk Kim ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen
149e71b7053SJung-uk Kim * sizeof(*cert->conf_sigalgs));
150e71b7053SJung-uk Kim if (ret->conf_sigalgs == NULL)
1517bded2dbSJung-uk Kim goto err;
152e71b7053SJung-uk Kim memcpy(ret->conf_sigalgs, cert->conf_sigalgs,
153e71b7053SJung-uk Kim cert->conf_sigalgslen * sizeof(*cert->conf_sigalgs));
1547bded2dbSJung-uk Kim ret->conf_sigalgslen = cert->conf_sigalgslen;
1557bded2dbSJung-uk Kim } else
1567bded2dbSJung-uk Kim ret->conf_sigalgs = NULL;
1577bded2dbSJung-uk Kim
1587bded2dbSJung-uk Kim if (cert->client_sigalgs) {
159e71b7053SJung-uk Kim ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen
160e71b7053SJung-uk Kim * sizeof(*cert->client_sigalgs));
161e71b7053SJung-uk Kim if (ret->client_sigalgs == NULL)
1627bded2dbSJung-uk Kim goto err;
1637bded2dbSJung-uk Kim memcpy(ret->client_sigalgs, cert->client_sigalgs,
164e71b7053SJung-uk Kim cert->client_sigalgslen * sizeof(*cert->client_sigalgs));
1657bded2dbSJung-uk Kim ret->client_sigalgslen = cert->client_sigalgslen;
1667bded2dbSJung-uk Kim } else
1677bded2dbSJung-uk Kim ret->client_sigalgs = NULL;
1687bded2dbSJung-uk Kim /* Copy any custom client certificate types */
169e71b7053SJung-uk Kim if (cert->ctype) {
170e71b7053SJung-uk Kim ret->ctype = OPENSSL_memdup(cert->ctype, cert->ctype_len);
171e71b7053SJung-uk Kim if (ret->ctype == NULL)
1727bded2dbSJung-uk Kim goto err;
173e71b7053SJung-uk Kim ret->ctype_len = cert->ctype_len;
1747bded2dbSJung-uk Kim }
1757bded2dbSJung-uk Kim
1767bded2dbSJung-uk Kim ret->cert_flags = cert->cert_flags;
1777bded2dbSJung-uk Kim
1787bded2dbSJung-uk Kim ret->cert_cb = cert->cert_cb;
1797bded2dbSJung-uk Kim ret->cert_cb_arg = cert->cert_cb_arg;
1807bded2dbSJung-uk Kim
1817bded2dbSJung-uk Kim if (cert->verify_store) {
182e71b7053SJung-uk Kim X509_STORE_up_ref(cert->verify_store);
1837bded2dbSJung-uk Kim ret->verify_store = cert->verify_store;
1847bded2dbSJung-uk Kim }
1857bded2dbSJung-uk Kim
1867bded2dbSJung-uk Kim if (cert->chain_store) {
187e71b7053SJung-uk Kim X509_STORE_up_ref(cert->chain_store);
1887bded2dbSJung-uk Kim ret->chain_store = cert->chain_store;
1897bded2dbSJung-uk Kim }
1907bded2dbSJung-uk Kim
191e71b7053SJung-uk Kim ret->sec_cb = cert->sec_cb;
192e71b7053SJung-uk Kim ret->sec_level = cert->sec_level;
193e71b7053SJung-uk Kim ret->sec_ex = cert->sec_ex;
1947bded2dbSJung-uk Kim
195e71b7053SJung-uk Kim if (!custom_exts_copy(&ret->custext, &cert->custext))
1967bded2dbSJung-uk Kim goto err;
197e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK
198e71b7053SJung-uk Kim if (cert->psk_identity_hint) {
199e71b7053SJung-uk Kim ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint);
200e71b7053SJung-uk Kim if (ret->psk_identity_hint == NULL)
2017bded2dbSJung-uk Kim goto err;
202e71b7053SJung-uk Kim }
2037bded2dbSJung-uk Kim #endif
204e71b7053SJung-uk Kim return ret;
20574664626SKris Kennaway
20674664626SKris Kennaway err:
207e71b7053SJung-uk Kim ssl_cert_free(ret);
20874664626SKris Kennaway
20974664626SKris Kennaway return NULL;
21074664626SKris Kennaway }
21174664626SKris Kennaway
2127bded2dbSJung-uk Kim /* Free up and clear all certificates and chains */
2137bded2dbSJung-uk Kim
ssl_cert_clear_certs(CERT * c)2147bded2dbSJung-uk Kim void ssl_cert_clear_certs(CERT *c)
2157bded2dbSJung-uk Kim {
2167bded2dbSJung-uk Kim int i;
2177bded2dbSJung-uk Kim if (c == NULL)
2187bded2dbSJung-uk Kim return;
2197bded2dbSJung-uk Kim for (i = 0; i < SSL_PKEY_NUM; i++) {
2207bded2dbSJung-uk Kim CERT_PKEY *cpk = c->pkeys + i;
2217bded2dbSJung-uk Kim X509_free(cpk->x509);
2227bded2dbSJung-uk Kim cpk->x509 = NULL;
2237bded2dbSJung-uk Kim EVP_PKEY_free(cpk->privatekey);
2247bded2dbSJung-uk Kim cpk->privatekey = NULL;
2257bded2dbSJung-uk Kim sk_X509_pop_free(cpk->chain, X509_free);
2267bded2dbSJung-uk Kim cpk->chain = NULL;
2277bded2dbSJung-uk Kim OPENSSL_free(cpk->serverinfo);
2287bded2dbSJung-uk Kim cpk->serverinfo = NULL;
2297bded2dbSJung-uk Kim cpk->serverinfo_length = 0;
2307bded2dbSJung-uk Kim }
2317bded2dbSJung-uk Kim }
2327bded2dbSJung-uk Kim
ssl_cert_free(CERT * c)23374664626SKris Kennaway void ssl_cert_free(CERT *c)
23474664626SKris Kennaway {
23574664626SKris Kennaway int i;
23674664626SKris Kennaway
23774664626SKris Kennaway if (c == NULL)
23874664626SKris Kennaway return;
239e71b7053SJung-uk Kim CRYPTO_DOWN_REF(&c->references, &i, c->lock);
240e71b7053SJung-uk Kim REF_PRINT_COUNT("CERT", c);
2416f9291ceSJung-uk Kim if (i > 0)
2426f9291ceSJung-uk Kim return;
243e71b7053SJung-uk Kim REF_ASSERT_ISNT(i < 0);
24474664626SKris Kennaway
245e71b7053SJung-uk Kim EVP_PKEY_free(c->dh_tmp);
24674664626SKris Kennaway
2477bded2dbSJung-uk Kim ssl_cert_clear_certs(c);
2487bded2dbSJung-uk Kim OPENSSL_free(c->conf_sigalgs);
2497bded2dbSJung-uk Kim OPENSSL_free(c->client_sigalgs);
250e71b7053SJung-uk Kim OPENSSL_free(c->ctype);
2517bded2dbSJung-uk Kim X509_STORE_free(c->verify_store);
2527bded2dbSJung-uk Kim X509_STORE_free(c->chain_store);
253e71b7053SJung-uk Kim custom_exts_free(&c->custext);
254e71b7053SJung-uk Kim #ifndef OPENSSL_NO_PSK
255e71b7053SJung-uk Kim OPENSSL_free(c->psk_identity_hint);
25674664626SKris Kennaway #endif
257e71b7053SJung-uk Kim CRYPTO_THREAD_lock_free(c->lock);
258ddd58736SKris Kennaway OPENSSL_free(c);
25974664626SKris Kennaway }
26074664626SKris Kennaway
ssl_cert_set0_chain(SSL * s,SSL_CTX * ctx,STACK_OF (X509)* chain)261e71b7053SJung-uk Kim int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
26274664626SKris Kennaway {
263e71b7053SJung-uk Kim int i, r;
264*b077aed3SPierre Pronchery CERT_PKEY *cpk = s != NULL ? s->cert->key : ctx->cert->key;
265*b077aed3SPierre Pronchery
2667bded2dbSJung-uk Kim if (!cpk)
2677bded2dbSJung-uk Kim return 0;
268e71b7053SJung-uk Kim for (i = 0; i < sk_X509_num(chain); i++) {
269*b077aed3SPierre Pronchery X509 *x = sk_X509_value(chain, i);
270*b077aed3SPierre Pronchery
271*b077aed3SPierre Pronchery r = ssl_security_cert(s, ctx, x, 0, 0);
272e71b7053SJung-uk Kim if (r != 1) {
273*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, r);
274e71b7053SJung-uk Kim return 0;
275e71b7053SJung-uk Kim }
276e71b7053SJung-uk Kim }
2777bded2dbSJung-uk Kim sk_X509_pop_free(cpk->chain, X509_free);
2787bded2dbSJung-uk Kim cpk->chain = chain;
2797bded2dbSJung-uk Kim return 1;
2807bded2dbSJung-uk Kim }
2817bded2dbSJung-uk Kim
ssl_cert_set1_chain(SSL * s,SSL_CTX * ctx,STACK_OF (X509)* chain)282e71b7053SJung-uk Kim int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
2837bded2dbSJung-uk Kim {
2847bded2dbSJung-uk Kim STACK_OF(X509) *dchain;
2857bded2dbSJung-uk Kim if (!chain)
286e71b7053SJung-uk Kim return ssl_cert_set0_chain(s, ctx, NULL);
2877bded2dbSJung-uk Kim dchain = X509_chain_up_ref(chain);
2887bded2dbSJung-uk Kim if (!dchain)
2897bded2dbSJung-uk Kim return 0;
290e71b7053SJung-uk Kim if (!ssl_cert_set0_chain(s, ctx, dchain)) {
2917bded2dbSJung-uk Kim sk_X509_pop_free(dchain, X509_free);
2927bded2dbSJung-uk Kim return 0;
2937bded2dbSJung-uk Kim }
2947bded2dbSJung-uk Kim return 1;
2957bded2dbSJung-uk Kim }
2967bded2dbSJung-uk Kim
ssl_cert_add0_chain_cert(SSL * s,SSL_CTX * ctx,X509 * x)297e71b7053SJung-uk Kim int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
2987bded2dbSJung-uk Kim {
299e71b7053SJung-uk Kim int r;
300e71b7053SJung-uk Kim CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
3017bded2dbSJung-uk Kim if (!cpk)
3027bded2dbSJung-uk Kim return 0;
303e71b7053SJung-uk Kim r = ssl_security_cert(s, ctx, x, 0, 0);
304e71b7053SJung-uk Kim if (r != 1) {
305*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, r);
306e71b7053SJung-uk Kim return 0;
307e71b7053SJung-uk Kim }
3087bded2dbSJung-uk Kim if (!cpk->chain)
3097bded2dbSJung-uk Kim cpk->chain = sk_X509_new_null();
3107bded2dbSJung-uk Kim if (!cpk->chain || !sk_X509_push(cpk->chain, x))
3117bded2dbSJung-uk Kim return 0;
3127bded2dbSJung-uk Kim return 1;
3137bded2dbSJung-uk Kim }
3147bded2dbSJung-uk Kim
ssl_cert_add1_chain_cert(SSL * s,SSL_CTX * ctx,X509 * x)315e71b7053SJung-uk Kim int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x)
3167bded2dbSJung-uk Kim {
317e71b7053SJung-uk Kim if (!ssl_cert_add0_chain_cert(s, ctx, x))
3187bded2dbSJung-uk Kim return 0;
319e71b7053SJung-uk Kim X509_up_ref(x);
3207bded2dbSJung-uk Kim return 1;
3217bded2dbSJung-uk Kim }
3227bded2dbSJung-uk Kim
ssl_cert_select_current(CERT * c,X509 * x)3237bded2dbSJung-uk Kim int ssl_cert_select_current(CERT *c, X509 *x)
3247bded2dbSJung-uk Kim {
3257bded2dbSJung-uk Kim int i;
3267bded2dbSJung-uk Kim if (x == NULL)
3277bded2dbSJung-uk Kim return 0;
3287bded2dbSJung-uk Kim for (i = 0; i < SSL_PKEY_NUM; i++) {
3297bded2dbSJung-uk Kim CERT_PKEY *cpk = c->pkeys + i;
3307bded2dbSJung-uk Kim if (cpk->x509 == x && cpk->privatekey) {
3317bded2dbSJung-uk Kim c->key = cpk;
3327bded2dbSJung-uk Kim return 1;
3337bded2dbSJung-uk Kim }
3347bded2dbSJung-uk Kim }
3357bded2dbSJung-uk Kim
3367bded2dbSJung-uk Kim for (i = 0; i < SSL_PKEY_NUM; i++) {
3377bded2dbSJung-uk Kim CERT_PKEY *cpk = c->pkeys + i;
3387bded2dbSJung-uk Kim if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
3397bded2dbSJung-uk Kim c->key = cpk;
3407bded2dbSJung-uk Kim return 1;
3417bded2dbSJung-uk Kim }
3427bded2dbSJung-uk Kim }
3437bded2dbSJung-uk Kim return 0;
3447bded2dbSJung-uk Kim }
3457bded2dbSJung-uk Kim
ssl_cert_set_current(CERT * c,long op)3467bded2dbSJung-uk Kim int ssl_cert_set_current(CERT *c, long op)
3477bded2dbSJung-uk Kim {
3487bded2dbSJung-uk Kim int i, idx;
3497bded2dbSJung-uk Kim if (!c)
3507bded2dbSJung-uk Kim return 0;
3517bded2dbSJung-uk Kim if (op == SSL_CERT_SET_FIRST)
3527bded2dbSJung-uk Kim idx = 0;
3537bded2dbSJung-uk Kim else if (op == SSL_CERT_SET_NEXT) {
3547bded2dbSJung-uk Kim idx = (int)(c->key - c->pkeys + 1);
3557bded2dbSJung-uk Kim if (idx >= SSL_PKEY_NUM)
3567bded2dbSJung-uk Kim return 0;
3577bded2dbSJung-uk Kim } else
3587bded2dbSJung-uk Kim return 0;
3597bded2dbSJung-uk Kim for (i = idx; i < SSL_PKEY_NUM; i++) {
3607bded2dbSJung-uk Kim CERT_PKEY *cpk = c->pkeys + i;
3617bded2dbSJung-uk Kim if (cpk->x509 && cpk->privatekey) {
3627bded2dbSJung-uk Kim c->key = cpk;
3637bded2dbSJung-uk Kim return 1;
3647bded2dbSJung-uk Kim }
3657bded2dbSJung-uk Kim }
3667bded2dbSJung-uk Kim return 0;
3677bded2dbSJung-uk Kim }
3687bded2dbSJung-uk Kim
ssl_cert_set_cert_cb(CERT * c,int (* cb)(SSL * ssl,void * arg),void * arg)3697bded2dbSJung-uk Kim void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
3707bded2dbSJung-uk Kim {
3717bded2dbSJung-uk Kim c->cert_cb = cb;
3727bded2dbSJung-uk Kim c->cert_cb_arg = arg;
3737bded2dbSJung-uk Kim }
3747bded2dbSJung-uk Kim
375*b077aed3SPierre Pronchery /*
376*b077aed3SPierre Pronchery * Verify a certificate chain
377*b077aed3SPierre Pronchery * Return codes:
378*b077aed3SPierre Pronchery * 1: Verify success
379*b077aed3SPierre Pronchery * 0: Verify failure or error
380*b077aed3SPierre Pronchery * -1: Retry required
381*b077aed3SPierre Pronchery */
ssl_verify_cert_chain(SSL * s,STACK_OF (X509)* sk)38274664626SKris Kennaway int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
38374664626SKris Kennaway {
38474664626SKris Kennaway X509 *x;
385e71b7053SJung-uk Kim int i = 0;
3867bded2dbSJung-uk Kim X509_STORE *verify_store;
387e71b7053SJung-uk Kim X509_STORE_CTX *ctx = NULL;
388e71b7053SJung-uk Kim X509_VERIFY_PARAM *param;
389e71b7053SJung-uk Kim
390e71b7053SJung-uk Kim if ((sk == NULL) || (sk_X509_num(sk) == 0))
391e71b7053SJung-uk Kim return 0;
39274664626SKris Kennaway
3937bded2dbSJung-uk Kim if (s->cert->verify_store)
3947bded2dbSJung-uk Kim verify_store = s->cert->verify_store;
3957bded2dbSJung-uk Kim else
3967bded2dbSJung-uk Kim verify_store = s->ctx->cert_store;
3977bded2dbSJung-uk Kim
398*b077aed3SPierre Pronchery ctx = X509_STORE_CTX_new_ex(s->ctx->libctx, s->ctx->propq);
399e71b7053SJung-uk Kim if (ctx == NULL) {
400*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
401e71b7053SJung-uk Kim return 0;
402e71b7053SJung-uk Kim }
40374664626SKris Kennaway
40474664626SKris Kennaway x = sk_X509_value(sk, 0);
405e71b7053SJung-uk Kim if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
406*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
407e71b7053SJung-uk Kim goto end;
4085c87c606SMark Murray }
409e71b7053SJung-uk Kim param = X509_STORE_CTX_get0_param(ctx);
410e71b7053SJung-uk Kim /*
411e71b7053SJung-uk Kim * XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
412e71b7053SJung-uk Kim * point, for now a single @SECLEVEL sets the same policy for TLS crypto
413e71b7053SJung-uk Kim * and PKI authentication.
414e71b7053SJung-uk Kim */
415e71b7053SJung-uk Kim X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
416e71b7053SJung-uk Kim
4177bded2dbSJung-uk Kim /* Set suite B flags if needed */
418e71b7053SJung-uk Kim X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s));
419e71b7053SJung-uk Kim if (!X509_STORE_CTX_set_ex_data
420e71b7053SJung-uk Kim (ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s)) {
421e71b7053SJung-uk Kim goto end;
422e71b7053SJung-uk Kim }
423e71b7053SJung-uk Kim
424e71b7053SJung-uk Kim /* Verify via DANE if enabled */
425e71b7053SJung-uk Kim if (DANETLS_ENABLED(&s->dane))
426e71b7053SJung-uk Kim X509_STORE_CTX_set0_dane(ctx, &s->dane);
4275c87c606SMark Murray
4286f9291ceSJung-uk Kim /*
4296f9291ceSJung-uk Kim * We need to inherit the verify parameters. These can be determined by
4306f9291ceSJung-uk Kim * the context: if its a server it will verify SSL client certificates or
4316f9291ceSJung-uk Kim * vice versa.
432f579bf8eSKris Kennaway */
433f579bf8eSKris Kennaway
434e71b7053SJung-uk Kim X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
4356f9291ceSJung-uk Kim /*
436e71b7053SJung-uk Kim * Anything non-default in "s->param" should overwrite anything in the ctx.
4376a599222SSimon L. B. Nielsen */
438e71b7053SJung-uk Kim X509_VERIFY_PARAM_set1(param, s->param);
43974664626SKris Kennaway
440a21b1b38SKris Kennaway if (s->verify_callback)
441e71b7053SJung-uk Kim X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
442a21b1b38SKris Kennaway
443*b077aed3SPierre Pronchery if (s->ctx->app_verify_callback != NULL) {
444e71b7053SJung-uk Kim i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
445*b077aed3SPierre Pronchery } else {
446e71b7053SJung-uk Kim i = X509_verify_cert(ctx);
447*b077aed3SPierre Pronchery /* We treat an error in the same way as a failure to verify */
448*b077aed3SPierre Pronchery if (i < 0)
449*b077aed3SPierre Pronchery i = 0;
450*b077aed3SPierre Pronchery }
451e71b7053SJung-uk Kim
452e71b7053SJung-uk Kim s->verify_result = X509_STORE_CTX_get_error(ctx);
453e71b7053SJung-uk Kim sk_X509_pop_free(s->verified_chain, X509_free);
454e71b7053SJung-uk Kim s->verified_chain = NULL;
455e71b7053SJung-uk Kim if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
456e71b7053SJung-uk Kim s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
457e71b7053SJung-uk Kim if (s->verified_chain == NULL) {
458*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
45974664626SKris Kennaway i = 0;
460e71b7053SJung-uk Kim }
46174664626SKris Kennaway }
46274664626SKris Kennaway
463e71b7053SJung-uk Kim /* Move peername from the store context params to the SSL handle's */
464e71b7053SJung-uk Kim X509_VERIFY_PARAM_move_peername(s->param, param);
46574664626SKris Kennaway
466e71b7053SJung-uk Kim end:
467e71b7053SJung-uk Kim X509_STORE_CTX_free(ctx);
468e71b7053SJung-uk Kim return i;
46974664626SKris Kennaway }
47074664626SKris Kennaway
set0_CA_list(STACK_OF (X509_NAME)** ca_list,STACK_OF (X509_NAME)* name_list)471e71b7053SJung-uk Kim static void set0_CA_list(STACK_OF(X509_NAME) **ca_list,
4726f9291ceSJung-uk Kim STACK_OF(X509_NAME) *name_list)
47374664626SKris Kennaway {
47474664626SKris Kennaway sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
475ced566fdSJacques Vidrine *ca_list = name_list;
47674664626SKris Kennaway }
47774664626SKris Kennaway
STACK_OF(X509_NAME)478e71b7053SJung-uk Kim STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk)
47974664626SKris Kennaway {
48074664626SKris Kennaway int i;
481e71b7053SJung-uk Kim const int num = sk_X509_NAME_num(sk);
48274664626SKris Kennaway STACK_OF(X509_NAME) *ret;
48374664626SKris Kennaway X509_NAME *name;
48474664626SKris Kennaway
485e71b7053SJung-uk Kim ret = sk_X509_NAME_new_reserve(NULL, num);
486e71b7053SJung-uk Kim if (ret == NULL) {
487*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
488e71b7053SJung-uk Kim return NULL;
489e71b7053SJung-uk Kim }
490e71b7053SJung-uk Kim for (i = 0; i < num; i++) {
49174664626SKris Kennaway name = X509_NAME_dup(sk_X509_NAME_value(sk, i));
492e71b7053SJung-uk Kim if (name == NULL) {
493*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
49474664626SKris Kennaway sk_X509_NAME_pop_free(ret, X509_NAME_free);
495e71b7053SJung-uk Kim return NULL;
49674664626SKris Kennaway }
497e71b7053SJung-uk Kim sk_X509_NAME_push(ret, name); /* Cannot fail after reserve call */
49874664626SKris Kennaway }
499e71b7053SJung-uk Kim return ret;
50074664626SKris Kennaway }
50174664626SKris Kennaway
SSL_set0_CA_list(SSL * s,STACK_OF (X509_NAME)* name_list)502e71b7053SJung-uk Kim void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
50374664626SKris Kennaway {
504e71b7053SJung-uk Kim set0_CA_list(&s->ca_names, name_list);
505e71b7053SJung-uk Kim }
506e71b7053SJung-uk Kim
SSL_CTX_set0_CA_list(SSL_CTX * ctx,STACK_OF (X509_NAME)* name_list)507e71b7053SJung-uk Kim void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
508e71b7053SJung-uk Kim {
509e71b7053SJung-uk Kim set0_CA_list(&ctx->ca_names, name_list);
510e71b7053SJung-uk Kim }
511e71b7053SJung-uk Kim
STACK_OF(X509_NAME)512e71b7053SJung-uk Kim const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx)
513e71b7053SJung-uk Kim {
514e71b7053SJung-uk Kim return ctx->ca_names;
515e71b7053SJung-uk Kim }
516e71b7053SJung-uk Kim
STACK_OF(X509_NAME)517e71b7053SJung-uk Kim const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s)
518e71b7053SJung-uk Kim {
519e71b7053SJung-uk Kim return s->ca_names != NULL ? s->ca_names : s->ctx->ca_names;
52074664626SKris Kennaway }
52174664626SKris Kennaway
SSL_CTX_set_client_CA_list(SSL_CTX * ctx,STACK_OF (X509_NAME)* name_list)522ced566fdSJacques Vidrine void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list)
52374664626SKris Kennaway {
524c9cf7b5cSJung-uk Kim set0_CA_list(&ctx->client_ca_names, name_list);
52574664626SKris Kennaway }
52674664626SKris Kennaway
STACK_OF(X509_NAME)5273b4e3dcbSSimon L. B. Nielsen STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx)
52874664626SKris Kennaway {
529c9cf7b5cSJung-uk Kim return ctx->client_ca_names;
530e71b7053SJung-uk Kim }
531e71b7053SJung-uk Kim
SSL_set_client_CA_list(SSL * s,STACK_OF (X509_NAME)* name_list)532e71b7053SJung-uk Kim void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list)
533e71b7053SJung-uk Kim {
534c9cf7b5cSJung-uk Kim set0_CA_list(&s->client_ca_names, name_list);
535e71b7053SJung-uk Kim }
536e71b7053SJung-uk Kim
STACK_OF(X509_NAME)537e71b7053SJung-uk Kim const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s)
538e71b7053SJung-uk Kim {
539*b077aed3SPierre Pronchery return s->s3.tmp.peer_ca_names;
54074664626SKris Kennaway }
54174664626SKris Kennaway
STACK_OF(X509_NAME)5423b4e3dcbSSimon L. B. Nielsen STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
54374664626SKris Kennaway {
544e71b7053SJung-uk Kim if (!s->server)
545*b077aed3SPierre Pronchery return s->s3.tmp.peer_ca_names;
546c9cf7b5cSJung-uk Kim return s->client_ca_names != NULL ? s->client_ca_names
547c9cf7b5cSJung-uk Kim : s->ctx->client_ca_names;
54874664626SKris Kennaway }
54974664626SKris Kennaway
add_ca_name(STACK_OF (X509_NAME)** sk,const X509 * x)550e71b7053SJung-uk Kim static int add_ca_name(STACK_OF(X509_NAME) **sk, const X509 *x)
55174664626SKris Kennaway {
55274664626SKris Kennaway X509_NAME *name;
55374664626SKris Kennaway
5546f9291ceSJung-uk Kim if (x == NULL)
555e71b7053SJung-uk Kim return 0;
556e71b7053SJung-uk Kim if (*sk == NULL && ((*sk = sk_X509_NAME_new_null()) == NULL))
557e71b7053SJung-uk Kim return 0;
55874664626SKris Kennaway
55974664626SKris Kennaway if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL)
560e71b7053SJung-uk Kim return 0;
56174664626SKris Kennaway
5626f9291ceSJung-uk Kim if (!sk_X509_NAME_push(*sk, name)) {
56374664626SKris Kennaway X509_NAME_free(name);
564e71b7053SJung-uk Kim return 0;
56574664626SKris Kennaway }
566e71b7053SJung-uk Kim return 1;
56774664626SKris Kennaway }
56874664626SKris Kennaway
SSL_add1_to_CA_list(SSL * ssl,const X509 * x)569e71b7053SJung-uk Kim int SSL_add1_to_CA_list(SSL *ssl, const X509 *x)
570e71b7053SJung-uk Kim {
571e71b7053SJung-uk Kim return add_ca_name(&ssl->ca_names, x);
572e71b7053SJung-uk Kim }
573e71b7053SJung-uk Kim
SSL_CTX_add1_to_CA_list(SSL_CTX * ctx,const X509 * x)574e71b7053SJung-uk Kim int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x)
575e71b7053SJung-uk Kim {
576e71b7053SJung-uk Kim return add_ca_name(&ctx->ca_names, x);
577e71b7053SJung-uk Kim }
578e71b7053SJung-uk Kim
579e71b7053SJung-uk Kim /*
580e71b7053SJung-uk Kim * The following two are older names are to be replaced with
581e71b7053SJung-uk Kim * SSL(_CTX)_add1_to_CA_list
582e71b7053SJung-uk Kim */
SSL_add_client_CA(SSL * ssl,X509 * x)58374664626SKris Kennaway int SSL_add_client_CA(SSL *ssl, X509 *x)
58474664626SKris Kennaway {
585c9cf7b5cSJung-uk Kim return add_ca_name(&ssl->client_ca_names, x);
58674664626SKris Kennaway }
58774664626SKris Kennaway
SSL_CTX_add_client_CA(SSL_CTX * ctx,X509 * x)58874664626SKris Kennaway int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x)
58974664626SKris Kennaway {
590c9cf7b5cSJung-uk Kim return add_ca_name(&ctx->client_ca_names, x);
59174664626SKris Kennaway }
59274664626SKris Kennaway
xname_cmp(const X509_NAME * a,const X509_NAME * b)593e71b7053SJung-uk Kim static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
59474664626SKris Kennaway {
595e71b7053SJung-uk Kim unsigned char *abuf = NULL, *bbuf = NULL;
596e71b7053SJung-uk Kim int alen, blen, ret;
597e71b7053SJung-uk Kim
598e71b7053SJung-uk Kim /* X509_NAME_cmp() itself casts away constness in this way, so
599e71b7053SJung-uk Kim * assume it's safe:
600e71b7053SJung-uk Kim */
601e71b7053SJung-uk Kim alen = i2d_X509_NAME((X509_NAME *)a, &abuf);
602e71b7053SJung-uk Kim blen = i2d_X509_NAME((X509_NAME *)b, &bbuf);
603e71b7053SJung-uk Kim
604e71b7053SJung-uk Kim if (alen < 0 || blen < 0)
605e71b7053SJung-uk Kim ret = -2;
606e71b7053SJung-uk Kim else if (alen != blen)
607e71b7053SJung-uk Kim ret = alen - blen;
608e71b7053SJung-uk Kim else /* alen == blen */
609e71b7053SJung-uk Kim ret = memcmp(abuf, bbuf, alen);
610e71b7053SJung-uk Kim
611e71b7053SJung-uk Kim OPENSSL_free(abuf);
612e71b7053SJung-uk Kim OPENSSL_free(bbuf);
613e71b7053SJung-uk Kim
614e71b7053SJung-uk Kim return ret;
61574664626SKris Kennaway }
61674664626SKris Kennaway
xname_sk_cmp(const X509_NAME * const * a,const X509_NAME * const * b)617e71b7053SJung-uk Kim static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
618e71b7053SJung-uk Kim {
619e71b7053SJung-uk Kim return xname_cmp(*a, *b);
620e71b7053SJung-uk Kim }
621e71b7053SJung-uk Kim
xname_hash(const X509_NAME * a)622e71b7053SJung-uk Kim static unsigned long xname_hash(const X509_NAME *a)
623e71b7053SJung-uk Kim {
624*b077aed3SPierre Pronchery /* This returns 0 also if SHA1 is not available */
625*b077aed3SPierre Pronchery return X509_NAME_hash_ex((X509_NAME *)a, NULL, NULL, NULL);
626e71b7053SJung-uk Kim }
627e71b7053SJung-uk Kim
STACK_OF(X509_NAME)628*b077aed3SPierre Pronchery STACK_OF(X509_NAME) *SSL_load_client_CA_file_ex(const char *file,
629*b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx,
630*b077aed3SPierre Pronchery const char *propq)
63174664626SKris Kennaway {
632e71b7053SJung-uk Kim BIO *in = BIO_new(BIO_s_file());
63374664626SKris Kennaway X509 *x = NULL;
63474664626SKris Kennaway X509_NAME *xn = NULL;
635e71b7053SJung-uk Kim STACK_OF(X509_NAME) *ret = NULL;
636e71b7053SJung-uk Kim LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
637*b077aed3SPierre Pronchery OSSL_LIB_CTX *prev_libctx = NULL;
63874664626SKris Kennaway
639e71b7053SJung-uk Kim if ((name_hash == NULL) || (in == NULL)) {
640*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
64174664626SKris Kennaway goto err;
64274664626SKris Kennaway }
64374664626SKris Kennaway
644*b077aed3SPierre Pronchery x = X509_new_ex(libctx, propq);
645*b077aed3SPierre Pronchery if (x == NULL) {
646*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
647*b077aed3SPierre Pronchery goto err;
648*b077aed3SPierre Pronchery }
649*b077aed3SPierre Pronchery if (BIO_read_filename(in, file) <= 0)
65074664626SKris Kennaway goto err;
65174664626SKris Kennaway
652*b077aed3SPierre Pronchery /* Internally lh_X509_NAME_retrieve() needs the libctx to retrieve SHA1 */
653*b077aed3SPierre Pronchery prev_libctx = OSSL_LIB_CTX_set0_default(libctx);
6546f9291ceSJung-uk Kim for (;;) {
65574664626SKris Kennaway if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
65674664626SKris Kennaway break;
6576f9291ceSJung-uk Kim if (ret == NULL) {
6583b4e3dcbSSimon L. B. Nielsen ret = sk_X509_NAME_new_null();
6596f9291ceSJung-uk Kim if (ret == NULL) {
660*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
6613b4e3dcbSSimon L. B. Nielsen goto err;
6623b4e3dcbSSimon L. B. Nielsen }
6633b4e3dcbSSimon L. B. Nielsen }
6646f9291ceSJung-uk Kim if ((xn = X509_get_subject_name(x)) == NULL)
6656f9291ceSJung-uk Kim goto err;
66674664626SKris Kennaway /* check for duplicates */
66774664626SKris Kennaway xn = X509_NAME_dup(xn);
6686f9291ceSJung-uk Kim if (xn == NULL)
6696f9291ceSJung-uk Kim goto err;
670e71b7053SJung-uk Kim if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) {
671e71b7053SJung-uk Kim /* Duplicate. */
67274664626SKris Kennaway X509_NAME_free(xn);
673e71b7053SJung-uk Kim xn = NULL;
674e71b7053SJung-uk Kim } else {
675e71b7053SJung-uk Kim lh_X509_NAME_insert(name_hash, xn);
676e71b7053SJung-uk Kim if (!sk_X509_NAME_push(ret, xn))
677e71b7053SJung-uk Kim goto err;
67874664626SKris Kennaway }
67974664626SKris Kennaway }
680e71b7053SJung-uk Kim goto done;
68174664626SKris Kennaway
68274664626SKris Kennaway err:
683e71b7053SJung-uk Kim X509_NAME_free(xn);
6846f9291ceSJung-uk Kim sk_X509_NAME_pop_free(ret, X509_NAME_free);
68574664626SKris Kennaway ret = NULL;
686e71b7053SJung-uk Kim done:
687*b077aed3SPierre Pronchery /* restore the old libctx */
688*b077aed3SPierre Pronchery OSSL_LIB_CTX_set0_default(prev_libctx);
6896f9291ceSJung-uk Kim BIO_free(in);
6906f9291ceSJung-uk Kim X509_free(x);
691e71b7053SJung-uk Kim lh_X509_NAME_free(name_hash);
6923b4e3dcbSSimon L. B. Nielsen if (ret != NULL)
6933b4e3dcbSSimon L. B. Nielsen ERR_clear_error();
694e71b7053SJung-uk Kim return ret;
69574664626SKris Kennaway }
69674664626SKris Kennaway
STACK_OF(X509_NAME)697*b077aed3SPierre Pronchery STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
698*b077aed3SPierre Pronchery {
699*b077aed3SPierre Pronchery return SSL_load_client_CA_file_ex(file, NULL, NULL);
700*b077aed3SPierre Pronchery }
701*b077aed3SPierre Pronchery
SSL_add_file_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * file)70274664626SKris Kennaway int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
70374664626SKris Kennaway const char *file)
70474664626SKris Kennaway {
70574664626SKris Kennaway BIO *in;
70674664626SKris Kennaway X509 *x = NULL;
70774664626SKris Kennaway X509_NAME *xn = NULL;
70874664626SKris Kennaway int ret = 1;
709ddd58736SKris Kennaway int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
71074664626SKris Kennaway
711e71b7053SJung-uk Kim oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
71274664626SKris Kennaway
713e71b7053SJung-uk Kim in = BIO_new(BIO_s_file());
71474664626SKris Kennaway
7156f9291ceSJung-uk Kim if (in == NULL) {
716*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
71774664626SKris Kennaway goto err;
71874664626SKris Kennaway }
71974664626SKris Kennaway
720*b077aed3SPierre Pronchery if (BIO_read_filename(in, file) <= 0)
72174664626SKris Kennaway goto err;
72274664626SKris Kennaway
7236f9291ceSJung-uk Kim for (;;) {
72474664626SKris Kennaway if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
72574664626SKris Kennaway break;
7266f9291ceSJung-uk Kim if ((xn = X509_get_subject_name(x)) == NULL)
7276f9291ceSJung-uk Kim goto err;
72874664626SKris Kennaway xn = X509_NAME_dup(xn);
7296f9291ceSJung-uk Kim if (xn == NULL)
7306f9291ceSJung-uk Kim goto err;
731e71b7053SJung-uk Kim if (sk_X509_NAME_find(stack, xn) >= 0) {
732e71b7053SJung-uk Kim /* Duplicate. */
73374664626SKris Kennaway X509_NAME_free(xn);
734e71b7053SJung-uk Kim } else if (!sk_X509_NAME_push(stack, xn)) {
735e71b7053SJung-uk Kim X509_NAME_free(xn);
736e71b7053SJung-uk Kim goto err;
737e71b7053SJung-uk Kim }
73874664626SKris Kennaway }
73974664626SKris Kennaway
740a3ddd25aSSimon L. B. Nielsen ERR_clear_error();
741e71b7053SJung-uk Kim goto done;
742a3ddd25aSSimon L. B. Nielsen
74374664626SKris Kennaway err:
74474664626SKris Kennaway ret = 0;
745e71b7053SJung-uk Kim done:
74674664626SKris Kennaway BIO_free(in);
74774664626SKris Kennaway X509_free(x);
748db522d3aSSimon L. B. Nielsen (void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
74974664626SKris Kennaway return ret;
75074664626SKris Kennaway }
75174664626SKris Kennaway
SSL_add_dir_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * dir)75274664626SKris Kennaway int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
75374664626SKris Kennaway const char *dir)
75474664626SKris Kennaway {
7553b4e3dcbSSimon L. B. Nielsen OPENSSL_DIR_CTX *d = NULL;
7563b4e3dcbSSimon L. B. Nielsen const char *filename;
75774664626SKris Kennaway int ret = 0;
75874664626SKris Kennaway
75974664626SKris Kennaway /* Note that a side effect is that the CAs will be sorted by name */
76074664626SKris Kennaway
7616f9291ceSJung-uk Kim while ((filename = OPENSSL_DIR_read(&d, dir))) {
76274664626SKris Kennaway char buf[1024];
763ddd58736SKris Kennaway int r;
764*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO
765*b077aed3SPierre Pronchery struct stat st;
76674664626SKris Kennaway
767*b077aed3SPierre Pronchery #else
768*b077aed3SPierre Pronchery /* Cannot use stat so just skip current and parent directories */
769*b077aed3SPierre Pronchery if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
770*b077aed3SPierre Pronchery continue;
771*b077aed3SPierre Pronchery #endif
772dee36b4fSJung-uk Kim if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
773*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, SSL_R_PATH_TOO_LONG);
77474664626SKris Kennaway goto err;
77574664626SKris Kennaway }
7763b4e3dcbSSimon L. B. Nielsen #ifdef OPENSSL_SYS_VMS
777dee36b4fSJung-uk Kim r = BIO_snprintf(buf, sizeof(buf), "%s%s", dir, filename);
7783b4e3dcbSSimon L. B. Nielsen #else
779dee36b4fSJung-uk Kim r = BIO_snprintf(buf, sizeof(buf), "%s/%s", dir, filename);
7803b4e3dcbSSimon L. B. Nielsen #endif
781*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_POSIX_IO
782*b077aed3SPierre Pronchery /* Skip subdirectories */
783*b077aed3SPierre Pronchery if (!stat(buf, &st) && S_ISDIR(st.st_mode))
784*b077aed3SPierre Pronchery continue;
785*b077aed3SPierre Pronchery #endif
7863b4e3dcbSSimon L. B. Nielsen if (r <= 0 || r >= (int)sizeof(buf))
787ddd58736SKris Kennaway goto err;
78874664626SKris Kennaway if (!SSL_add_file_cert_subjects_to_stack(stack, buf))
78974664626SKris Kennaway goto err;
79074664626SKris Kennaway }
79174664626SKris Kennaway
7926f9291ceSJung-uk Kim if (errno) {
793*b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(),
794*b077aed3SPierre Pronchery "calling OPENSSL_dir_read(%s)", dir);
795*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_SYS_LIB);
7965c87c606SMark Murray goto err;
7975c87c606SMark Murray }
7985c87c606SMark Murray
7995c87c606SMark Murray ret = 1;
8005c87c606SMark Murray
8015c87c606SMark Murray err:
8026f9291ceSJung-uk Kim if (d)
8036f9291ceSJung-uk Kim OPENSSL_DIR_end(&d);
804e71b7053SJung-uk Kim
8055c87c606SMark Murray return ret;
8065c87c606SMark Murray }
8077bded2dbSJung-uk Kim
add_uris_recursive(STACK_OF (X509_NAME)* stack,const char * uri,int depth)808*b077aed3SPierre Pronchery static int add_uris_recursive(STACK_OF(X509_NAME) *stack,
809*b077aed3SPierre Pronchery const char *uri, int depth)
810*b077aed3SPierre Pronchery {
811*b077aed3SPierre Pronchery int ok = 1;
812*b077aed3SPierre Pronchery OSSL_STORE_CTX *ctx = NULL;
813*b077aed3SPierre Pronchery X509 *x = NULL;
814*b077aed3SPierre Pronchery X509_NAME *xn = NULL;
815*b077aed3SPierre Pronchery
816*b077aed3SPierre Pronchery if ((ctx = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL)) == NULL)
817*b077aed3SPierre Pronchery goto err;
818*b077aed3SPierre Pronchery
819*b077aed3SPierre Pronchery while (!OSSL_STORE_eof(ctx) && !OSSL_STORE_error(ctx)) {
820*b077aed3SPierre Pronchery OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
821*b077aed3SPierre Pronchery int infotype = info == 0 ? 0 : OSSL_STORE_INFO_get_type(info);
822*b077aed3SPierre Pronchery
823*b077aed3SPierre Pronchery if (info == NULL)
824*b077aed3SPierre Pronchery continue;
825*b077aed3SPierre Pronchery
826*b077aed3SPierre Pronchery if (infotype == OSSL_STORE_INFO_NAME) {
827*b077aed3SPierre Pronchery /*
828*b077aed3SPierre Pronchery * This is an entry in the "directory" represented by the current
829*b077aed3SPierre Pronchery * uri. if |depth| allows, dive into it.
830*b077aed3SPierre Pronchery */
831*b077aed3SPierre Pronchery if (depth > 0)
832*b077aed3SPierre Pronchery ok = add_uris_recursive(stack, OSSL_STORE_INFO_get0_NAME(info),
833*b077aed3SPierre Pronchery depth - 1);
834*b077aed3SPierre Pronchery } else if (infotype == OSSL_STORE_INFO_CERT) {
835*b077aed3SPierre Pronchery if ((x = OSSL_STORE_INFO_get0_CERT(info)) == NULL
836*b077aed3SPierre Pronchery || (xn = X509_get_subject_name(x)) == NULL
837*b077aed3SPierre Pronchery || (xn = X509_NAME_dup(xn)) == NULL)
838*b077aed3SPierre Pronchery goto err;
839*b077aed3SPierre Pronchery if (sk_X509_NAME_find(stack, xn) >= 0) {
840*b077aed3SPierre Pronchery /* Duplicate. */
841*b077aed3SPierre Pronchery X509_NAME_free(xn);
842*b077aed3SPierre Pronchery } else if (!sk_X509_NAME_push(stack, xn)) {
843*b077aed3SPierre Pronchery X509_NAME_free(xn);
844*b077aed3SPierre Pronchery goto err;
845*b077aed3SPierre Pronchery }
846*b077aed3SPierre Pronchery }
847*b077aed3SPierre Pronchery
848*b077aed3SPierre Pronchery OSSL_STORE_INFO_free(info);
849*b077aed3SPierre Pronchery }
850*b077aed3SPierre Pronchery
851*b077aed3SPierre Pronchery ERR_clear_error();
852*b077aed3SPierre Pronchery goto done;
853*b077aed3SPierre Pronchery
854*b077aed3SPierre Pronchery err:
855*b077aed3SPierre Pronchery ok = 0;
856*b077aed3SPierre Pronchery done:
857*b077aed3SPierre Pronchery OSSL_STORE_close(ctx);
858*b077aed3SPierre Pronchery
859*b077aed3SPierre Pronchery return ok;
860*b077aed3SPierre Pronchery }
861*b077aed3SPierre Pronchery
SSL_add_store_cert_subjects_to_stack(STACK_OF (X509_NAME)* stack,const char * store)862*b077aed3SPierre Pronchery int SSL_add_store_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
863*b077aed3SPierre Pronchery const char *store)
864*b077aed3SPierre Pronchery {
865*b077aed3SPierre Pronchery int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b)
866*b077aed3SPierre Pronchery = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
867*b077aed3SPierre Pronchery int ret = add_uris_recursive(stack, store, 1);
868*b077aed3SPierre Pronchery
869*b077aed3SPierre Pronchery (void)sk_X509_NAME_set_cmp_func(stack, oldcmp);
870*b077aed3SPierre Pronchery return ret;
871*b077aed3SPierre Pronchery }
872*b077aed3SPierre Pronchery
8737bded2dbSJung-uk Kim /* Build a certificate chain for current certificate */
ssl_build_cert_chain(SSL * s,SSL_CTX * ctx,int flags)874e71b7053SJung-uk Kim int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
8757bded2dbSJung-uk Kim {
876e71b7053SJung-uk Kim CERT *c = s ? s->cert : ctx->cert;
8777bded2dbSJung-uk Kim CERT_PKEY *cpk = c->key;
878e71b7053SJung-uk Kim X509_STORE *chain_store = NULL;
879e71b7053SJung-uk Kim X509_STORE_CTX *xs_ctx = NULL;
8807bded2dbSJung-uk Kim STACK_OF(X509) *chain = NULL, *untrusted = NULL;
8817bded2dbSJung-uk Kim X509 *x;
882*b077aed3SPierre Pronchery SSL_CTX *real_ctx = (s == NULL) ? ctx : s->ctx;
8837bded2dbSJung-uk Kim int i, rv = 0;
8847bded2dbSJung-uk Kim
8857bded2dbSJung-uk Kim if (!cpk->x509) {
886*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, SSL_R_NO_CERTIFICATE_SET);
8877bded2dbSJung-uk Kim goto err;
8887bded2dbSJung-uk Kim }
8897bded2dbSJung-uk Kim /* Rearranging and check the chain: add everything to a store */
8907bded2dbSJung-uk Kim if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
8917bded2dbSJung-uk Kim chain_store = X509_STORE_new();
892e71b7053SJung-uk Kim if (chain_store == NULL)
8937bded2dbSJung-uk Kim goto err;
8947bded2dbSJung-uk Kim for (i = 0; i < sk_X509_num(cpk->chain); i++) {
8957bded2dbSJung-uk Kim x = sk_X509_value(cpk->chain, i);
896e71b7053SJung-uk Kim if (!X509_STORE_add_cert(chain_store, x))
8977bded2dbSJung-uk Kim goto err;
8987bded2dbSJung-uk Kim }
8997bded2dbSJung-uk Kim /* Add EE cert too: it might be self signed */
900e71b7053SJung-uk Kim if (!X509_STORE_add_cert(chain_store, cpk->x509))
9017bded2dbSJung-uk Kim goto err;
9027bded2dbSJung-uk Kim } else {
9037bded2dbSJung-uk Kim if (c->chain_store)
9047bded2dbSJung-uk Kim chain_store = c->chain_store;
905e71b7053SJung-uk Kim else if (s)
906e71b7053SJung-uk Kim chain_store = s->ctx->cert_store;
907e71b7053SJung-uk Kim else
908e71b7053SJung-uk Kim chain_store = ctx->cert_store;
9097bded2dbSJung-uk Kim
9107bded2dbSJung-uk Kim if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED)
9117bded2dbSJung-uk Kim untrusted = cpk->chain;
9127bded2dbSJung-uk Kim }
9137bded2dbSJung-uk Kim
914*b077aed3SPierre Pronchery xs_ctx = X509_STORE_CTX_new_ex(real_ctx->libctx, real_ctx->propq);
915e71b7053SJung-uk Kim if (xs_ctx == NULL) {
916*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
917e71b7053SJung-uk Kim goto err;
918e71b7053SJung-uk Kim }
919e71b7053SJung-uk Kim if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
920*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, ERR_R_X509_LIB);
9217bded2dbSJung-uk Kim goto err;
9227bded2dbSJung-uk Kim }
9237bded2dbSJung-uk Kim /* Set suite B flags if needed */
924e71b7053SJung-uk Kim X509_STORE_CTX_set_flags(xs_ctx,
9257bded2dbSJung-uk Kim c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
9267bded2dbSJung-uk Kim
927e71b7053SJung-uk Kim i = X509_verify_cert(xs_ctx);
9287bded2dbSJung-uk Kim if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
9297bded2dbSJung-uk Kim if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
9307bded2dbSJung-uk Kim ERR_clear_error();
9317bded2dbSJung-uk Kim i = 1;
9327bded2dbSJung-uk Kim rv = 2;
9337bded2dbSJung-uk Kim }
9347bded2dbSJung-uk Kim if (i > 0)
935e71b7053SJung-uk Kim chain = X509_STORE_CTX_get1_chain(xs_ctx);
9367bded2dbSJung-uk Kim if (i <= 0) {
937e71b7053SJung-uk Kim i = X509_STORE_CTX_get_error(xs_ctx);
938*b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_SSL, SSL_R_CERTIFICATE_VERIFY_FAILED,
939*b077aed3SPierre Pronchery "Verify error:%s", X509_verify_cert_error_string(i));
9407bded2dbSJung-uk Kim
9417bded2dbSJung-uk Kim goto err;
9427bded2dbSJung-uk Kim }
9437bded2dbSJung-uk Kim /* Remove EE certificate from chain */
9447bded2dbSJung-uk Kim x = sk_X509_shift(chain);
9457bded2dbSJung-uk Kim X509_free(x);
9467bded2dbSJung-uk Kim if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) {
9477bded2dbSJung-uk Kim if (sk_X509_num(chain) > 0) {
9487bded2dbSJung-uk Kim /* See if last cert is self signed */
9497bded2dbSJung-uk Kim x = sk_X509_value(chain, sk_X509_num(chain) - 1);
950e71b7053SJung-uk Kim if (X509_get_extension_flags(x) & EXFLAG_SS) {
9517bded2dbSJung-uk Kim x = sk_X509_pop(chain);
9527bded2dbSJung-uk Kim X509_free(x);
9537bded2dbSJung-uk Kim }
9547bded2dbSJung-uk Kim }
9557bded2dbSJung-uk Kim }
956e71b7053SJung-uk Kim /*
957e71b7053SJung-uk Kim * Check security level of all CA certificates: EE will have been checked
958e71b7053SJung-uk Kim * already.
959e71b7053SJung-uk Kim */
960e71b7053SJung-uk Kim for (i = 0; i < sk_X509_num(chain); i++) {
961e71b7053SJung-uk Kim x = sk_X509_value(chain, i);
962e71b7053SJung-uk Kim rv = ssl_security_cert(s, ctx, x, 0, 0);
963e71b7053SJung-uk Kim if (rv != 1) {
964*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_SSL, rv);
965e71b7053SJung-uk Kim sk_X509_pop_free(chain, X509_free);
966e71b7053SJung-uk Kim rv = 0;
967e71b7053SJung-uk Kim goto err;
968e71b7053SJung-uk Kim }
969e71b7053SJung-uk Kim }
970e71b7053SJung-uk Kim sk_X509_pop_free(cpk->chain, X509_free);
9717bded2dbSJung-uk Kim cpk->chain = chain;
9727bded2dbSJung-uk Kim if (rv == 0)
9737bded2dbSJung-uk Kim rv = 1;
9747bded2dbSJung-uk Kim err:
9757bded2dbSJung-uk Kim if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
9767bded2dbSJung-uk Kim X509_STORE_free(chain_store);
977e71b7053SJung-uk Kim X509_STORE_CTX_free(xs_ctx);
9787bded2dbSJung-uk Kim
9797bded2dbSJung-uk Kim return rv;
9807bded2dbSJung-uk Kim }
9817bded2dbSJung-uk Kim
ssl_cert_set_cert_store(CERT * c,X509_STORE * store,int chain,int ref)9827bded2dbSJung-uk Kim int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref)
9837bded2dbSJung-uk Kim {
9847bded2dbSJung-uk Kim X509_STORE **pstore;
9857bded2dbSJung-uk Kim if (chain)
9867bded2dbSJung-uk Kim pstore = &c->chain_store;
9877bded2dbSJung-uk Kim else
9887bded2dbSJung-uk Kim pstore = &c->verify_store;
9897bded2dbSJung-uk Kim X509_STORE_free(*pstore);
9907bded2dbSJung-uk Kim *pstore = store;
9917bded2dbSJung-uk Kim if (ref && store)
992e71b7053SJung-uk Kim X509_STORE_up_ref(store);
9937bded2dbSJung-uk Kim return 1;
9947bded2dbSJung-uk Kim }
995e71b7053SJung-uk Kim
ssl_cert_get_cert_store(CERT * c,X509_STORE ** pstore,int chain)99683eaf7aeSJung-uk Kim int ssl_cert_get_cert_store(CERT *c, X509_STORE **pstore, int chain)
99783eaf7aeSJung-uk Kim {
99883eaf7aeSJung-uk Kim *pstore = (chain ? c->chain_store : c->verify_store);
99983eaf7aeSJung-uk Kim return 1;
100083eaf7aeSJung-uk Kim }
100183eaf7aeSJung-uk Kim
ssl_get_security_level_bits(const SSL * s,const SSL_CTX * ctx,int * levelp)10029a3ae0cdSJung-uk Kim int ssl_get_security_level_bits(const SSL *s, const SSL_CTX *ctx, int *levelp)
10039a3ae0cdSJung-uk Kim {
10049a3ae0cdSJung-uk Kim int level;
1005*b077aed3SPierre Pronchery /*
1006*b077aed3SPierre Pronchery * note that there's a corresponding minbits_table
1007*b077aed3SPierre Pronchery * in crypto/x509/x509_vfy.c that's used for checking the security level
1008*b077aed3SPierre Pronchery * of RSA and DSA keys
1009*b077aed3SPierre Pronchery */
10109a3ae0cdSJung-uk Kim static const int minbits_table[5 + 1] = { 0, 80, 112, 128, 192, 256 };
10119a3ae0cdSJung-uk Kim
10129a3ae0cdSJung-uk Kim if (ctx != NULL)
10139a3ae0cdSJung-uk Kim level = SSL_CTX_get_security_level(ctx);
10149a3ae0cdSJung-uk Kim else
10159a3ae0cdSJung-uk Kim level = SSL_get_security_level(s);
10169a3ae0cdSJung-uk Kim
10179a3ae0cdSJung-uk Kim if (level > 5)
10189a3ae0cdSJung-uk Kim level = 5;
10199a3ae0cdSJung-uk Kim else if (level < 0)
10209a3ae0cdSJung-uk Kim level = 0;
10219a3ae0cdSJung-uk Kim
10229a3ae0cdSJung-uk Kim if (levelp != NULL)
10239a3ae0cdSJung-uk Kim *levelp = level;
10249a3ae0cdSJung-uk Kim
10259a3ae0cdSJung-uk Kim return minbits_table[level];
10269a3ae0cdSJung-uk Kim }
10279a3ae0cdSJung-uk Kim
ssl_security_default_callback(const SSL * s,const SSL_CTX * ctx,int op,int bits,int nid,void * other,void * ex)1028e71b7053SJung-uk Kim static int ssl_security_default_callback(const SSL *s, const SSL_CTX *ctx,
1029e71b7053SJung-uk Kim int op, int bits, int nid, void *other,
1030e71b7053SJung-uk Kim void *ex)
1031e71b7053SJung-uk Kim {
10325ac766abSJung-uk Kim int level, minbits, pfs_mask;
1033e71b7053SJung-uk Kim
10349a3ae0cdSJung-uk Kim minbits = ssl_get_security_level_bits(s, ctx, &level);
10359a3ae0cdSJung-uk Kim
10369a3ae0cdSJung-uk Kim if (level == 0) {
1037e71b7053SJung-uk Kim /*
1038e71b7053SJung-uk Kim * No EDH keys weaker than 1024-bits even at level 0, otherwise,
1039e71b7053SJung-uk Kim * anything goes.
1040e71b7053SJung-uk Kim */
1041e71b7053SJung-uk Kim if (op == SSL_SECOP_TMP_DH && bits < 80)
1042e71b7053SJung-uk Kim return 0;
1043e71b7053SJung-uk Kim return 1;
1044e71b7053SJung-uk Kim }
1045e71b7053SJung-uk Kim switch (op) {
1046e71b7053SJung-uk Kim case SSL_SECOP_CIPHER_SUPPORTED:
1047e71b7053SJung-uk Kim case SSL_SECOP_CIPHER_SHARED:
1048e71b7053SJung-uk Kim case SSL_SECOP_CIPHER_CHECK:
1049e71b7053SJung-uk Kim {
1050e71b7053SJung-uk Kim const SSL_CIPHER *c = other;
1051e71b7053SJung-uk Kim /* No ciphers below security level */
1052e71b7053SJung-uk Kim if (bits < minbits)
1053e71b7053SJung-uk Kim return 0;
1054e71b7053SJung-uk Kim /* No unauthenticated ciphersuites */
1055e71b7053SJung-uk Kim if (c->algorithm_auth & SSL_aNULL)
1056e71b7053SJung-uk Kim return 0;
1057e71b7053SJung-uk Kim /* No MD5 mac ciphersuites */
1058e71b7053SJung-uk Kim if (c->algorithm_mac & SSL_MD5)
1059e71b7053SJung-uk Kim return 0;
1060e71b7053SJung-uk Kim /* SHA1 HMAC is 160 bits of security */
1061e71b7053SJung-uk Kim if (minbits > 160 && c->algorithm_mac & SSL_SHA1)
1062e71b7053SJung-uk Kim return 0;
1063e71b7053SJung-uk Kim /* Level 2: no RC4 */
1064e71b7053SJung-uk Kim if (level >= 2 && c->algorithm_enc == SSL_RC4)
1065e71b7053SJung-uk Kim return 0;
1066e71b7053SJung-uk Kim /* Level 3: forward secure ciphersuites only */
10675ac766abSJung-uk Kim pfs_mask = SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK;
1068c9cf7b5cSJung-uk Kim if (level >= 3 && c->min_tls != TLS1_3_VERSION &&
10695ac766abSJung-uk Kim !(c->algorithm_mkey & pfs_mask))
1070e71b7053SJung-uk Kim return 0;
1071e71b7053SJung-uk Kim break;
1072e71b7053SJung-uk Kim }
1073e71b7053SJung-uk Kim case SSL_SECOP_VERSION:
1074e71b7053SJung-uk Kim if (!SSL_IS_DTLS(s)) {
1075e71b7053SJung-uk Kim /* SSLv3 not allowed at level 2 */
1076e71b7053SJung-uk Kim if (nid <= SSL3_VERSION && level >= 2)
1077e71b7053SJung-uk Kim return 0;
1078e71b7053SJung-uk Kim /* TLS v1.1 and above only for level 3 */
1079e71b7053SJung-uk Kim if (nid <= TLS1_VERSION && level >= 3)
1080e71b7053SJung-uk Kim return 0;
1081e71b7053SJung-uk Kim /* TLS v1.2 only for level 4 and above */
1082e71b7053SJung-uk Kim if (nid <= TLS1_1_VERSION && level >= 4)
1083e71b7053SJung-uk Kim return 0;
1084e71b7053SJung-uk Kim } else {
1085e71b7053SJung-uk Kim /* DTLS v1.2 only for level 4 and above */
1086e71b7053SJung-uk Kim if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
1087e71b7053SJung-uk Kim return 0;
1088e71b7053SJung-uk Kim }
1089e71b7053SJung-uk Kim break;
1090e71b7053SJung-uk Kim
1091e71b7053SJung-uk Kim case SSL_SECOP_COMPRESSION:
1092e71b7053SJung-uk Kim if (level >= 2)
1093e71b7053SJung-uk Kim return 0;
1094e71b7053SJung-uk Kim break;
1095e71b7053SJung-uk Kim case SSL_SECOP_TICKET:
1096e71b7053SJung-uk Kim if (level >= 3)
1097e71b7053SJung-uk Kim return 0;
1098e71b7053SJung-uk Kim break;
1099e71b7053SJung-uk Kim default:
1100e71b7053SJung-uk Kim if (bits < minbits)
1101e71b7053SJung-uk Kim return 0;
1102e71b7053SJung-uk Kim }
1103e71b7053SJung-uk Kim return 1;
1104e71b7053SJung-uk Kim }
1105e71b7053SJung-uk Kim
ssl_security(const SSL * s,int op,int bits,int nid,void * other)1106e71b7053SJung-uk Kim int ssl_security(const SSL *s, int op, int bits, int nid, void *other)
1107e71b7053SJung-uk Kim {
1108e71b7053SJung-uk Kim return s->cert->sec_cb(s, NULL, op, bits, nid, other, s->cert->sec_ex);
1109e71b7053SJung-uk Kim }
1110e71b7053SJung-uk Kim
ssl_ctx_security(const SSL_CTX * ctx,int op,int bits,int nid,void * other)1111e71b7053SJung-uk Kim int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
1112e71b7053SJung-uk Kim {
1113e71b7053SJung-uk Kim return ctx->cert->sec_cb(NULL, ctx, op, bits, nid, other,
1114e71b7053SJung-uk Kim ctx->cert->sec_ex);
1115e71b7053SJung-uk Kim }
1116e71b7053SJung-uk Kim
ssl_cert_lookup_by_nid(int nid,size_t * pidx)1117e71b7053SJung-uk Kim int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
1118e71b7053SJung-uk Kim {
1119e71b7053SJung-uk Kim size_t i;
1120e71b7053SJung-uk Kim
1121e71b7053SJung-uk Kim for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
1122e71b7053SJung-uk Kim if (ssl_cert_info[i].nid == nid) {
1123e71b7053SJung-uk Kim *pidx = i;
1124e71b7053SJung-uk Kim return 1;
1125e71b7053SJung-uk Kim }
1126e71b7053SJung-uk Kim }
1127e71b7053SJung-uk Kim
1128e71b7053SJung-uk Kim return 0;
1129e71b7053SJung-uk Kim }
1130e71b7053SJung-uk Kim
ssl_cert_lookup_by_pkey(const EVP_PKEY * pk,size_t * pidx)1131e71b7053SJung-uk Kim const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
1132e71b7053SJung-uk Kim {
1133*b077aed3SPierre Pronchery size_t i;
1134e71b7053SJung-uk Kim
1135*b077aed3SPierre Pronchery for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
1136*b077aed3SPierre Pronchery const SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i];
1137e71b7053SJung-uk Kim
1138*b077aed3SPierre Pronchery if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid))
1139*b077aed3SPierre Pronchery || EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) {
1140e71b7053SJung-uk Kim if (pidx != NULL)
1141*b077aed3SPierre Pronchery *pidx = i;
1142*b077aed3SPierre Pronchery return tmp_lu;
1143*b077aed3SPierre Pronchery }
1144*b077aed3SPierre Pronchery }
1145e71b7053SJung-uk Kim
1146*b077aed3SPierre Pronchery return NULL;
1147e71b7053SJung-uk Kim }
1148e71b7053SJung-uk Kim
ssl_cert_lookup_by_idx(size_t idx)1149e71b7053SJung-uk Kim const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
1150e71b7053SJung-uk Kim {
1151e71b7053SJung-uk Kim if (idx >= OSSL_NELEM(ssl_cert_info))
1152e71b7053SJung-uk Kim return NULL;
1153e71b7053SJung-uk Kim return &ssl_cert_info[idx];
1154e71b7053SJung-uk Kim }
1155