Apply GREASE to TLS 1.3 tickets.
Change-Id: I5d4fc0d3204744e93d71a36923469035c19a5b10
Reviewed-on: https://boringssl-review.googlesource.com/11560
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 88fe845..938bcb5 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -3114,8 +3114,8 @@
OPENSSL_EXPORT void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx,
int enable);
-/* SSL_CTX_set_grease_enabled configures whether client sockets on |ctx| should
- * enable GREASE. See draft-davidben-tls-grease-01. */
+/* SSL_CTX_set_grease_enabled configures whether sockets on |ctx| should enable
+ * GREASE. See draft-davidben-tls-grease-01. */
OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled);
diff --git a/ssl/internal.h b/ssl/internal.h
index 3e7c053..720b822 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1024,6 +1024,7 @@
ssl_grease_extension1,
ssl_grease_extension2,
ssl_grease_version,
+ ssl_grease_ticket_extension,
};
/* ssl_get_grease_value returns a GREASE value for |ssl|. For a given
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 309cd82..1449550 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -1127,8 +1127,8 @@
// invalid Channel ID signature.
InvalidChannelIDSignature bool
- // ExpectGREASE, if true, causes the server to reject a ClientHello
- // unless it contains GREASE values. See draft-davidben-tls-grease-01.
+ // ExpectGREASE, if true, causes messages without GREASE values to be
+ // rejected. See draft-davidben-tls-grease-01.
ExpectGREASE bool
}
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 84e1eb8..7f395d5 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -1398,6 +1398,10 @@
if c.isClient {
if newSessionTicket, ok := msg.(*newSessionTicketMsg); ok {
+ if c.config.Bugs.ExpectGREASE && !newSessionTicket.hasGREASEExtension {
+ return errors.New("tls: no GREASE ticket extension found")
+ }
+
if c.config.ClientSessionCache == nil || newSessionTicket.ticketLifetime == 0 {
return nil
}
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 19578e8..9864b0a 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -1819,12 +1819,13 @@
}
type newSessionTicketMsg struct {
- raw []byte
- version uint16
- ticketLifetime uint32
- keModes []byte
- authModes []byte
- ticket []byte
+ raw []byte
+ version uint16
+ ticketLifetime uint32
+ keModes []byte
+ authModes []byte
+ ticket []byte
+ hasGREASEExtension bool
}
func (m *newSessionTicketMsg) marshal() []byte {
@@ -1913,7 +1914,24 @@
if len(data) < extsLength {
return false
}
+ extensions := data[:extsLength]
data = data[extsLength:]
+
+ for len(extensions) > 0 {
+ if len(extensions) < 4 {
+ return false
+ }
+ extValue := uint16(extensions[0])<<8 | uint16(extensions[1])
+ extLength := int(extensions[2])<<8 | int(extensions[3])
+ if len(extensions) < 4+extLength {
+ return false
+ }
+ extensions = extensions[4+extLength:]
+
+ if isGREASEValue(extValue) {
+ m.hasGREASEExtension = true
+ }
+ }
}
if len(data) > 0 {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 248c6eb..a7fd154 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -2263,7 +2263,7 @@
expectedLocalError: "remote error: illegal parameter",
},
{
- name: "GREASE-TLS12",
+ name: "GREASE-Client-TLS12",
config: Config{
MaxVersion: VersionTLS12,
Bugs: ProtocolBugs{
@@ -2273,7 +2273,18 @@
flags: []string{"-enable-grease"},
},
{
- name: "GREASE-TLS13",
+ name: "GREASE-Client-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectGREASE: true,
+ },
+ },
+ flags: []string{"-enable-grease"},
+ },
+ {
+ testType: serverTest,
+ name: "GREASE-Server-TLS13",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index 984cc5c..7332347 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -541,7 +541,7 @@
/* TODO(svaldez): Add support for sending 0RTT through TicketEarlyDataInfo
* extension. */
- CBB cbb, body, ke_modes, auth_modes, ticket;
+ CBB cbb, body, ke_modes, auth_modes, ticket, extensions;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_NEW_SESSION_TICKET) ||
!CBB_add_u32(&body, session->tlsext_tick_lifetime_hint) ||
@@ -551,16 +551,31 @@
!CBB_add_u8(&auth_modes, SSL_PSK_AUTH) ||
!CBB_add_u16_length_prefixed(&body, &ticket) ||
!ssl_encrypt_ticket(ssl, &ticket, session) ||
- !CBB_add_u16(&body, 0 /* no ticket extensions */) ||
- !ssl->method->finish_message(ssl, &cbb)) {
- CBB_cleanup(&cbb);
- return ssl_hs_error;
+ !CBB_add_u16_length_prefixed(&body, &extensions)) {
+ goto err;
+ }
+
+ /* Add a fake extension. See draft-davidben-tls-grease-01. */
+ if (ssl->ctx->grease_enabled) {
+ if (!CBB_add_u16(&extensions,
+ ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
+ !CBB_add_u16(&extensions, 0 /* empty */)) {
+ goto err;
+ }
+ }
+
+ if (!ssl->method->finish_message(ssl, &cbb)) {
+ goto err;
}
hs->session_tickets_sent++;
hs->state = state_flush_new_session_ticket;
return ssl_hs_write_message;
+
+err:
+ CBB_cleanup(&cbb);
+ return ssl_hs_error;
}
/* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the