Negotiate the cipher suite before ALPN.

HTTP/2 places requirements on the cipher suite. So that servers can
decline HTTP/2 when these requirements aren't met, defer ALPN
negotiation.

See also b/32553041.

Change-Id: Idbcf049f9c8bda06a8be52a0154fe76e84607268
Reviewed-on: https://boringssl-review.googlesource.com/11982
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index d0f4fec..417b194 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2389,7 +2389,10 @@
  * |*out_len| to the selected protocol and return |SSL_TLSEXT_ERR_OK| on
  * success. It does not pass ownership of the buffer. Otherwise, it should
  * return |SSL_TLSEXT_ERR_NOACK|. Other |SSL_TLSEXT_ERR_*| values are
- * unimplemented and will be treated as |SSL_TLSEXT_ERR_NOACK|. */
+ * unimplemented and will be treated as |SSL_TLSEXT_ERR_NOACK|.
+ *
+ * The cipher suite is selected before negotiating ALPN. The callback may use
+ * |SSL_get_pending_cipher| to query the cipher suite. */
 OPENSSL_EXPORT void SSL_CTX_set_alpn_select_cb(
     SSL_CTX *ctx, int (*cb)(SSL *ssl, const uint8_t **out, uint8_t *out_len,
                             const uint8_t *in, unsigned in_len, void *arg),
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index 9200b85..d17e659 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -556,7 +556,7 @@
 }
 
 static int negotiate_version(
-    SSL *ssl, int *out_alert,
+    SSL *ssl, uint8_t *out_alert,
     const struct ssl_early_callback_ctx *client_hello) {
   uint16_t min_version, max_version;
   if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
@@ -665,7 +665,8 @@
 }
 
 static int ssl3_get_client_hello(SSL *ssl) {
-  int al = SSL_AD_INTERNAL_ERROR, ret = -1;
+  uint8_t al = SSL_AD_INTERNAL_ERROR;
+  int ret = -1;
   SSL_SESSION *session = NULL;
 
   if (ssl->state == SSL3_ST_SR_CLNT_HELLO_A) {
@@ -887,6 +888,12 @@
     }
   }
 
+  /* Resolve ALPN after the cipher suite is selected. HTTP/2 negotiation depends
+   * on the cipher suite. */
+  if (!ssl_negotiate_alpn(ssl, &al, &client_hello)) {
+    goto f_err;
+  }
+
   /* Now that the cipher is known, initialize the handshake hash. */
   if (!ssl3_init_handshake_hash(ssl)) {
     goto f_err;
diff --git a/ssl/internal.h b/ssl/internal.h
index b6f0203..461de2c 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1083,6 +1083,12 @@
     SSL *ssl, uint8_t **out, size_t *out_len,
     enum ssl_cert_verify_context_t cert_verify_context);
 
+/* ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
+ * one on successful negotiation or if nothing was negotiated. It returns zero
+ * and sets |*out_alert| to an alert on error. */
+int ssl_negotiate_alpn(SSL *ssl, uint8_t *out_alert,
+                       const struct ssl_early_callback_ctx *client_hello);
+
 
 /* SSLKEYLOGFILE functions. */
 
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index ab1a599..eb60550 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -2347,6 +2347,64 @@
   return true;
 }
 
+// Tests that that |SSL_get_pending_cipher| is available during the ALPN
+// selection callback.
+static bool TestALPNCipherAvailable() {
+  static const uint8_t kALPNProtos[] = {0x03, 'f', 'o', 'o'};
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  for (uint16_t version : kTLSVersions) {
+    // SSL 3.0 lacks extensions.
+    if (version == SSL3_VERSION) {
+      continue;
+    }
+
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+    if (!ctx ||
+        !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+        !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+        !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+        !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+        SSL_CTX_set_alpn_protos(ctx.get(), kALPNProtos, sizeof(kALPNProtos)) !=
+            0) {
+      return false;
+    }
+
+    // The ALPN callback does not fail the handshake on error, so have the
+    // callback write a boolean.
+    bool pending_cipher_known = false;
+    SSL_CTX_set_alpn_select_cb(
+        ctx.get(),
+        [](SSL *ssl, const uint8_t **out, uint8_t *out_len, const uint8_t *in,
+           unsigned in_len, void *arg) -> int {
+          bool *result = reinterpret_cast<bool *>(arg);
+          *result = SSL_get_pending_cipher(ssl) != nullptr;
+          return SSL_TLSEXT_ERR_NOACK;
+        },
+        &pending_cipher_known);
+
+    bssl::UniquePtr<SSL> client, server;
+    if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                                nullptr /* no session */)) {
+      return false;
+    }
+
+    if (!pending_cipher_known) {
+      fprintf(stderr,
+              "%x: The pending cipher was not known in the ALPN callback.\n",
+              version);
+      return false;
+    }
+  }
+
+  return true;
+}
+
 int main() {
   CRYPTO_library_init();
 
@@ -2384,7 +2442,8 @@
       !TestSNICallback() ||
       !TestEarlyCallbackVersionSwitch() ||
       !TestSetVersion() ||
-      !TestVersions()) {
+      !TestVersions() ||
+      !TestALPNCipherAvailable()) {
     ERR_print_errors_fp(stderr);
     return 1;
   }
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index fffde09..fbc723b 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1342,10 +1342,6 @@
 
   if (contents == NULL ||
       ssl->s3->initial_handshake_complete ||
-      /* If the ALPN extension is seen before NPN, ignore it. (If ALPN is seen
-       * afterwards, parsing the ALPN extension will clear
-       * |next_proto_neg_seen|. */
-      ssl->s3->alpn_selected != NULL ||
       ssl->ctx->next_protos_advertised_cb == NULL ||
       SSL_is_dtls(ssl)) {
     return 1;
@@ -1545,14 +1541,14 @@
   return 1;
 }
 
-static int ext_alpn_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                      CBS *contents) {
-  if (contents == NULL) {
-    return 1;
-  }
-
+int ssl_negotiate_alpn(SSL *ssl, uint8_t *out_alert,
+                       const struct ssl_early_callback_ctx *client_hello) {
+  CBS contents;
   if (ssl->ctx->alpn_select_cb == NULL ||
-      ssl->s3->initial_handshake_complete) {
+      !ssl_early_callback_get_extension(
+          client_hello, &contents,
+          TLSEXT_TYPE_application_layer_protocol_negotiation)) {
+    /* Ignore ALPN if not configured or no extension was supplied. */
     return 1;
   }
 
@@ -1560,9 +1556,11 @@
   ssl->s3->hs->next_proto_neg_seen = 0;
 
   CBS protocol_name_list;
-  if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) ||
-      CBS_len(contents) != 0 ||
+  if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) ||
+      CBS_len(&contents) != 0 ||
       CBS_len(&protocol_name_list) < 2) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+    *out_alert = SSL_AD_DECODE_ERROR;
     return 0;
   }
 
@@ -1574,6 +1572,8 @@
     if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name) ||
         /* Empty protocol names are forbidden. */
         CBS_len(&protocol_name) == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+      *out_alert = SSL_AD_DECODE_ERROR;
       return 0;
     }
   }
@@ -2461,7 +2461,8 @@
     ext_alpn_init,
     ext_alpn_add_clienthello,
     ext_alpn_parse_serverhello,
-    ext_alpn_parse_clienthello,
+    /* ALPN is negotiated late in |ssl_negotiate_alpn|. */
+    ignore_parse_clienthello,
     ext_alpn_add_serverhello,
   },
   {
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index 2280a2b..574e6dd 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -211,6 +211,13 @@
   ssl->s3->tmp.new_cipher = ssl->s3->new_session->cipher;
   ssl->method->received_flight(ssl);
 
+  /* Resolve ALPN after the cipher suite is selected. HTTP/2 negotiation depends
+   * on the cipher suite. */
+  uint8_t alert;
+  if (!ssl_negotiate_alpn(ssl, &alert, &client_hello)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return ssl_hs_error;
+  }
 
   /* The PRF hash is now known. */
   size_t hash_len =