Shift some complexity out of ssl_add_clienthello_tlsext.
ssl_add_clienthello_tlsext is about to get kinda messy with ECH. Move
the padding and GREASE extensions into a few helpers.
Bug: 275
Change-Id: I3bb702fb79dce4be68490c4a8fd889121ecdae58
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47995
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/handshake.cc b/ssl/handshake.cc
index 1994465..07c9e3d 100644
--- a/ssl/handshake.cc
+++ b/ssl/handshake.cc
@@ -439,8 +439,8 @@
return ret;
}
-uint16_t ssl_get_grease_value(const SSL_HANDSHAKE *hs,
- enum ssl_grease_index_t index) {
+static uint16_t grease_index_to_value(const SSL_HANDSHAKE *hs,
+ enum ssl_grease_index_t index) {
// This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16.
uint16_t ret = hs->grease_seed[index];
ret = (ret & 0xf0) | 0x0a;
@@ -448,6 +448,19 @@
return ret;
}
+uint16_t ssl_get_grease_value(const SSL_HANDSHAKE *hs,
+ enum ssl_grease_index_t index) {
+ uint16_t ret = grease_index_to_value(hs, index);
+ if (index == ssl_grease_extension2 &&
+ ret == grease_index_to_value(hs, ssl_grease_extension1)) {
+ // The two fake extensions must not have the same value. GREASE values are
+ // of the form 0x1a1a, 0x2a2a, 0x3a3a, etc., so XOR to generate a different
+ // one.
+ ret ^= 0x1010;
+ }
+ return ret;
+}
+
enum ssl_hs_wait_t ssl_get_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
SSLMessage msg;
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index 7f2c244..e780677 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -3247,6 +3247,19 @@
return NULL;
}
+static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) {
+ CBB child;
+ uint8_t *ptr;
+ if (!CBB_add_u16(cbb, ext) || //
+ !CBB_add_u16_length_prefixed(cbb, &child) ||
+ !CBB_add_space(&child, &ptr, len)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return false;
+ }
+ OPENSSL_memset(ptr, 0, len);
+ return CBB_flush(cbb);
+}
+
bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out,
bool *out_needs_psk_binder, size_t header_len) {
SSL *const ssl = hs->ssl;
@@ -3262,15 +3275,11 @@
// important to reset this value.
hs->extensions.sent = 0;
- uint16_t grease_ext1 = 0;
- if (ssl->ctx->grease_enabled) {
- // Add a fake empty extension. See RFC 8701.
- grease_ext1 = ssl_get_grease_value(hs, ssl_grease_extension1);
- if (!CBB_add_u16(&extensions, grease_ext1) ||
- !CBB_add_u16(&extensions, 0 /* zero length */)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return false;
- }
+ // Add a fake empty extension. See RFC 8701.
+ if (ssl->ctx->grease_enabled &&
+ !add_padding_extension(
+ &extensions, ssl_get_grease_value(hs, ssl_grease_extension1), 0)) {
+ return false;
}
bool last_was_empty = false;
@@ -3293,22 +3302,10 @@
if (ssl->ctx->grease_enabled) {
// Add a fake non-empty extension. See RFC 8701.
- uint16_t grease_ext2 = ssl_get_grease_value(hs, ssl_grease_extension2);
-
- // The two fake extensions must not have the same value. GREASE values are
- // of the form 0x1a1a, 0x2a2a, 0x3a3a, etc., so XOR to generate a different
- // one.
- if (grease_ext1 == grease_ext2) {
- grease_ext2 ^= 0x1010;
- }
-
- if (!CBB_add_u16(&extensions, grease_ext2) ||
- !CBB_add_u16(&extensions, 1 /* one byte length */) ||
- !CBB_add_u8(&extensions, 0 /* single zero byte as contents */)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ if (!add_padding_extension(
+ &extensions, ssl_get_grease_value(hs, ssl_grease_extension2), 1)) {
return false;
}
-
last_was_empty = false;
}
@@ -3348,16 +3345,9 @@
}
}
- if (padding_len != 0) {
- uint8_t *padding_bytes;
- if (!CBB_add_u16(&extensions, TLSEXT_TYPE_padding) ||
- !CBB_add_u16(&extensions, padding_len) ||
- !CBB_add_space(&extensions, &padding_bytes, padding_len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return false;
- }
-
- OPENSSL_memset(padding_bytes, 0, padding_len);
+ if (padding_len != 0 &&
+ !add_padding_extension(&extensions, TLSEXT_TYPE_padding, padding_len)) {
+ return false;
}
}