-/*
- * ! \file ssl/ssl_cert.c
- */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#endif
#include "internal/o_dir.h"
-#include <openssl/objects.h>
+#include <openssl/lhash.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
ret->references = 1;
ret->key = &ret->pkeys[cert->key - cert->pkeys];
-#ifndef OPENSSL_NO_RSA
- if (cert->rsa_tmp != NULL) {
- RSA_up_ref(cert->rsa_tmp);
- ret->rsa_tmp = cert->rsa_tmp;
- }
- ret->rsa_tmp_cb = cert->rsa_tmp_cb;
-#endif
-
#ifndef OPENSSL_NO_DH
if (cert->dh_tmp != NULL) {
- ret->dh_tmp = DHparams_dup(cert->dh_tmp);
- if (ret->dh_tmp == NULL) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB);
- goto err;
- }
- if (cert->dh_tmp->priv_key) {
- BIGNUM *b = BN_dup(cert->dh_tmp->priv_key);
- if (!b) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
- goto err;
- }
- ret->dh_tmp->priv_key = b;
- }
- if (cert->dh_tmp->pub_key) {
- BIGNUM *b = BN_dup(cert->dh_tmp->pub_key);
- if (!b) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB);
- goto err;
- }
- ret->dh_tmp->pub_key = b;
- }
+ ret->dh_tmp = cert->dh_tmp;
+ EVP_PKEY_up_ref(ret->dh_tmp);
}
ret->dh_tmp_cb = cert->dh_tmp_cb;
ret->dh_tmp_auto = cert->dh_tmp_auto;
#endif
-#ifndef OPENSSL_NO_EC
- if (cert->ecdh_tmp) {
- ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
- if (ret->ecdh_tmp == NULL) {
- SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB);
- goto err;
- }
- }
- ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
- ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
-#endif
-
for (i = 0; i < SSL_PKEY_NUM; i++) {
CERT_PKEY *cpk = cert->pkeys + i;
CERT_PKEY *rpk = ret->pkeys + i;
if (cpk->privatekey != NULL) {
rpk->privatekey = cpk->privatekey;
- CRYPTO_add(&cpk->privatekey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+ EVP_PKEY_up_ref(cpk->privatekey);
}
if (cpk->chain) {
/* Configured sigalgs copied across */
if (cert->conf_sigalgs) {
ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen);
- if (!ret->conf_sigalgs)
+ if (ret->conf_sigalgs == NULL)
goto err;
memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen);
ret->conf_sigalgslen = cert->conf_sigalgslen;
if (cert->client_sigalgs) {
ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen);
- if (!ret->client_sigalgs)
+ if (ret->client_sigalgs == NULL)
goto err;
memcpy(ret->client_sigalgs, cert->client_sigalgs,
cert->client_sigalgslen);
/* Copy any custom client certificate types */
if (cert->ctypes) {
ret->ctypes = OPENSSL_malloc(cert->ctype_num);
- if (!ret->ctypes)
+ if (ret->ctypes == NULL)
goto err;
memcpy(ret->ctypes, cert->ctypes, cert->ctype_num);
ret->ctype_num = cert->ctype_num;
ret->cert_cb_arg = cert->cert_cb_arg;
if (cert->verify_store) {
- CRYPTO_add(&cert->verify_store->references, 1,
- CRYPTO_LOCK_X509_STORE);
+ X509_STORE_up_ref(cert->verify_store);
ret->verify_store = cert->verify_store;
}
if (cert->chain_store) {
- CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE);
+ X509_STORE_up_ref(cert->chain_store);
ret->chain_store = cert->chain_store;
}
goto err;
if (!custom_exts_copy(&ret->srv_ext, &cert->srv_ext))
goto err;
-
+#ifndef OPENSSL_NO_PSK
if (cert->psk_identity_hint) {
- ret->psk_identity_hint = BUF_strdup(cert->psk_identity_hint);
+ ret->psk_identity_hint = OPENSSL_strdup(cert->psk_identity_hint);
if (ret->psk_identity_hint == NULL)
goto err;
}
-
+#endif
return (ret);
err:
return;
i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT);
-#ifdef REF_PRINT
- REF_PRINT("CERT", c);
-#endif
+ REF_PRINT_COUNT("CERT", c);
if (i > 0)
return;
-#ifdef REF_CHECK
- if (i < 0) {
- fprintf(stderr, "ssl_cert_free, bad reference count\n");
- abort(); /* ok */
- }
-#endif
+ REF_ASSERT_ISNT(i < 0);
-#ifndef OPENSSL_NO_RSA
- RSA_free(c->rsa_tmp);
-#endif
#ifndef OPENSSL_NO_DH
- DH_free(c->dh_tmp);
-#endif
-#ifndef OPENSSL_NO_EC
- EC_KEY_free(c->ecdh_tmp);
+ EVP_PKEY_free(c->dh_tmp);
#endif
ssl_cert_clear_certs(c);
int i;
X509_STORE *verify_store;
X509_STORE_CTX ctx;
+ X509_VERIFY_PARAM *param;
if (s->cert->verify_store)
verify_store = s->cert->verify_store;
SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
return (0);
}
+ param = X509_STORE_CTX_get0_param(&ctx);
+
/* Set suite B flags if needed */
X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
+ /* Verify via DANE if enabled */
+ if (DANETLS_ENABLED(&s->dane))
+ X509_STORE_CTX_set0_dane(&ctx, &s->dane);
+
/*
* We need to inherit the verify parameters. These can be determined by
* the context: if its a server it will verify SSL client certificates or
X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server");
/*
- * Anything non-default in "param" should overwrite anything in the ctx.
+ * Anything non-default in "s->param" should overwrite anything in the ctx.
*/
- X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param);
+ X509_VERIFY_PARAM_set1(param, s->param);
if (s->verify_callback)
X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
}
s->verify_result = ctx.error;
+ sk_X509_pop_free(s->verified_chain, X509_free);
+ s->verified_chain = NULL;
+ if (X509_STORE_CTX_get_chain(&ctx) != NULL) {
+ s->verified_chain = X509_STORE_CTX_get1_chain(&ctx);
+ if (s->verified_chain == NULL) {
+ SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+ i = 0;
+ }
+ }
+
+ /* Move peername from the store context params to the SSL handle's */
+ X509_VERIFY_PARAM_move_peername(s->param, param);
+
X509_STORE_CTX_cleanup(&ctx);
return (i);
STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s)
{
- if (s->type == SSL_ST_CONNECT) { /* we are in the client */
+ if (!s->server) { /* we are in the client */
if (((s->version >> 8) == SSL3_VERSION_MAJOR) && (s->s3 != NULL))
return (s->s3->tmp.ca_names);
else
return (add_client_CA(&(ctx->client_CA), x));
}
-static int xname_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
+static int xname_sk_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
{
return (X509_NAME_cmp(*a, *b));
}
+static int xname_cmp(const X509_NAME *a, const X509_NAME *b)
+{
+ return X509_NAME_cmp(a, b);
+}
+
+static unsigned long xname_hash(const X509_NAME *a)
+{
+ return X509_NAME_hash((X509_NAME *)a);
+}
+
/**
* Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed;
* it doesn't really have anything to do with clients (except that a common use
*/
STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
{
- BIO *in;
+ BIO *in = BIO_new(BIO_s_file());
X509 *x = NULL;
X509_NAME *xn = NULL;
- STACK_OF(X509_NAME) *ret = NULL, *sk;
+ STACK_OF(X509_NAME) *ret = NULL;
+ LHASH_OF(X509_NAME) *name_hash =
+ lh_X509_NAME_new(xname_hash, xname_cmp);
- sk = sk_X509_NAME_new(xname_cmp);
-
- in = BIO_new(BIO_s_file_internal());
-
- if ((sk == NULL) || (in == NULL)) {
+ if ((name_hash == NULL) || (in == NULL)) {
SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
goto err;
}
xn = X509_NAME_dup(xn);
if (xn == NULL)
goto err;
- if (sk_X509_NAME_find(sk, xn) >= 0)
+ if (lh_X509_NAME_retrieve(name_hash, xn) != NULL) {
+ /* Duplicate. */
X509_NAME_free(xn);
- else {
- sk_X509_NAME_push(sk, xn);
+ } else {
+ lh_X509_NAME_insert(name_hash, xn);
sk_X509_NAME_push(ret, xn);
}
}
sk_X509_NAME_pop_free(ret, X509_NAME_free);
ret = NULL;
done:
- sk_X509_NAME_free(sk);
BIO_free(in);
X509_free(x);
+ lh_X509_NAME_free(name_hash);
if (ret != NULL)
ERR_clear_error();
return (ret);
int ret = 1;
int (*oldcmp) (const X509_NAME *const *a, const X509_NAME *const *b);
- oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
+ oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_sk_cmp);
- in = BIO_new(BIO_s_file_internal());
+ in = BIO_new(BIO_s_file());
if (in == NULL) {
SSLerr(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK,
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB);
return (0);
}
+ /*
+ * It is valid for the chain not to be complete (because normally we
+ * don't include the root cert in the chain). Therefore we deliberately
+ * ignore the error return from this call. We're not actually verifying
+ * the cert - we're just building as much of the chain as we can
+ */
X509_verify_cert(&xs_ctx);
/* Don't leave errors in the queue */
ERR_clear_error();
/* Rearranging and check the chain: add everything to a store */
if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) {
chain_store = X509_STORE_new();
- if (!chain_store)
+ if (chain_store == NULL)
goto err;
for (i = 0; i < sk_X509_num(cpk->chain); i++) {
x = sk_X509_value(cpk->chain, i);
X509_STORE_free(*pstore);
*pstore = store;
if (ref && store)
- CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE);
+ X509_STORE_up_ref(store);
return 1;
}
level = SSL_CTX_get_security_level(ctx);
else
level = SSL_get_security_level(s);
- /* Level 0: anything goes */
- if (level <= 0)
+
+ if (level <= 0) {
+ /*
+ * No EDH keys weaker than 1024-bits even at level 0, otherwise,
+ * anything goes.
+ */
+ if (op == SSL_SECOP_TMP_DH && bits < 80)
+ return 0;
return 1;
+ }
if (level > 5)
level = 5;
minbits = minbits_table[level - 1];
break;
}
case SSL_SECOP_VERSION:
- /* SSLv3 not allowed on level 2 */
- if (nid <= SSL3_VERSION && level >= 2)
- return 0;
- /* TLS v1.1 and above only for level 3 */
- if (nid <= TLS1_VERSION && level >= 3)
- return 0;
- /* TLS v1.2 only for level 4 and above */
- if (nid <= TLS1_1_VERSION && level >= 4)
- return 0;
+ if (!SSL_IS_DTLS(s)) {
+ /* SSLv3 not allowed at level 2 */
+ if (nid <= SSL3_VERSION && level >= 2)
+ return 0;
+ /* TLS v1.1 and above only for level 3 */
+ if (nid <= TLS1_VERSION && level >= 3)
+ return 0;
+ /* TLS v1.2 only for level 4 and above */
+ if (nid <= TLS1_1_VERSION && level >= 4)
+ return 0;
+ } else {
+ /* DTLS v1.2 only for level 4 and above */
+ if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
+ return 0;
+ }
break;
case SSL_SECOP_COMPRESSION: