Enforce the server ALPN protocol was advertised.

The server should not be allowed select a protocol that wasn't
advertised. Callers tend to not really notice and act as if some default
were chosen which is unlikely to work very well.

Change-Id: Ib6388db72f05386f854d275bab762ca79e8174e6
Reviewed-on: https://boringssl-review.googlesource.com/10284
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/t1_lib.c b/ssl/t1_lib.c
index 62f3824..5e790a4 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1517,6 +1517,32 @@
     return 0;
   }
 
+  /* Check that the protcol name is one of the ones we advertised. */
+  int protocol_ok = 0;
+  CBS client_protocol_name_list, client_protocol_name;
+  CBS_init(&client_protocol_name_list, ssl->alpn_client_proto_list,
+           ssl->alpn_client_proto_list_len);
+  while (CBS_len(&client_protocol_name_list) > 0) {
+    if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
+                                    &client_protocol_name)) {
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      return 0;
+    }
+
+    if (CBS_len(&client_protocol_name) == CBS_len(&protocol_name) &&
+        memcmp(CBS_data(&client_protocol_name), CBS_data(&protocol_name),
+               CBS_len(&protocol_name)) == 0) {
+      protocol_ok = 1;
+      break;
+    }
+  }
+
+  if (!protocol_ok) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
   if (!CBS_stow(&protocol_name, &ssl->s3->alpn_selected,
                 &ssl->s3->alpn_selected_len)) {
     *out_alert = SSL_AD_INTERNAL_ERROR;