Implement draft-davidben-tls-grease-01.

This GREASEs cipher suites, groups, and extensions. For now, we'll
always place them in a hard-coded position. We can experiment with more
interesting strategies later.

If we add new ciphers and curves, presumably we prefer them over current
ones, so place GREASE values at the front. This prevents implementations
from parsing only the first value and ignoring the rest.

Add two new extensions, one empty and one non-empty. Place the empty one
in front (IBM WebSphere can't handle trailing empty extensions) and the
non-empty one at the end.

Change-Id: If2e009936bc298cedf2a7a593ce7d5d5ddbb841a
Reviewed-on: https://boringssl-review.googlesource.com/11241
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index d78d0a4..584e9ea 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -579,6 +579,18 @@
   return ret;
 }
 
+uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index) {
+  /* Use the client_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->s3->client_random[index];
+  /* This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16. */
+  ret = (ret & 0xf0) | 0x0a;
+  ret |= ret << 8;
+  return ret;
+}
+
 static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
                                         uint16_t min_version,
                                         uint16_t max_version) {
@@ -590,6 +602,12 @@
     return 0;
   }
 
+  /* 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))) {
+    return 0;
+  }
+
   STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
 
   int any_enabled = 0;