Add the CA extension to client hello

If we have CA_names configured in the client,
make use of them and send the CA extension so
the client requests a cert with a matching
issuer.

Change-Id: I1f51a058b7a386915c198485915425727f15d002
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/71611
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
diff --git a/ssl/extensions.cc b/ssl/extensions.cc
index 0e001a6..c9424c9 100644
--- a/ssl/extensions.cc
+++ b/ssl/extensions.cc
@@ -2560,6 +2560,45 @@
 }
 
 
+// Certificate Authorities.
+//
+// https://tools.ietf.org/html/rfc8446#section-4.2.4
+
+static bool ext_certificate_authorities_add_clienthello(
+    const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible,
+    ssl_client_hello_type_t type) {
+  if (ssl_has_CA_names(hs->config)) {
+    CBB ca_contents;
+    if (!CBB_add_u16(out, TLSEXT_TYPE_certificate_authorities) || //
+        !CBB_add_u16_length_prefixed(out, &ca_contents) || //
+        !ssl_add_CA_names(hs, &ca_contents) || //
+        !CBB_flush(out)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static bool ext_certificate_authorities_parse_clienthello(SSL_HANDSHAKE *hs,
+                                                          uint8_t *out_alert,
+                                                          CBS *contents) {
+  if (contents == NULL) {
+    return true;
+  }
+
+  if (CBS_len(contents) == 0) {
+    return false;
+  }
+
+  hs->ca_names = SSL_parse_CA_list(hs->ssl, out_alert, contents);
+  if (!hs->ca_names) {
+    return false;
+  }
+
+  return true;
+}
+
+
 // QUIC Transport Parameters
 
 static bool ext_quic_transport_params_add_clienthello_impl(
@@ -3285,6 +3324,13 @@
     ignore_parse_clienthello,
     ext_alps_add_serverhello_old,
   },
+  {
+    TLSEXT_TYPE_certificate_authorities,
+    ext_certificate_authorities_add_clienthello,
+    forbid_parse_serverhello,
+    ext_certificate_authorities_parse_clienthello,
+    dont_add_serverhello,
+  },
 };
 
 #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
diff --git a/ssl/internal.h b/ssl/internal.h
index c34e9d9..a3b1ce0 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -2254,8 +2254,8 @@
   // server when using a TLS 1.2 PSK key exchange.
   UniquePtr<char> peer_psk_identity_hint;
 
-  // ca_names, on the client, contains the list of CAs received in a
-  // CertificateRequest message.
+  // ca_names contains the list of CAs received via the Certificate Authorities
+  // extension in our peer's CertificateRequest or ClientHello message
   UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names;
 
   // cached_x509_ca_names contains a cache of parsed versions of the elements of