Implement draft 16 HelloRetryRequest and cookie.

We'll never send cookies, but we'll echo them on request. Implement it
in runner as well and test.

BUG=98

Change-Id: Idd3799f1eaccd52ac42f5e2e5ae07c209318c270
Reviewed-on: https://boringssl-review.googlesource.com/11565
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 7031145..c9f5bbf 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2030,8 +2030,8 @@
   }
 
   uint16_t group_id;
-  if (ssl->s3->hs->retry_group) {
-    /* Append the new key share to the old list. */
+  if (ssl->s3->hs->received_hello_retry_request) {
+    /* Replay the old key shares. */
     if (!CBB_add_bytes(&kse_bytes, ssl->s3->hs->key_share_bytes,
                        ssl->s3->hs->key_share_bytes_len)) {
       return 0;
@@ -2041,6 +2041,12 @@
     ssl->s3->hs->key_share_bytes_len = 0;
 
     group_id = ssl->s3->hs->retry_group;
+
+    /* We received a HelloRetryRequest without a new curve, so there is no new
+     * share to append. Leave |ecdh_ctx| as-is. */
+    if (group_id == 0) {
+      return CBB_flush(out);
+    }
   } else {
     /* Add a fake group. See draft-davidben-tls-grease-01. */
     if (ssl->ctx->grease_enabled &&
@@ -2072,7 +2078,7 @@
     return 0;
   }
 
-  if (!ssl->s3->hs->retry_group) {
+  if (!ssl->s3->hs->received_hello_retry_request) {
     /* Save the contents of the extension to repeat it in the second
      * ClientHello. */
     ssl->s3->hs->key_share_bytes_len = CBB_len(&kse_bytes);
@@ -2258,6 +2264,32 @@
 }
 
 
+/* Cookie
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.2 */
+
+static int ext_cookie_add_clienthello(SSL *ssl, CBB *out) {
+  if (ssl->s3->hs->cookie == NULL) {
+    return 1;
+  }
+
+  CBB contents, cookie;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_cookie) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &cookie) ||
+      !CBB_add_bytes(&cookie, ssl->s3->hs->cookie, ssl->s3->hs->cookie_len) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  /* The cookie is no longer needed in memory. */
+  OPENSSL_free(ssl->s3->hs->cookie);
+  ssl->s3->hs->cookie = NULL;
+  ssl->s3->hs->cookie_len = 0;
+  return 1;
+}
+
+
 /* Negotiated Groups
  *
  * https://tools.ietf.org/html/rfc4492#section-5.1.2
@@ -2472,6 +2504,14 @@
     ignore_parse_clienthello,
     dont_add_serverhello,
   },
+  {
+    TLSEXT_TYPE_cookie,
+    NULL,
+    ext_cookie_add_clienthello,
+    forbid_parse_serverhello,
+    ignore_parse_clienthello,
+    dont_add_serverhello,
+  },
   /* The final extension must be non-empty. WebSphere Application Server 7.0 is
    * intolerant to the last extension being zero-length. See
    * https://crbug.com/363583. */