Trim unnecessary TLS 1.3 states.

Large chunks of contiguous messages can now be sent in a row. Notably,
the ServerHello flight involves a number of optional messages which can
now be collapsed into straight-line code.

BUG=72

Change-Id: I1429d22a12401aa0f811a04e495bd5d754c084a4
Reviewed-on: https://boringssl-review.googlesource.com/13226
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2017-01-12 19:44:57 -05:00 committed by Adam Langley
parent 25ac251a1d
commit 81b7bc3979
2 changed files with 69 additions and 111 deletions

View File

@ -40,8 +40,7 @@ enum client_hs_state_t {
state_send_client_certificate,
state_send_client_certificate_verify,
state_complete_client_certificate_verify,
state_send_channel_id,
state_send_client_finished,
state_complete_second_flight,
state_done,
};
@ -464,7 +463,7 @@ static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* The peer didn't request a certificate. */
if (!hs->cert_request) {
hs->tls13_state = state_send_channel_id;
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
}
@ -496,13 +495,13 @@ static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
SSL *const ssl = hs->ssl;
/* Don't send CertificateVerify if there is no certificate. */
if (!ssl_has_certificate(ssl)) {
hs->tls13_state = state_send_channel_id;
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
}
switch (tls13_prepare_certificate_verify(hs, is_first_run)) {
case ssl_private_key_success:
hs->tls13_state = state_send_channel_id;
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
case ssl_private_key_retry:
@ -517,39 +516,35 @@ static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_channel_id(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_complete_second_flight(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!ssl->s3->tlsext_channel_id_valid) {
hs->tls13_state = state_send_client_finished;
return ssl_hs_ok;
/* Send a Channel ID assertion if necessary. */
if (ssl->s3->tlsext_channel_id_valid) {
if (!ssl_do_channel_id_callback(ssl)) {
hs->tls13_state = state_complete_second_flight;
return ssl_hs_error;
}
if (ssl->tlsext_channel_id_private == NULL) {
return ssl_hs_channel_id_lookup;
}
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
!tls1_write_channel_id(ssl, &body) ||
!ssl_add_message_cbb(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
}
}
if (!ssl_do_channel_id_callback(ssl)) {
return ssl_hs_error;
}
if (ssl->tlsext_channel_id_private == NULL) {
return ssl_hs_channel_id_lookup;
}
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
!tls1_write_channel_id(ssl, &body) ||
!ssl_add_message_cbb(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
}
hs->tls13_state = state_send_client_finished;
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_client_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* Send a Finished message. */
if (!tls13_prepare_finished(hs)) {
return ssl_hs_error;
}
/* Derive the final keys and enable them. */
if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->server_traffic_secret_0,
hs->hash_len) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_traffic_secret_0,
@ -600,11 +595,8 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
case state_complete_client_certificate_verify:
ret = do_send_client_certificate_verify(hs, 0 /* complete */);
break;
case state_send_channel_id:
ret = do_send_channel_id(hs);
break;
case state_send_client_finished:
ret = do_send_client_finished(hs);
case state_complete_second_flight:
ret = do_complete_second_flight(hs);
break;
case state_done:
ret = ssl_hs_ok;

View File

@ -40,9 +40,6 @@ enum server_hs_state_t {
state_send_hello_retry_request,
state_process_second_client_hello,
state_send_server_hello,
state_send_encrypted_extensions,
state_send_certificate_request,
state_send_server_certificate,
state_send_server_certificate_verify,
state_complete_server_certificate_verify,
state_send_server_finished,
@ -390,6 +387,8 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* Send a ServerHello. */
CBB cbb, body, extensions;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
!CBB_add_u16(&body, ssl->version) ||
@ -413,39 +412,23 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
goto err;
}
hs->tls13_state = state_send_encrypted_extensions;
return ssl_hs_ok;
err:
CBB_cleanup(&cbb);
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* Derive and enable the handshake traffic secrets. */
if (!tls13_derive_handshake_secrets(hs) ||
!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
hs->hash_len) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
hs->hash_len)) {
return ssl_hs_error;
goto err;
}
CBB cbb, body;
/* Send EncryptedExtensions. */
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_ENCRYPTED_EXTENSIONS) ||
!ssl_add_serverhello_tlsext(hs, &body) ||
!ssl_add_message_cbb(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
goto err;
}
hs->tls13_state = state_send_certificate_request;
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_certificate_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* Determine whether to request a client certificate. */
hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
/* CertificateRequest may only be sent in non-resumption handshakes. */
@ -453,38 +436,50 @@ static enum ssl_hs_wait_t do_send_certificate_request(SSL_HANDSHAKE *hs) {
hs->cert_request = 0;
}
if (!hs->cert_request) {
/* Skip this state. */
hs->tls13_state = state_send_server_certificate;
return ssl_hs_ok;
}
/* Send a CertificateRequest, if necessary. */
if (hs->cert_request) {
CBB sigalgs_cbb;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_CERTIFICATE_REQUEST) ||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
goto err;
}
CBB cbb, body, sigalgs_cbb;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_CERTIFICATE_REQUEST) ||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
goto err;
}
const uint16_t *sigalgs;
size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
goto err;
}
const uint16_t *sigalgs;
size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
goto err;
}
for (size_t i = 0; i < num_sigalgs; i++) {
if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
goto err;
}
}
for (size_t i = 0; i < num_sigalgs; i++) {
if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
if (!ssl_add_client_CA_list(ssl, &body) ||
!CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
!ssl_add_message_cbb(ssl, &cbb)) {
goto err;
}
}
if (!ssl_add_client_CA_list(ssl, &body) ||
!CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
!ssl_add_message_cbb(ssl, &cbb)) {
goto err;
/* Send the server Certificate message, if necessary. */
if (!ssl->s3->session_reused) {
if (!ssl_has_certificate(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
goto err;
}
if (!tls13_prepare_certificate(hs)) {
goto err;
}
hs->tls13_state = state_send_server_certificate_verify;
return ssl_hs_ok;
}
hs->tls13_state = state_send_server_certificate;
hs->tls13_state = state_send_server_finished;
return ssl_hs_ok;
err:
@ -492,26 +487,6 @@ err:
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (ssl->s3->session_reused) {
hs->tls13_state = state_send_server_finished;
return ssl_hs_ok;
}
if (!ssl_has_certificate(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}
if (!tls13_prepare_certificate(hs)) {
return ssl_hs_error;
}
hs->tls13_state = state_send_server_certificate_verify;
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run) {
switch (tls13_prepare_certificate_verify(hs, is_first_run)) {
@ -714,15 +689,6 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
case state_send_server_hello:
ret = do_send_server_hello(hs);
break;
case state_send_encrypted_extensions:
ret = do_send_encrypted_extensions(hs);
break;
case state_send_certificate_request:
ret = do_send_certificate_request(hs);
break;
case state_send_server_certificate:
ret = do_send_server_certificate(hs);
break;
case state_send_server_certificate_verify:
ret = do_send_server_certificate_verify(hs, 1 /* first run */);
break;