Don't use the client_random entropy for GREASE.

No sense in tempting middleboxes unnecessarily.

Change-Id: Iec66f77195f6b8aa62be681917342e59eb7aba31
Reviewed-on: https://boringssl-review.googlesource.com/24964
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/handshake.cc b/ssl/handshake.cc
index 3b446a8..cdd1b32 100644
--- a/ssl/handshake.cc
+++ b/ssl/handshake.cc
@@ -116,6 +116,8 @@
 
 #include <utility>
 
+#include <openssl/rand.h>
+
 #include "../crypto/internal.h"
 #include "internal.h"
 
@@ -143,7 +145,8 @@
       next_proto_neg_seen(false),
       ticket_expected(false),
       extended_master_secret(false),
-      pending_private_key_op(false) {
+      pending_private_key_op(false),
+      grease_seeded(false) {
 }
 
 SSL_HANDSHAKE::~SSL_HANDSHAKE() {
@@ -351,18 +354,19 @@
   return ret;
 }
 
-uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index) {
-  // Use the client_random or server_random for entropy. This both avoids
-  // calling |RAND_bytes| on a single byte repeatedly and ensures the values are
-  // deterministic. This allows the same ClientHello be sent twice for a
-  // HelloRetryRequest or the same group be advertised in both supported_groups
-  // and key_shares.
-  uint16_t ret = ssl->server ? ssl->s3->server_random[index]
-                             : ssl->s3->client_random[index];
-  // The first four bytes of server_random are a timestamp prior to TLS 1.3, but
-  // servers have no fields to GREASE until TLS 1.3.
-  assert(!ssl->server || ssl_protocol_version(ssl) >= TLS1_3_VERSION);
+uint16_t ssl_get_grease_value(SSL_HANDSHAKE *hs,
+                              enum ssl_grease_index_t index) {
+  // Draw entropy for all GREASE values at once. This avoids calling
+  // |RAND_bytes| repeatedly and makes the values consistent within a
+  // connection. The latter is so the second ClientHello matches after
+  // HelloRetryRequest and so supported_groups and key_shares are consistent.
+  if (!hs->grease_seeded) {
+    RAND_bytes(hs->grease_seed, sizeof(hs->grease_seed));
+    hs->grease_seeded = true;
+  }
+
   // 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;
   ret |= ret << 8;
   return ret;
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc
index 4e2158e..3961ca1 100644
--- a/ssl/handshake_client.cc
+++ b/ssl/handshake_client.cc
@@ -223,7 +223,7 @@
 
   // Add a fake cipher suite. See draft-davidben-tls-grease-01.
   if (ssl->ctx->grease_enabled &&
-      !CBB_add_u16(&child, ssl_get_grease_value(ssl, ssl_grease_cipher))) {
+      !CBB_add_u16(&child, ssl_get_grease_value(hs, ssl_grease_cipher))) {
     return 0;
   }
 
diff --git a/ssl/internal.h b/ssl/internal.h
index fb99101..d4f0e3f 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1281,6 +1281,16 @@
   ssl_hs_certificate_verify,
 };
 
+enum ssl_grease_index_t {
+  ssl_grease_cipher = 0,
+  ssl_grease_group,
+  ssl_grease_extension1,
+  ssl_grease_extension2,
+  ssl_grease_version,
+  ssl_grease_ticket_extension,
+  ssl_grease_last_index = ssl_grease_ticket_extension,
+};
+
 struct SSL_HANDSHAKE {
   explicit SSL_HANDSHAKE(SSL *ssl);
   ~SSL_HANDSHAKE();
@@ -1493,6 +1503,9 @@
   // in progress.
   bool pending_private_key_op:1;
 
+  // grease_seeded is true if |grease_seed| has been initialized.
+  bool grease_seeded:1;
+
   // client_version is the value sent or received in the ClientHello version.
   uint16_t client_version = 0;
 
@@ -1508,6 +1521,10 @@
   // TLS 1.3 variant.
   uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0};
   uint8_t session_id_len = 0;
+
+  // grease_seed is the entropy for GREASE values. It is valid if
+  // |grease_seeded| is true.
+  uint8_t grease_seed[ssl_grease_last_index + 1] = {0};
 };
 
 UniquePtr<SSL_HANDSHAKE> ssl_handshake_new(SSL *ssl);
@@ -1650,20 +1667,11 @@
 
 // GREASE.
 
-enum ssl_grease_index_t {
-  ssl_grease_cipher = 0,
-  ssl_grease_group,
-  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
+// ssl_get_grease_value returns a GREASE value for |hs|. For a given
 // connection, the values for each index will be deterministic. This allows the
 // same ClientHello be sent twice for a HelloRetryRequest or the same group be
 // advertised in both supported_groups and key_shares.
-uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index);
+uint16_t ssl_get_grease_value(SSL_HANDSHAKE *hs, enum ssl_grease_index_t index);
 
 
 // Signature algorithms.
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index dafb885..de02476 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -2115,7 +2115,7 @@
     // Add a fake group. See draft-davidben-tls-grease-01.
     if (ssl->ctx->grease_enabled &&
         (!CBB_add_u16(&kse_bytes,
-                      ssl_get_grease_value(ssl, ssl_grease_group)) ||
+                      ssl_get_grease_value(hs, ssl_grease_group)) ||
          !CBB_add_u16(&kse_bytes, 1 /* length */) ||
          !CBB_add_u8(&kse_bytes, 0 /* one byte key share */))) {
       return false;
@@ -2287,7 +2287,7 @@
 
   // Add a fake version. See draft-davidben-tls-grease-01.
   if (ssl->ctx->grease_enabled &&
-      !CBB_add_u16(&versions, ssl_get_grease_value(ssl, ssl_grease_version))) {
+      !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) {
     return false;
   }
 
@@ -2377,7 +2377,7 @@
   // Add a fake group. See draft-davidben-tls-grease-01.
   if (ssl->ctx->grease_enabled &&
       !CBB_add_u16(&groups_bytes,
-                   ssl_get_grease_value(ssl, ssl_grease_group))) {
+                   ssl_get_grease_value(hs, ssl_grease_group))) {
     return false;
   }
 
@@ -2813,7 +2813,7 @@
   uint16_t grease_ext1 = 0;
   if (ssl->ctx->grease_enabled) {
     // Add a fake empty extension. See draft-davidben-tls-grease-01.
-    grease_ext1 = ssl_get_grease_value(ssl, ssl_grease_extension1);
+    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);
@@ -2841,7 +2841,7 @@
 
   if (ssl->ctx->grease_enabled) {
     // Add a fake non-empty extension. See draft-davidben-tls-grease-01.
-    uint16_t grease_ext2 = ssl_get_grease_value(ssl, ssl_grease_extension2);
+    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
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index 331e0d5..a6a3a0a 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -211,7 +211,7 @@
 
     // Add a fake extension. See draft-davidben-tls-grease-01.
     if (!CBB_add_u16(&extensions,
-                     ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
+                     ssl_get_grease_value(hs, ssl_grease_ticket_extension)) ||
         !CBB_add_u16(&extensions, 0 /* empty */)) {
       return 0;
     }