Convert the signature algorithms extension to the new system

Change-Id: Ia53b434acd11e9d2b0151b967387d86745ae441f
Reviewed-on: https://boringssl-review.googlesource.com/5362
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index 96daf20..8de63f6 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -84,6 +84,8 @@
 SSL,function,165,dtls1_write_app_data
 SSL,function,285,ext_ri_parse_clienthello
 SSL,function,286,ext_ri_parse_serverhello
+SSL,function,287,ext_sigalgs_parse_clienthello
+SSL,function,288,ext_sigalgs_parse_serverhello
 SSL,function,166,i2d_SSL_SESSION
 SSL,function,167,ssl3_accept
 SSL,function,169,ssl3_cert_verify_hash
@@ -309,6 +311,7 @@
 SSL,reason,218,SESSION_ID_CONTEXT_UNINITIALIZED
 SSL,reason,219,SESSION_MAY_NOT_BE_CREATED
 SSL,reason,220,SIGNATURE_ALGORITHMS_ERROR
+SSL,reason,280,SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER
 SSL,reason,221,SRTP_COULD_NOT_ALLOCATE_PROFILES
 SSL,reason,222,SRTP_PROTECTION_PROFILE_LIST_TOO_LONG
 SSL,reason,223,SRTP_UNKNOWN_PROTECTION_PROFILE
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 72d268a..b9e51e3 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2958,6 +2958,8 @@
 #define SSL_F_SSL_CTX_set_tlsext_ticket_keys 284
 #define SSL_F_ext_ri_parse_clienthello 285
 #define SSL_F_ext_ri_parse_serverhello 286
+#define SSL_F_ext_sigalgs_parse_clienthello 287
+#define SSL_F_ext_sigalgs_parse_serverhello 288
 #define SSL_R_APP_DATA_IN_HANDSHAKE 100
 #define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 101
 #define SSL_R_BAD_ALERT 102
@@ -3138,6 +3140,7 @@
 #define SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION 277
 #define SSL_R_TOO_MANY_WARNING_ALERTS 278
 #define SSL_R_UNEXPECTED_EXTENSION 279
+#define SSL_R_SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER 280
 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index f857bc9..d44205e 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1265,6 +1265,89 @@
 }
 
 
