Implement PR 1091 (TLS 1.3 draft '22').
This introduces a wire change to Experiment2/Experiment3 over 0RTT, however
as there is never going to be a 0RTT deployment with Experiment2/Experiment3,
this is valid.
Change-Id: Id541d195cbc4bbb3df7680ae2a02b53bb8ae3eab
Reviewed-on: https://boringssl-review.googlesource.com/22744
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index 9afd0d4..1040ace 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -47,7 +47,6 @@
state_send_server_certificate_verify,
state_send_server_finished,
state_read_second_client_flight,
- state_process_change_cipher_spec,
state_process_end_of_early_data,
state_read_client_certificate,
state_read_client_certificate_verify,
@@ -490,23 +489,55 @@
static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- ScopedCBB cbb;
- CBB body, extensions;
- uint16_t group_id;
- if (!ssl->method->init_message(ssl, cbb.get(), &body,
- SSL3_MT_HELLO_RETRY_REQUEST) ||
- !CBB_add_u16(&body, ssl->version) ||
- (ssl_is_draft21(ssl->version) &&
- !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) ||
- !tls1_get_shared_group(hs, &group_id) ||
- !CBB_add_u16_length_prefixed(&body, &extensions) ||
- !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
- !CBB_add_u16(&extensions, 2 /* length */) ||
- !CBB_add_u16(&extensions, group_id) ||
- !ssl_add_message_cbb(ssl, cbb.get())) {
- return ssl_hs_error;
+
+
+ if (ssl_is_draft22(ssl->version)) {
+ ScopedCBB cbb;
+ CBB body, session_id, extensions;
+ uint16_t group_id;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
+ SSL3_MT_SERVER_HELLO) ||
+ !CBB_add_u16(&body, TLS1_2_VERSION) ||
+ !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
+ !CBB_add_u8_length_prefixed(&body, &session_id) ||
+ !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
+ !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+ !CBB_add_u8(&body, 0 /* no compression */) ||
+ !tls1_get_shared_group(hs, &group_id) ||
+ !CBB_add_u16_length_prefixed(&body, &extensions) ||
+ !CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
+ !CBB_add_u16(&extensions, 2 /* length */) ||
+ !CBB_add_u16(&extensions, ssl->version) ||
+ !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+ !CBB_add_u16(&extensions, 2 /* length */) ||
+ !CBB_add_u16(&extensions, group_id) ||
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
+ }
+
+ if (!ssl->method->add_change_cipher_spec(ssl)) {
+ return ssl_hs_error;
+ }
+ } else {
+ ScopedCBB cbb;
+ CBB body, extensions;
+ uint16_t group_id;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
+ SSL3_MT_HELLO_RETRY_REQUEST) ||
+ !CBB_add_u16(&body, ssl->version) ||
+ (ssl_is_draft21(ssl->version) &&
+ !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) ||
+ !tls1_get_shared_group(hs, &group_id) ||
+ !CBB_add_u16_length_prefixed(&body, &extensions) ||
+ !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+ !CBB_add_u16(&extensions, 2 /* length */) ||
+ !CBB_add_u16(&extensions, group_id) ||
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
+ }
}
+ hs->sent_hello_retry_request = true;
hs->tls13_state = state_read_second_client_hello;
return ssl_hs_flush;
}
@@ -576,6 +607,7 @@
}
if (ssl_is_resumption_experiment(ssl->version) &&
+ (!ssl_is_draft22(ssl->version) || !hs->sent_hello_retry_request) &&
!ssl->method->add_change_cipher_spec(ssl)) {
return ssl_hs_error;
}
@@ -756,46 +788,35 @@
hs->can_early_write = true;
hs->can_early_read = true;
hs->in_early_data = true;
- hs->tls13_state = state_process_end_of_early_data;
- return ssl_hs_read_end_of_early_data;
}
hs->tls13_state = state_process_end_of_early_data;
- return ssl_hs_ok;
+ return ssl->early_data_accepted ? ssl_hs_read_end_of_early_data : ssl_hs_ok;
}
static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- hs->tls13_state = state_process_change_cipher_spec;
if (hs->early_data_offered) {
// If early data was not accepted, the EndOfEarlyData and ChangeCipherSpec
// message will be in the discarded early data.
- if (!hs->ssl->early_data_accepted) {
- return ssl_hs_ok;
- }
- if (ssl_is_draft21(ssl->version)) {
- SSLMessage msg;
- if (!ssl->method->get_message(ssl, &msg)) {
- return ssl_hs_read_message;
- }
+ if (hs->ssl->early_data_accepted) {
+ if (ssl_is_draft21(ssl->version)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
- if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
- return ssl_hs_error;
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
+ return ssl_hs_error;
+ }
+ if (CBS_len(&msg.body) != 0) {
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ return ssl_hs_error;
+ }
+ ssl->method->next_message(ssl);
}
- if (CBS_len(&msg.body) != 0) {
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return ssl_hs_error;
- }
- ssl->method->next_message(ssl);
}
}
- return ssl_is_resumption_client_ccs_experiment(hs->ssl->version)
- ? ssl_hs_read_change_cipher_spec
- : ssl_hs_ok;
-}
-
-static enum ssl_hs_wait_t do_process_change_cipher_spec(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
hs->hash_len)) {
return ssl_hs_error;
@@ -973,9 +994,6 @@
case state_process_end_of_early_data:
ret = do_process_end_of_early_data(hs);
break;
- case state_process_change_cipher_spec:
- ret = do_process_change_cipher_spec(hs);
- break;
case state_read_client_certificate:
ret = do_read_client_certificate(hs);
break;
@@ -1028,8 +1046,6 @@
return "TLS 1.3 server send_server_finished";
case state_read_second_client_flight:
return "TLS 1.3 server read_second_client_flight";
- case state_process_change_cipher_spec:
- return "TLS 1.3 server process_change_cipher_spec";
case state_process_end_of_early_data:
return "TLS 1.3 server process_end_of_early_data";
case state_read_client_certificate: