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