+/* Signature Algorithms.
+ *
+ * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
+
+static int ext_sigalgs_add_clienthello(SSL *ssl, CBB *out) {
+  if (ssl3_version_from_wire(ssl, ssl->client_version) < TLS1_2_VERSION) {
+    return 1;
+  }
+
+  const uint8_t *sigalgs_data;
+  const size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs_data);
+
+  CBB contents, sigalgs;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &sigalgs) ||
+      !CBB_add_bytes(&sigalgs, sigalgs_data, sigalgs_len) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ext_sigalgs_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+                                         CBS *contents) {
+  if (contents != NULL) {
+    /* Servers MUST NOT send this extension. */
+    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+    OPENSSL_PUT_ERROR(SSL, ext_sigalgs_parse_serverhello,
+                      SSL_R_SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER);
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ext_sigalgs_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+                                         CBS *contents) {
+  OPENSSL_free(ssl->cert->peer_sigalgs);
+  ssl->cert->peer_sigalgs = NULL;
+  ssl->cert->peer_sigalgslen = 0;
+
+  OPENSSL_free(ssl->cert->shared_sigalgs);
+  ssl->cert->shared_sigalgs = NULL;
+  ssl->cert->shared_sigalgslen = 0;
+
+  if (contents == NULL) {
+    return 1;
+  }
+
+  CBS supported_signature_algorithms;
+  if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
+      CBS_len(contents) != 0) {
+    return 0;
+  }
+
+  /* Ensure the signature algorithms are non-empty. It contains a list of
+   * SignatureAndHashAlgorithms which are two bytes each. */
+  if (CBS_len(&supported_signature_algorithms) == 0 ||
+      (CBS_len(&supported_signature_algorithms) % 2) != 0 ||
+      !tls1_process_sigalgs(ssl, &supported_signature_algorithms)) {
+    return 0;
+  }
+
+  /* It's a fatal error if the signature_algorithms extension is received and
+   * there are no shared algorithms. */
+  if (ssl->cert->peer_sigalgs && !ssl->cert->shared_sigalgs) {
+    OPENSSL_PUT_ERROR(SSL, ext_sigalgs_parse_clienthello,
+                      SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ext_sigalgs_add_serverhello(SSL *ssl, CBB *out) {
+  /* Servers MUST NOT send this extension. */
+  return 1;
+}
+
+
 /* kExtensions contains all the supported extensions. */
 static const struct tls_extension kExtensions[] = {
   {
@@ -1302,6 +1385,14 @@
     ext_ticket_parse_clienthello,
     ext_ticket_add_serverhello,
   },
+  {
+    TLSEXT_TYPE_signature_algorithms,
+    NULL,
+    ext_sigalgs_add_clienthello,
+    ext_sigalgs_parse_serverhello,
+    ext_sigalgs_parse_clienthello,
+    ext_sigalgs_add_serverhello,
+  },
 };
 
 #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
@@ -1398,20 +1489,6 @@
   ret += CBB_len(&cbb);
   CBB_cleanup(&cbb);
 
-  if (ssl3_version_from_wire(s, s->client_version) >= TLS1_2_VERSION) {
-    size_t salglen;
-    const uint8_t *salg;
-    salglen = tls12_get_psigalgs(s, &salg);
-    if ((size_t)(limit - ret) < salglen + 6) {
-      return NULL;
-    }
-    s2n(TLSEXT_TYPE_signature_algorithms, ret);
-    s2n(salglen + 2, ret);
-    s2n(salglen, ret);
-    memcpy(ret, salg, salglen);
-    ret += salglen;
-  }
-
   if (s->ocsp_stapling_enabled) {
     /* The status_request extension is excessively extensible at every layer.
      * On the client, only support requesting OCSP responses with an empty
@@ -1819,16 +1896,6 @@
   OPENSSL_free(s->s3->alpn_selected);
   s->s3->alpn_selected = NULL;
 
-  /* Clear any signature algorithms extension received */
-  OPENSSL_free(s->cert->peer_sigalgs);
-  s->cert->peer_sigalgs = NULL;
-  s->cert->peer_sigalgslen = 0;
-
-  /* Clear any shared signature algorithms */
-  OPENSSL_free(s->cert->shared_sigalgs);
-  s->cert->shared_sigalgs = NULL;
-  s->cert->shared_sigalgslen = 0;
-
   /* Clear ECC extensions */
   OPENSSL_free(s->s3->tmp.peer_ecpointformatlist);
   s->s3->tmp.peer_ecpointformatlist = NULL;
@@ -1941,35 +2008,6 @@
       }
 
       s->s3->tmp.peer_ellipticcurvelist_length = num_curves;
-    } else if (type == TLSEXT_TYPE_signature_algorithms) {
-      CBS supported_signature_algorithms;
-
-      if (!CBS_get_u16_length_prefixed(&extension,
-                                       &supported_signature_algorithms) ||
-          CBS_len(&extension) != 0) {
-        *out_alert = SSL_AD_DECODE_ERROR;
-        return 0;
-      }
-
-      /* Ensure the signature algorithms are non-empty. It contains a list of
-       * SignatureAndHashAlgorithms which are two bytes each. */
-      if (CBS_len(&supported_signature_algorithms) == 0 ||
-          (CBS_len(&supported_signature_algorithms) % 2) != 0) {
-        *out_alert = SSL_AD_DECODE_ERROR;
-        return 0;
-      }
-
-      if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) {
-        *out_alert = SSL_AD_DECODE_ERROR;
-        return 0;
-      }
-      /* If sigalgs received and no shared algorithms fatal error. */
-      if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs) {
-        OPENSSL_PUT_ERROR(SSL, ssl_scan_clienthello_tlsext,
-                          SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
-        *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-        return 0;
-      }
     } else if (type == TLSEXT_TYPE_next_proto_neg &&
                !s->s3->initial_handshake_complete &&
                s->s3->alpn_selected == NULL && !SSL_IS_DTLS(s)) {