Changing representation of signature/hash to use SignatureScheme.

As part of the SignatureAlgorithm change in the TLS 1.3 specification,
the existing signature/hash combinations are replaced with a combined
signature algorithm identifier. This change maintains the existing APIs
while fixing the internal representations. The signing code currently
still treats the SignatureAlgorithm as a decomposed value, which will be
fixed as part of a separate CL.

Change-Id: I0cd1660d74ad9bcf55ce5da4449bf2922660be36
Reviewed-on: https://boringssl-review.googlesource.com/8480
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 6ce9412..797da38 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2958,10 +2958,9 @@
  * respectively. */
 OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl);
 
-/* SSL_get_server_key_exchange_hash, on a client, returns the hash the server
- * used to sign the ServerKeyExchange in TLS 1.2. If not applicable, it returns
- * |TLSEXT_hash_none|. */
-OPENSSL_EXPORT uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl);
+/* SSL_get_peer_signature_algorithm returns the signature algorithm used by the
+ * peer. If not applicable, it returns zero. */
+OPENSSL_EXPORT uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl);
 
 /* TODO(davidben): Remove this when wpa_supplicant in Android has synced with
  * upstream. */
@@ -3193,6 +3192,14 @@
 OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,
                                                const char *profiles);
 
+/* SSL_get_server_key_exchange_hash, on a client, returns the hash the server
+ * used to sign the ServerKeyExchange in TLS 1.2. If not applicable, it returns
+ * |TLSEXT_hash_none|.
+ *
+ * TODO(davidben): Remove once Chromium switches to
+ * |SSL_get_peer_signature_algorithm|. */
+OPENSSL_EXPORT uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl);
+
 /* SSL_set_tlsext_use_srtp calls |SSL_set_srtp_profiles|. It returns zero on
  * success and one on failure.
  *
@@ -4248,10 +4255,9 @@
      * False Start. The client may write data at this point. */
     char in_false_start;
 
-    /* server_key_exchange_hash, on a client, is the hash the server used to
-     * sign the ServerKeyExchange in TLS 1.2. If not applicable, it is
-     * |TLSEXT_hash_none|. */
-    uint8_t server_key_exchange_hash;
+    /* peer_signature_algorithm is the signature algorithm used to authenticate
+     * the peer, or zero if not applicable. */
+    uint16_t peer_signature_algorithm;
 
     /* ecdh_ctx is the current ECDH instance. */
     SSL_ECDH_CTX ecdh_ctx;
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 973ea1c..7dbc394 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -261,6 +261,16 @@
 #define TLSEXT_hash_sha384 5
 #define TLSEXT_hash_sha512 6
 
+#define SSL_SIGN_RSA_PKCS1_SHA1         0x0201
+#define SSL_SIGN_RSA_PKCS1_SHA256       0x0401
+#define SSL_SIGN_RSA_PKCS1_SHA384       0x0501
+#define SSL_SIGN_RSA_PKCS1_SHA512       0x0601
+#define SSL_SIGN_ECDSA_SHA1             0x0203
+#define SSL_SIGN_ECDSA_SECP256R1_SHA256 0x0403
+#define SSL_SIGN_ECDSA_SECP384R1_SHA384 0x0503
+#define SSL_SIGN_ECDSA_SECP521R1_SHA512 0x0603
+
+
 /* Flag set for unrecognised algorithms */
 #define TLSEXT_nid_unknown 0x1000000
 
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index e5c6e2f..09f4d4f 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -1311,17 +1311,16 @@
 
     const EVP_MD *md = NULL;
     if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
