Add a ssl_hs_flush_and_read_message wait mode.

Every flush but the last is always immediately followed by a read. Add a
combined wait mode to make things simpler. Unfortunately, both flights
we have (the state machine doesn't write the first ClientHello) are
followed immediately by a state change, which means we still need some
state in between because we must run code after write_message but before
read_message.

(This way to fix that is to get rid of the buffer BIO, change
write_message to write_flight, and allow things like init_message /
finish_message / init_message / finish_message / set_write_state /
init_message / finish_message / write_flight.)

Change-Id: Iebaa388ccbe7fcad48c1b2256e1c0d3a7c9c8a2a
Reviewed-on: https://boringssl-review.googlesource.com/8828
Reviewed-by: Steven Valdez <svaldez@google.com>
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-18 22:25:05 +02:00 committed by CQ bot account: commit-bot@chromium.org
parent feff406782
commit f2401eb42b
3 changed files with 18 additions and 20 deletions

View File

@ -844,6 +844,7 @@ enum ssl_hs_wait_t {
ssl_hs_read_message,
ssl_hs_write_message,
ssl_hs_flush,
ssl_hs_flush_and_read_message,
ssl_hs_x509_lookup,
ssl_hs_private_key_operation,
};

View File

@ -68,6 +68,20 @@ int tls13_handshake(SSL *ssl) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
return -1;
case ssl_hs_flush:
case ssl_hs_flush_and_read_message: {
int ret = BIO_flush(ssl->wbio);
if (ret <= 0) {
ssl->rwstate = SSL_WRITING;
return ret;
}
if (hs->wait != ssl_hs_flush_and_read_message) {
break;
}
hs->wait = ssl_hs_read_message;
/* Fall-through. */
}
case ssl_hs_read_message: {
int ret = ssl->method->ssl_get_message(ssl, -1, ssl_dont_hash_message);
if (ret <= 0) {
@ -84,15 +98,6 @@ int tls13_handshake(SSL *ssl) {
break;
}
case ssl_hs_flush: {
int ret = BIO_flush(ssl->wbio);
if (ret <= 0) {
ssl->rwstate = SSL_WRITING;
return ret;
}
break;
}
case ssl_hs_x509_lookup:
ssl->rwstate = SSL_X509_LOOKUP;
hs->wait = ssl_hs_ok;
@ -316,6 +321,8 @@ int tls13_check_message_type(SSL *ssl, int type) {
if (ssl->s3->tmp.message_type != type) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
ERR_add_error_dataf("got type %d, wanted type %d",
ssl->s3->tmp.message_type, type);
return 0;
}

View File

@ -37,7 +37,6 @@ enum server_hs_state_t {
state_complete_server_certificate_verify,
state_send_server_finished,
state_flush,
state_read_client_second_flight,
state_process_client_certificate,
state_process_client_certificate_verify,
state_process_client_finished,
@ -352,12 +351,6 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
}
static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
hs->state = state_read_client_second_flight;
return ssl_hs_flush;
}
static enum ssl_hs_wait_t do_read_client_second_flight(SSL *ssl,
SSL_HANDSHAKE *hs) {
/* Update the secret to the master secret and derive traffic keys. */
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
@ -368,7 +361,7 @@ static enum ssl_hs_wait_t do_read_client_second_flight(SSL *ssl,
}
hs->state = state_process_client_certificate;
return ssl_hs_read_message;
return ssl_hs_flush_and_read_message;
}
static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
@ -457,9 +450,6 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
case state_flush:
ret = do_flush(ssl, hs);
break;
case state_read_client_second_flight:
ret = do_read_client_second_flight(ssl, hs);
break;
case state_process_client_certificate:
ret = do_process_client_certificate(ssl, hs);
break;