Factor out the client_cert_cb code.

Share a bit more of it between TLS 1.2 and 1.3.

Change-Id: I43c9dbf785a3d33db1793cffb0fdbd3af075cc89
Reviewed-on: https://boringssl-review.googlesource.com/8849
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
David Benjamin 2016-07-20 10:11:04 +02:00 committed by CQ bot account: commit-bot@chromium.org
parent 14a077c353
commit 13f1ebe827
6 changed files with 45 additions and 63 deletions

View File

@ -322,7 +322,6 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_CW_CERT_A (0x170 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_B (0x171 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_C (0x172 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_D (0x173 | SSL_ST_CONNECT)
#define SSL3_ST_CW_KEY_EXCH_A (0x180 | SSL_ST_CONNECT)
#define SSL3_ST_CW_KEY_EXCH_B (0x181 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_VRFY_A (0x190 | SSL_ST_CONNECT)

View File

@ -328,7 +328,6 @@ int ssl3_connect(SSL *ssl) {
case SSL3_ST_CW_CERT_A:
case SSL3_ST_CW_CERT_B:
case SSL3_ST_CW_CERT_C:
case SSL3_ST_CW_CERT_D:
if (ssl->s3->tmp.cert_request) {
ret = ssl3_send_client_certificate(ssl);
if (ret <= 0) {
@ -1410,22 +1409,6 @@ static int ssl3_get_server_hello_done(SSL *ssl) {
return 1;
}
static int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509,
EVP_PKEY **out_pkey) {
if (ssl->ctx->client_cert_cb == NULL) {
return 0;
}
int ret = ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey);
if (ret <= 0) {
return ret;
}
assert(*out_x509 != NULL);
assert(*out_pkey != NULL);
return 1;
}
static int ssl3_send_client_certificate(SSL *ssl) {
if (ssl->state == SSL3_ST_CW_CERT_A) {
/* Call cert_cb to update the certificate. */
@ -1441,36 +1424,19 @@ static int ssl3_send_client_certificate(SSL *ssl) {
}
}
if (ssl_has_certificate(ssl)) {
ssl->state = SSL3_ST_CW_CERT_C;
} else {
ssl->state = SSL3_ST_CW_CERT_B;
}
ssl->state = SSL3_ST_CW_CERT_B;
}
if (ssl->state == SSL3_ST_CW_CERT_B) {
/* Call client_cert_cb to update the certificate. */
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int ret = ssl_do_client_cert_cb(ssl, &x509, &pkey);
if (ret < 0) {
ssl->rwstate = SSL_X509_LOOKUP;
int should_retry;
if (!ssl_do_client_cert_cb(ssl, &should_retry)) {
if (should_retry) {
ssl->rwstate = SSL_X509_LOOKUP;
}
return -1;
}
int setup_error = ret == 1 && (!SSL_use_certificate(ssl, x509) ||
!SSL_use_PrivateKey(ssl, pkey));
X509_free(x509);
EVP_PKEY_free(pkey);
if (setup_error) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
ssl->state = SSL3_ST_CW_CERT_C;
}
if (ssl->state == SSL3_ST_CW_CERT_C) {
if (!ssl_has_certificate(ssl)) {
ssl->s3->tmp.cert_request = 0;
/* Without a client certificate, the handshake buffer may be released. */
@ -1486,10 +1452,10 @@ static int ssl3_send_client_certificate(SSL *ssl) {
if (!ssl3_output_cert_chain(ssl)) {
return -1;
}
ssl->state = SSL3_ST_CW_CERT_D;
ssl->state = SSL3_ST_CW_CERT_C;
}
assert(ssl->state == SSL3_ST_CW_CERT_D);
assert(ssl->state == SSL3_ST_CW_CERT_C);
return ssl->method->write_message(ssl);
}

View File

@ -774,6 +774,11 @@ int ssl_add_client_CA_list(SSL *ssl, CBB *cbb);
* error queue. */
int ssl_check_leaf_certificate(SSL *ssl, X509 *leaf);
/* ssl_do_client_cert_cb runs the client_cert_cb, if any, and returns one on
* success and zero on error. On error, it sets |*out_should_retry| to one if
* the callback failed and should be retried and zero otherwise. */
int ssl_do_client_cert_cb(SSL *ssl, int *out_should_retry);
/* TLS 1.3 key derivation. */

View File

@ -639,6 +639,33 @@ int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) {
return CBB_flush(cbb);
}
int ssl_do_client_cert_cb(SSL *ssl, int *out_should_retry) {
if (ssl_has_certificate(ssl) || ssl->ctx->client_cert_cb == NULL) {
return 1;
}
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int ret = ssl->ctx->client_cert_cb(ssl, &x509, &pkey);
if (ret < 0) {
*out_should_retry = 1;
return 0;
}
if (ret != 0) {
if (!SSL_use_certificate(ssl, x509) ||
!SSL_use_PrivateKey(ssl, pkey)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
*out_should_retry = 0;
return 0;
}
}
X509_free(x509);
EVP_PKEY_free(pkey);
return 1;
}
static int set_cert_store(X509_STORE **store_ptr, X509_STORE *new_store, int take_ref) {
X509_STORE_free(*store_ptr);
*store_ptr = new_store;

View File

@ -134,9 +134,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_CW_CERT_C:
return "SSLv3 write client certificate C";
case SSL3_ST_CW_CERT_D:
return "SSLv3 write client certificate D";
case SSL3_ST_CW_KEY_EXCH_A:
return "SSLv3 write client key exchange A";
@ -294,9 +291,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_CW_CERT_C:
return "3WCC_C";
case SSL3_ST_CW_CERT_D:
return "3WCC_D";
case SSL3_ST_CW_KEY_EXCH_A:
return "3WCKEA";

View File

@ -330,23 +330,14 @@ static enum ssl_hs_wait_t do_certificate_callback(SSL *ssl, SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_send_client_certificate(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!ssl_has_certificate(ssl) && ssl->ctx->client_cert_cb != NULL) {
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int rv = ssl->ctx->client_cert_cb(ssl, &x509, &pkey);
if (rv < 0) {
/* Call client_cert_cb to update the certificate. */
int should_retry;
if (!ssl_do_client_cert_cb(ssl, &should_retry)) {
if (should_retry) {
hs->state = state_send_client_certificate;
return ssl_hs_x509_lookup;
}
int setup_error = rv == 1 && (!SSL_use_certificate(ssl, x509) ||
!SSL_use_PrivateKey(ssl, pkey));
X509_free(x509);
EVP_PKEY_free(pkey);
if (setup_error) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
return ssl_hs_error;
}
if (!tls13_prepare_certificate(ssl)) {