Fold away certificate slots mechanism.
This allows us to remove the confusing EVP_PKEY argument to the
SSL_PRIVATE_KEY_METHOD wrapper functions. It also simplifies some of the
book-keeping around the CERT structure, as well as the API for
configuring certificates themselves. The current one is a little odd as
some functions automatically route to the slot while others affect the
most recently touched slot. Others still (extra_certs) apply to all
slots, making them not terribly useful.
Consumers with complex needs should use cert_cb or the early callback
(select_certificate_cb) to configure whatever they like based on the
ClientHello.
BUG=486295
Change-Id: Ice29ffeb867fa4959898b70dfc50fc00137f01f3
Reviewed-on: https://boringssl-review.googlesource.com/5351
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 0064b43..6a694b3 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -799,20 +799,19 @@
/* Fix this so it checks all the valid key/cert options */
int SSL_CTX_check_private_key(const SSL_CTX *ctx) {
- if (ctx == NULL || ctx->cert == NULL || ctx->cert->key->x509 == NULL) {
+ if (ctx == NULL || ctx->cert == NULL || ctx->cert->x509 == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key,
SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
- if (ctx->cert->key->privatekey == NULL) {
+ if (ctx->cert->privatekey == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key,
SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return 0;
}
- return X509_check_private_key(ctx->cert->key->x509,
- ctx->cert->key->privatekey);
+ return X509_check_private_key(ctx->cert->x509, ctx->cert->privatekey);
}
/* Fix this function so that it takes an optional type parameter */
@@ -828,20 +827,19 @@
return 0;
}
- if (ssl->cert->key->x509 == NULL) {
+ if (ssl->cert->x509 == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
- if (ssl->cert->key->privatekey == NULL) {
+ if (ssl->cert->privatekey == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_check_private_key,
SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return 0;
}
- return X509_check_private_key(ssl->cert->key->x509,
- ssl->cert->key->privatekey);
+ return X509_check_private_key(ssl->cert->x509, ssl->cert->privatekey);
}
int SSL_accept(SSL *s) {
@@ -1716,8 +1714,6 @@
CRYPTO_new_ex_data(&g_ex_data_class_ssl_ctx, ret, &ret->ex_data);
- ret->extra_certs = NULL;
-
ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
ret->tlsext_servername_callback = 0;
@@ -1781,7 +1777,6 @@
ssl_cipher_preference_list_free(ctx->cipher_list_tls11);
ssl_cert_free(ctx->cert);
sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free);
- sk_X509_pop_free(ctx->extra_certs, X509_free);
sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles);
OPENSSL_free(ctx->psk_identity_hint);
OPENSSL_free(ctx->tlsext_ecpointformatlist);
@@ -1827,17 +1822,12 @@
ssl_cert_set_cert_cb(s->cert, cb, arg);
}
-static int ssl_has_key(SSL *s, size_t idx) {
- CERT_PKEY *cpk = &s->cert->pkeys[idx];
- return cpk->x509 && cpk->privatekey;
-}
-
void ssl_get_compatible_server_ciphers(SSL *s, uint32_t *out_mask_k,
uint32_t *out_mask_a) {
CERT *c = s->cert;
- int have_rsa_cert, dh_tmp;
+ int have_rsa_cert = 0, dh_tmp;
uint32_t mask_k, mask_a;
- int have_ecc_cert, ecdsa_ok;
+ int have_ecc_cert = 0, ecdsa_ok;
X509 *x;
if (c == NULL) {
@@ -1849,8 +1839,13 @@
dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
- have_rsa_cert = ssl_has_key(s, SSL_PKEY_RSA);
- have_ecc_cert = ssl_has_key(s, SSL_PKEY_ECC);
+ if (s->cert->x509 != NULL && s->cert->privatekey != NULL) {
+ if (s->cert->privatekey->type == EVP_PKEY_RSA) {
+ have_rsa_cert = 1;
+ } else if (s->cert->privatekey->type == EVP_PKEY_EC) {
+ have_ecc_cert = 1;
+ }
+ }
mask_k = 0;
mask_a = 0;
@@ -1865,7 +1860,7 @@
/* An ECC certificate may be usable for ECDSA cipher suites depending on the
* key usage extension and on the client's curve preferences. */
if (have_ecc_cert) {
- x = c->pkeys[SSL_PKEY_ECC].x509;
+ x = c->x509;
/* This call populates extension flags (ex_flags). */
X509_check_purpose(x, -1, 0);
ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
@@ -1895,47 +1890,6 @@
*out_mask_a = mask_a;
}
-static int ssl_get_server_cert_index(const SSL *s) {
- int idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
- if (idx == -1) {
- OPENSSL_PUT_ERROR(SSL, ssl_get_server_cert_index, ERR_R_INTERNAL_ERROR);
- }
- return idx;
-}
-
-CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) {
- int i = ssl_get_server_cert_index(s);
-
- /* This may or may not be an error. */
- if (i < 0) {
- return NULL;
- }
-
- /* May be NULL. */
- return &s->cert->pkeys[i];
-}
-
-EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher) {
- uint32_t alg_a = cipher->algorithm_auth;
- CERT *c = s->cert;
- int idx = -1;
-
- if ((alg_a & SSL_aRSA) &&
- (c->pkeys[SSL_PKEY_RSA].privatekey != NULL)) {
- idx = SSL_PKEY_RSA;
- } else if ((alg_a & SSL_aECDSA) &&
- (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) {
- idx = SSL_PKEY_ECC;
- }
-
- if (idx == -1) {
- OPENSSL_PUT_ERROR(SSL, ssl_get_sign_pkey, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
-
- return c->pkeys[idx].privatekey;
-}
-
void ssl_update_cache(SSL *s, int mode) {
/* Never cache sessions with empty session IDs. */
if (s->session->session_id_length == 0) {
@@ -2164,7 +2118,7 @@
X509 *SSL_get_certificate(const SSL *s) {
if (s->cert != NULL) {
- return s->cert->key->x509;
+ return s->cert->x509;
}
return NULL;
@@ -2172,7 +2126,7 @@
EVP_PKEY *SSL_get_privatekey(const SSL *s) {
if (s->cert != NULL) {
- return s->cert->key->privatekey;
+ return s->cert->privatekey;
}
return NULL;
@@ -2180,7 +2134,7 @@
X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
if (ctx->cert != NULL) {
- return ctx->cert->key->x509;
+ return ctx->cert->x509;
}
return NULL;
@@ -2188,7 +2142,7 @@
EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) {
if (ctx->cert != NULL) {
- return ctx->cert->key->privatekey;
+ return ctx->cert->privatekey;
}
return NULL;