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>
diff --git a/ssl/internal.h b/ssl/internal.h
index a70400b..b52c974 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -844,6 +844,7 @@
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,
};
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index 4e9feaa..023dc0d 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -68,6 +68,20 @@
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 @@
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 @@
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;
}
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index ce65abf..1a1e52a 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -37,7 +37,6 @@
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_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 @@
}
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 @@
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;