-      uint8_t hash, signature;
-      if (!CBS_get_u8(&server_key_exchange, &hash) ||
-          !CBS_get_u8(&server_key_exchange, &signature)) {
+      uint16_t signature_algorithm;
+      if (!CBS_get_u16(&server_key_exchange, &signature_algorithm)) {
         al = SSL_AD_DECODE_ERROR;
         OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
         goto f_err;
       }
-      if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature, pkey)) {
+      if (!tls12_check_peer_sigalg(ssl, &md, &al, signature_algorithm, pkey)) {
         goto f_err;
       }
-      ssl->s3->tmp.server_key_exchange_hash = hash;
+      ssl->s3->tmp.peer_signature_algorithm = signature_algorithm;
     } else if (pkey->type == EVP_PKEY_RSA) {
       md = EVP_md5_sha1();
     } else {
@@ -1823,7 +1822,7 @@
   const EVP_MD *md = NULL;
   if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
     md = tls1_choose_signing_digest(ssl);
-    if (!tls12_add_sigandhash(ssl, &body, md)) {
+    if (!tls12_add_sigalg(ssl, &body, md)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       goto err;
     }
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index 128bb8d..0356735 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -1254,7 +1254,7 @@
     const EVP_MD *md;
     if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
       md = tls1_choose_signing_digest(ssl);
-      if (!tls12_add_sigandhash(ssl, &body, md)) {
+      if (!tls12_add_sigalg(ssl, &body, md)) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
         ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
         goto err;
@@ -1335,16 +1335,22 @@
   /* Get configured signature algorithms. */
   int have_rsa_sign = 0;
   int have_ecdsa_sign = 0;
-  const uint8_t *sig;
-  size_t siglen = tls12_get_psigalgs(ssl, &sig);
+  const uint16_t *sig_algs;
+  size_t sig_algs_len = tls12_get_psigalgs(ssl, &sig_algs);
   size_t i;
-  for (i = 0; i < siglen; i += 2, sig += 2) {
-    switch (sig[1]) {
-      case TLSEXT_signature_rsa:
+  for (i = 0; i < sig_algs_len; i++) {
+    switch (sig_algs[i]) {
+      case SSL_SIGN_RSA_PKCS1_SHA512:
+      case SSL_SIGN_RSA_PKCS1_SHA384:
+      case SSL_SIGN_RSA_PKCS1_SHA256:
+      case SSL_SIGN_RSA_PKCS1_SHA1:
         have_rsa_sign = 1;
         break;
 
-      case TLSEXT_signature_ecdsa:
+      case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+      case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+      case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+      case SSL_SIGN_ECDSA_SHA1:
         have_ecdsa_sign = 1;
         break;
     }
@@ -1378,12 +1384,18 @@
   }
 
   if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
-    const uint8_t *sigalgs;
+    const uint16_t *sigalgs;
     size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs);
-    if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
-        !CBB_add_bytes(&sigalgs_cbb, sigalgs, sigalgs_len)) {
+    if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
       goto err;
     }
+
+    size_t i;
+    for (i = 0; i < sigalgs_len; i++) {
+      if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
+        goto err;
+      }
+    }
   }
 
   STACK_OF(X509_NAME) *sk = SSL_get_client_CA_list(ssl);
@@ -1888,16 +1900,16 @@
 
   /* Determine the digest type if needbe. */
   if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
-    uint8_t hash, signature_type;
-    if (!CBS_get_u8(&certificate_verify, &hash) ||
-        !CBS_get_u8(&certificate_verify, &signature_type)) {
+    uint16_t signature_algorithm;
+    if (!CBS_get_u16(&certificate_verify, &signature_algorithm)) {
       al = SSL_AD_DECODE_ERROR;
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
       goto f_err;
     }
-    if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature_type, pkey)) {
+    if (!tls12_check_peer_sigalg(ssl, &md, &al, signature_algorithm, pkey)) {
       goto f_err;
     }
+    ssl->s3->tmp.peer_signature_algorithm = signature_algorithm;
   }
 
   /* Compute the digest. */
diff --git a/ssl/internal.h b/ssl/internal.h
index 4ecf6e0..fb8dd9d 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -747,12 +747,6 @@
   ssl_hash_message,
 };
 
-/* Structure containing decoded values of signature algorithms extension */
-typedef struct tls_sigalgs_st {
-  uint8_t rsign;
-  uint8_t rhash;
-} TLS_SIGALGS;
-
 typedef struct cert_st {
   X509 *x509;
   EVP_PKEY *privatekey;
@@ -777,7 +771,7 @@
   /* peer_sigalgs are the algorithm/hash pairs that the peer supports. These
    * are taken from the contents of signature algorithms extension for a server
    * or from the CertificateRequest for a client. */
-  TLS_SIGALGS *peer_sigalgs;
+  uint16_t *peer_sigalgs;
   /* peer_sigalgslen is the number of entries in |peer_sigalgs|. */
   size_t peer_sigalgslen;
 
@@ -1142,13 +1136,10 @@
                        size_t ticket_len, const uint8_t *session_id,
                        size_t session_id_len);
 
-/* tls12_add_sigandhash assembles the SignatureAndHashAlgorithm corresponding to
- * |ssl|'s private key and |md|. The two-byte value is written to |out|. It
- * returns one on success and zero on failure. */
-int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md);
-
-int tls12_get_sigid(int pkey_type);
-const EVP_MD *tls12_get_hash(uint8_t hash_alg);
+/* tls12_add_sigalg picks the SignatureScheme corresponding to |ssl|'s private
+ * key and |md| and writes it to |out|. It returns one on success and zero on
+ * failure. */
+int tls12_add_sigalg(SSL *ssl, CBB *out, const EVP_MD *md);
 
 /* tls1_channel_id_hash computes the hash to be signed by Channel ID and writes
  * it to |out|, which must contain at least |EVP_MAX_MD_SIZE| bytes. It returns
@@ -1220,14 +1211,14 @@
  * based on the peer's preferences the digests supported. */
 const EVP_MD *tls1_choose_signing_digest(SSL *ssl);
 
-size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs);
+size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs);
 
-/* tls12_check_peer_sigalg checks that |hash| and |signature| are consistent
- * with |pkey| and |ssl|'s sent, supported signature algorithms and, if so,
+/* tls12_check_peer_sigalg checks that |signature_algorithm| is consistent with
+ * the |pkey| and |ssl|'s sent, supported signature algorithms and, if so,
  * writes the relevant digest into |*out_md| and returns 1. Otherwise it
  * returns 0 and writes an alert into |*out_alert|. */
 int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert,
-                            uint8_t hash, uint8_t signature, EVP_PKEY *pkey);
+                            uint16_t signature_algorithm, EVP_PKEY *pkey);
 void ssl_set_client_disabled(SSL *ssl);
 
 #endif /* OPENSSL_HEADER_SSL_INTERNAL_H */
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a7070d1..ebac0f4 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2812,8 +2812,12 @@
   return ret;
 }
 
+uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl) {
+  return ssl->s3->tmp.peer_signature_algorithm;
+}
+
 uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl) {
-  return ssl->s3->tmp.server_key_exchange_hash;
+  return (uint8_t) (SSL_get_peer_signature_algorithm(ssl) >> 8);
 }
 
 size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, size_t max_out) {
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 16cac15..4f80865 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -498,39 +498,36 @@
 /* List of supported signature algorithms and hashes. Should make this
  * customisable at some point, for now include everything we support. */
 
-#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
+static const uint16_t kDefaultSignatureAlgorithms[] = {
+    SSL_SIGN_RSA_PKCS1_SHA512,
+    SSL_SIGN_ECDSA_SECP521R1_SHA512,
 
-#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
+    SSL_SIGN_RSA_PKCS1_SHA384,
+    SSL_SIGN_ECDSA_SECP384R1_SHA384,
 
-#define tlsext_sigalg(md) tlsext_sigalg_rsa(md) tlsext_sigalg_ecdsa(md)
+    SSL_SIGN_RSA_PKCS1_SHA256,
+    SSL_SIGN_ECDSA_SECP256R1_SHA256,
 
-static const uint8_t tls12_sigalgs[] = {
-    tlsext_sigalg(TLSEXT_hash_sha512)
-    tlsext_sigalg(TLSEXT_hash_sha384)
-    tlsext_sigalg(TLSEXT_hash_sha256)
-    tlsext_sigalg(TLSEXT_hash_sha1)
+    SSL_SIGN_RSA_PKCS1_SHA1,
+    SSL_SIGN_ECDSA_SHA1,
 };
 
-size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs) {
-  *psigs = tls12_sigalgs;
-  return sizeof(tls12_sigalgs);
+size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs) {
+  *psigs = kDefaultSignatureAlgorithms;
+  return sizeof(kDefaultSignatureAlgorithms) /
+         sizeof(kDefaultSignatureAlgorithms[0]);
 }
 
-int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert,
-                            uint8_t hash, uint8_t signature, EVP_PKEY *pkey) {
-  const uint8_t *sent_sigs;
-  size_t sent_sigslen, i;
-  int sigalg = tls12_get_sigid(pkey->type);
+static int tls12_get_pkey_type(uint16_t sig_alg);
+static const EVP_MD *tls12_get_hash(uint16_t sig_alg);
 
-  /* Should never happen */
-  if (sigalg == -1) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-    return 0;
-  }
+int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert,
+                            uint16_t signature_algorithm, EVP_PKEY *pkey) {
+  const uint16_t *sent_sigs;
+  size_t sent_sigslen, i;
 
   /* Check key type is consistent with signature */
-  if (sigalg != signature) {
+  if (pkey->type != tls12_get_pkey_type(signature_algorithm)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     return 0;
@@ -538,8 +535,8 @@
 
   /* Check signature matches a type we sent */
   sent_sigslen = tls12_get_psigalgs(ssl, &sent_sigs);
-  for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
-    if (hash == sent_sigs[0] && signature == sent_sigs[1]) {
+  for (i = 0; i < sent_sigslen; i++) {
+    if (signature_algorithm == sent_sigs[i]) {
       break;
     }
   }
@@ -550,7 +547,7 @@
     return 0;
   }
 
-  *out_md = tls12_get_hash(hash);
+  *out_md = tls12_get_hash(signature_algorithm);
   if (*out_md == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_DIGEST);
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
@@ -566,7 +563,7 @@
  * settings. */
 void ssl_set_client_disabled(SSL *ssl) {
   CERT *c = ssl->cert;
-  const uint8_t *sigalgs;
+  const uint16_t *sigalgs;
   size_t i, sigalgslen;
   int have_rsa = 0, have_ecdsa = 0;
   c->mask_a = 0;
@@ -575,13 +572,19 @@
   /* Now go through all signature algorithms seeing if we support any for RSA,
    * DSA, ECDSA. Do this for all versions not just TLS 1.2. */
   sigalgslen = tls12_get_psigalgs(ssl, &sigalgs);
-  for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
-    switch (sigalgs[1]) {
-      case TLSEXT_signature_rsa:
+  for (i = 0; i < sigalgslen; i++) {
+    switch (sigalgs[i]) {
+      case SSL_SIGN_RSA_PKCS1_SHA512:
+      case SSL_SIGN_RSA_PKCS1_SHA384:
+      case SSL_SIGN_RSA_PKCS1_SHA256:
+      case SSL_SIGN_RSA_PKCS1_SHA1:
         have_rsa = 1;
         break;
 
-      case TLSEXT_signature_ecdsa:
+      case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+      case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+      case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+      case SSL_SIGN_ECDSA_SHA1:
         have_ecdsa = 1;
         break;
     }
@@ -1043,15 +1046,24 @@
     return 1;
   }
 
-  const uint8_t *sigalgs_data;
+  const uint16_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)) {
+      !CBB_add_u16_length_prefixed(&contents, &sigalgs)) {
+    return 0;
+  }
+
+  size_t i;
+  for (i = 0; i < sigalgs_len; i++) {
+    if (!CBB_add_u16(&sigalgs, sigalgs_data[i])) {
+      return 0;
+    }
+  }
+
+  if (!CBB_flush(out)) {
     return 0;
   }
 
@@ -2516,51 +2528,44 @@
   return ret;
 }
 
-/* Tables to translate from NIDs to TLS v1.2 ids */
+/* Tables to translate from NIDs to TLS v1.2 ids
+ *
+ * TODO(svaldez): Remove decomposition of SignatureAlgorithm IDs. */
 typedef struct {
-  int nid;
-  int id;
+  int pkey_type;
+  int md_type;
+  uint16_t id;
 } tls12_lookup;
 
-static const tls12_lookup tls12_md[] = {
-    {NID_sha1, TLSEXT_hash_sha1},
-    {NID_sha256, TLSEXT_hash_sha256},
-    {NID_sha384, TLSEXT_hash_sha384},
-    {NID_sha512, TLSEXT_hash_sha512},
+static const tls12_lookup kTLS12SignatureAlgorithmIDs[] = {
+    {EVP_PKEY_RSA, NID_sha512, SSL_SIGN_RSA_PKCS1_SHA512},
+    {EVP_PKEY_EC, NID_sha512, SSL_SIGN_ECDSA_SECP521R1_SHA512},
+    {EVP_PKEY_RSA, NID_sha384, SSL_SIGN_RSA_PKCS1_SHA384},
+    {EVP_PKEY_EC, NID_sha384, SSL_SIGN_ECDSA_SECP384R1_SHA384},
+    {EVP_PKEY_RSA, NID_sha256, SSL_SIGN_RSA_PKCS1_SHA256},
+    {EVP_PKEY_EC, NID_sha256, SSL_SIGN_ECDSA_SECP256R1_SHA256},
+    {EVP_PKEY_RSA, NID_sha1, SSL_SIGN_RSA_PKCS1_SHA1},
+    {EVP_PKEY_EC, NID_sha1, SSL_SIGN_ECDSA_SHA1},
 };
 
-static const tls12_lookup tls12_sig[] = {{EVP_PKEY_RSA, TLSEXT_signature_rsa},
-                                         {EVP_PKEY_EC, TLSEXT_signature_ecdsa}};
+int tls12_add_sigalg(SSL *ssl, CBB *out, const EVP_MD *md) {
+  int pkey_type = ssl_private_key_type(ssl);
+  int md_type = EVP_MD_type(md);
 
-static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) {
   size_t i;
-  for (i = 0; i < tlen; i++) {
-    if (table[i].nid == nid) {
-      return table[i].id;
+  for (i = 0; i < sizeof(kTLS12SignatureAlgorithmIDs) / sizeof(tls12_lookup);
+       i++) {
+    if (kTLS12SignatureAlgorithmIDs[i].pkey_type == pkey_type &&
+        kTLS12SignatureAlgorithmIDs[i].md_type == md_type) {
+      return CBB_add_u16(out, kTLS12SignatureAlgorithmIDs[i].id);
     }
   }
 
-  return -1;
+  return 0;
 }
 
-int tls12_get_sigid(int pkey_type) {
-  return tls12_find_id(pkey_type, tls12_sig,
-                       sizeof(tls12_sig) / sizeof(tls12_lookup));
-}
-
-int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md) {
-  int md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
-                            sizeof(tls12_md) / sizeof(tls12_lookup));
-  int sig_id = tls12_get_sigid(ssl_private_key_type(ssl));
-
-  return md_id != -1 &&
-         sig_id != -1 &&
-         CBB_add_u8(out, (uint8_t)md_id) &&
-         CBB_add_u8(out, (uint8_t)sig_id);
-}
-
-const EVP_MD *tls12_get_hash(uint8_t hash_alg) {
-  switch (hash_alg) {
+static const EVP_MD *tls12_get_hash(uint16_t sig_alg) {
+  switch (sig_alg >> 8) {
     case TLSEXT_hash_sha1:
       return EVP_sha1();
 
@@ -2580,8 +2585,8 @@
 
 /* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature
  * algorithm |sig_alg|. It returns -1 if the type is unknown. */
-static int tls12_get_pkey_type(uint8_t sig_alg) {
-  switch (sig_alg) {
+static int tls12_get_pkey_type(uint16_t sig_alg) {
+  switch (sig_alg & 0xff) {
     case TLSEXT_signature_rsa:
       return EVP_PKEY_RSA;
 
@@ -2593,9 +2598,6 @@
   }
 }
 
-OPENSSL_COMPILE_ASSERT(sizeof(TLS_SIGALGS) == 2,
-    sizeof_tls_sigalgs_is_not_two);
-
 int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) {
   /* Extension ignored for inappropriate versions */
   if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
@@ -2620,9 +2622,9 @@
     return 1;
   }
 
-  /* This multiplication doesn't overflow because sizeof(TLS_SIGALGS) is two
-   * (statically asserted above) and we just divided |num_sigalgs| by two. */
-  cert->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(TLS_SIGALGS));
+  /* This multiplication doesn't overflow because sizeof(uint16_t) is two
+   * and we just divided |num_sigalgs| by two. */
+  cert->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(uint16_t));
   if (cert->peer_sigalgs == NULL) {
     return 0;
   }
@@ -2633,9 +2635,7 @@
 
   size_t i;
   for (i = 0; i < num_sigalgs; i++) {
-    TLS_SIGALGS *const sigalg = &cert->peer_sigalgs[i];
-    if (!CBS_get_u8(&sigalgs, &sigalg->rhash) ||
-        !CBS_get_u8(&sigalgs, &sigalg->rsign)) {
+    if (!CBS_get_u16(&sigalgs, &cert->peer_sigalgs[i])) {
       return 0;
     }
   }
@@ -2662,10 +2662,10 @@
   for (i = 0; i < num_digest_nids; i++) {
     const int digest_nid = digest_nids[i];
     for (j = 0; j < cert->peer_sigalgslen; j++) {
-      const EVP_MD *md = tls12_get_hash(cert->peer_sigalgs[j].rhash);
+      const EVP_MD *md = tls12_get_hash(cert->peer_sigalgs[j]);
       if (md == NULL ||
           digest_nid != EVP_MD_type(md) ||
-          tls12_get_pkey_type(cert->peer_sigalgs[j].rsign) != type) {
+          tls12_get_pkey_type(cert->peer_sigalgs[j]) != type) {
         continue;
       }