Parse ClientHello extensions before deciding on resumption.
This simplifies a little code around EMS and PSK KE modes, but requires
tweaking the SNI code.
The extensions that are more tightly integrated with the handshake are
still processed inline for now. It does, however, require an extra state
in 1.2 so the asynchronous session callback does not cause extensions to
be processed twice. Tweak a test enforce this.
This and a follow-up to move cert_cb before resumption are done in
preparation for resolving the cipher suite before resumption and only
resuming on match.
Note this has caller-visible effects:
- The legacy SNI callback happens before resumption.
- The ALPN callback happens before resumption.
- Custom extension ClientHello parsing callbacks also cannot depend on
resumption state.
- The DoS protection callback now runs after all the extension callbacks
as it is documented to be called after the resumption decision.
BUG=116
Change-Id: I1281a3b61789b95c370314aaed4f04c1babbc65f
Reviewed-on: https://boringssl-review.googlesource.com/11845
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index 979d8cc..ca4223e 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -109,36 +109,39 @@
}
memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len);
- uint8_t alert = SSL_AD_DECODE_ERROR;
- CBS psk_key_exchange_modes;
- if (ssl_early_callback_get_extension(&client_hello, &psk_key_exchange_modes,
- TLSEXT_TYPE_psk_key_exchange_modes) &&
- !ssl_ext_psk_key_exchange_modes_parse_clienthello(
- ssl, &alert, &psk_key_exchange_modes)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ /* TLS 1.3 requires the peer only advertise the null compression. */
+ if (client_hello.compression_methods_len != 1 ||
+ client_hello.compression_methods[0] != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
- SSL_SESSION *session = NULL;
- CBS binders;
- if (hs->accept_psk_mode) {
- CBS pre_shared_key;
- if (ssl_early_callback_get_extension(&client_hello, &pre_shared_key,
- TLSEXT_TYPE_pre_shared_key)) {
- /* Verify that the pre_shared_key extension is the last extension in
- * ClientHello. */
- if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
- client_hello.extensions + client_hello.extensions_len) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- return ssl_hs_error;
- }
+ /* TLS extensions. */
+ if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+ return ssl_hs_error;
+ }
- if (!ssl_ext_pre_shared_key_parse_clienthello(ssl, &session, &binders,
- &alert, &pre_shared_key)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- return ssl_hs_error;
- }
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ SSL_SESSION *session = NULL;
+ CBS pre_shared_key, binders;
+ if (hs->accept_psk_mode &&
+ ssl_early_callback_get_extension(&client_hello, &pre_shared_key,
+ TLSEXT_TYPE_pre_shared_key)) {
+ /* Verify that the pre_shared_key extension is the last extension in
+ * ClientHello. */
+ if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
+ client_hello.extensions + client_hello.extensions_len) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ return ssl_hs_error;
+ }
+
+ if (!ssl_ext_pre_shared_key_parse_clienthello(ssl, &session, &binders,
+ &alert, &pre_shared_key)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ return ssl_hs_error;
}
}
@@ -179,20 +182,6 @@
return ssl_hs_error;
}
- /* TLS 1.3 requires the peer only advertise the null compression. */
- if (client_hello.compression_methods_len != 1 ||
- client_hello.compression_methods[0] != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- return ssl_hs_error;
- }
-
- /* TLS extensions. */
- if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
- return ssl_hs_error;
- }
-
hs->state = state_select_parameters;
return ssl_hs_ok;
}
@@ -282,6 +271,15 @@
}
ssl->s3->new_session->cipher = cipher;
+
+ /* On new sessions, stash the SNI value in the session. */
+ if (ssl->s3->hs->hostname != NULL) {
+ ssl->s3->new_session->tlsext_hostname = BUF_strdup(ssl->s3->hs->hostname);
+ if (ssl->s3->new_session->tlsext_hostname == NULL) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return ssl_hs_error;
+ }
+ }
}
ssl->s3->tmp.new_cipher = ssl->s3->new_session->cipher;