Make ssl_parse_extensions a little easier to use.
std::initializer_list appears to work by instantiating a T[N] at the
call site (which is what we were doing anyway), so I don't believe there
is a runtime dependency.
This also adds a way for individual entries to turn themselves off,
which means we don't need to manually check for some unsolicited
extensions.
Change-Id: I40f79b6a0e9c005fc621f4a798fe201bfbf08411
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48910
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 7a19b2a..bd7e63f 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -162,31 +162,25 @@
return ssl_hs_ok;
}
- bool have_cookie, have_key_share, have_supported_versions;
- CBS cookie, key_share, supported_versions;
- SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
- {TLSEXT_TYPE_cookie, &have_cookie, &cookie},
- {TLSEXT_TYPE_supported_versions, &have_supported_versions,
- &supported_versions},
- };
-
- if (!ssl_parse_extensions(&server_hello.extensions, &alert, ext_types,
+ SSLExtension cookie(TLSEXT_TYPE_cookie), key_share(TLSEXT_TYPE_key_share),
+ supported_versions(TLSEXT_TYPE_supported_versions);
+ if (!ssl_parse_extensions(&server_hello.extensions, &alert,
+ {&cookie, &key_share, &supported_versions},
/*ignore_unknown=*/false)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
- if (!have_cookie && !have_key_share) {
+ if (!cookie.present && !key_share.present) {
OPENSSL_PUT_ERROR(SSL, SSL_R_EMPTY_HELLO_RETRY_REQUEST);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
- if (have_cookie) {
+ if (cookie.present) {
CBS cookie_value;
- if (!CBS_get_u16_length_prefixed(&cookie, &cookie_value) ||
+ if (!CBS_get_u16_length_prefixed(&cookie.data, &cookie_value) ||
CBS_len(&cookie_value) == 0 ||
- CBS_len(&cookie) != 0) {
+ CBS_len(&cookie.data) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -197,9 +191,10 @@
}
}
- if (have_key_share) {
+ if (key_share.present) {
uint16_t group_id;
- if (!CBS_get_u16(&key_share, &group_id) || CBS_len(&key_share) != 0) {
+ if (!CBS_get_u16(&key_share.data, &group_id) ||
+ CBS_len(&key_share.data) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -316,18 +311,11 @@
OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_hello.random),
SSL3_RANDOM_SIZE);
- // Parse out the extensions.
- bool have_key_share = false, have_pre_shared_key = false,
- have_supported_versions = false;
- CBS key_share, pre_shared_key, supported_versions;
- SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
- {TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
- {TLSEXT_TYPE_supported_versions, &have_supported_versions,
- &supported_versions},
- };
-
- if (!ssl_parse_extensions(&server_hello.extensions, &alert, ext_types,
+ SSLExtension key_share(TLSEXT_TYPE_key_share),
+ pre_shared_key(TLSEXT_TYPE_pre_shared_key, ssl->session != nullptr),
+ supported_versions(TLSEXT_TYPE_supported_versions);
+ if (!ssl_parse_extensions(&server_hello.extensions, &alert,
+ {&key_share, &pre_shared_key, &supported_versions},
/*ignore_unknown=*/false)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
@@ -335,8 +323,9 @@
// Recheck supported_versions, in case this is after HelloRetryRequest.
uint16_t version;
- if (!have_supported_versions ||
- !CBS_get_u16(&supported_versions, &version) ||
+ if (!supported_versions.present ||
+ !CBS_get_u16(&supported_versions.data, &version) ||
+ CBS_len(&supported_versions.data) != 0 ||
version != ssl->version) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SECOND_SERVERHELLO_VERSION_MISMATCH);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -344,15 +333,9 @@
}
alert = SSL_AD_DECODE_ERROR;
- if (have_pre_shared_key) {
- if (ssl->session == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
- ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
- return ssl_hs_error;
- }
-
+ if (pre_shared_key.present) {
if (!ssl_ext_pre_shared_key_parse_serverhello(hs, &alert,
- &pre_shared_key)) {
+ &pre_shared_key.data)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
@@ -409,7 +392,7 @@
return ssl_hs_error;
}
- if (!have_key_share) {
+ if (!key_share.present) {
// We do not support psk_ke and thus always require a key share.
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
@@ -420,7 +403,7 @@
Array<uint8_t> dhe_secret;
alert = SSL_AD_DECODE_ERROR;
if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &alert,
- &key_share)) {
+ &key_share.data)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
@@ -456,7 +439,7 @@
SSL3_RANDOM_SIZE);
} else {
// Resuming against the ClientHelloOuter was an unsolicited extension.
- if (have_pre_shared_key) {
+ if (pre_shared_key.present) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return ssl_hs_error;
@@ -600,25 +583,19 @@
}
- bool have_sigalgs = false, have_ca = false;
- CBS sigalgs, ca;
- const SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_signature_algorithms, &have_sigalgs, &sigalgs},
- {TLSEXT_TYPE_certificate_authorities, &have_ca, &ca},
- };
-
+ SSLExtension sigalgs(TLSEXT_TYPE_signature_algorithms),
+ ca(TLSEXT_TYPE_certificate_authorities);
CBS body = msg.body, context, extensions, supported_signature_algorithms;
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!CBS_get_u8_length_prefixed(&body, &context) ||
// The request context is always empty during the handshake.
CBS_len(&context) != 0 ||
- !CBS_get_u16_length_prefixed(&body, &extensions) ||
+ !CBS_get_u16_length_prefixed(&body, &extensions) || //
CBS_len(&body) != 0 ||
- !ssl_parse_extensions(&extensions, &alert, ext_types,
+ !ssl_parse_extensions(&extensions, &alert, {&sigalgs, &ca},
/*ignore_unknown=*/true) ||
- (have_ca && CBS_len(&ca) == 0) ||
- !have_sigalgs ||
- !CBS_get_u16_length_prefixed(&sigalgs,
+ !sigalgs.present ||
+ !CBS_get_u16_length_prefixed(&sigalgs.data,
&supported_signature_algorithms) ||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -626,8 +603,8 @@
return ssl_hs_error;
}
- if (have_ca) {
- hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca);
+ if (ca.present) {
+ hs->ca_names = ssl_parse_client_CA_list(ssl, &alert, &ca.data);
if (!hs->ca_names) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
@@ -1050,23 +1027,17 @@
return nullptr;
}
- // Parse out the extensions.
- bool have_early_data = false;
- CBS early_data;
- const SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_early_data, &have_early_data, &early_data},
- };
-
+ SSLExtension early_data(TLSEXT_TYPE_early_data);
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!ssl_parse_extensions(&extensions, &alert, ext_types,
+ if (!ssl_parse_extensions(&extensions, &alert, {&early_data},
/*ignore_unknown=*/true)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return nullptr;
}
- if (have_early_data) {
- if (!CBS_get_u32(&early_data, &session->ticket_max_early_data) ||
- CBS_len(&early_data) != 0) {
+ if (early_data.present) {
+ if (!CBS_get_u32(&early_data.data, &session->ticket_max_early_data) ||
+ CBS_len(&early_data.data) != 0) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return nullptr;