Don't use |X509_get_pubkey| in TLS 1.3 code either.

Change-Id: I7050c74ac38503f450760a857442e6fc0863d5df
Reviewed-on: https://boringssl-review.googlesource.com/12708
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/internal.h b/ssl/internal.h
index 76e37b4..43aeaad 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1067,8 +1067,8 @@
  * it returns one. Otherwise, it sends an alert and returns zero. */
 int tls13_check_message_type(SSL *ssl, int type);
 
-int tls13_process_certificate(SSL *ssl, int allow_anonymous);
-int tls13_process_certificate_verify(SSL *ssl);
+int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous);
+int tls13_process_certificate_verify(SSL_HANDSHAKE *hs);
 int tls13_process_finished(SSL_HANDSHAKE *hs);
 
 int tls13_prepare_certificate(SSL_HANDSHAKE *hs);
diff --git a/ssl/tls13_both.c b/ssl/tls13_both.c
index 25dc852..1be1897 100644
--- a/ssl/tls13_both.c
+++ b/ssl/tls13_both.c
@@ -163,7 +163,8 @@
   return 0;
 }
 
-int tls13_process_certificate(SSL *ssl, int allow_anonymous) {
+int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
+  SSL *const ssl = hs->ssl;
   CBS cbs, context, certificate_list;
   CBS_init(&cbs, ssl->init_msg, ssl->init_num);
   if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
@@ -177,6 +178,7 @@
       ssl->server && ssl->retain_only_sha256_of_client_certs;
   int ret = 0;
 
+  EVP_PKEY *pkey = NULL;
   STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null();
   if (certs == NULL) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
@@ -200,10 +202,19 @@
       goto err;
     }
 
-    /* Retain the hash of the leaf certificate if requested. */
-    if (sk_CRYPTO_BUFFER_num(certs) == 0 && retain_sha256) {
-      SHA256(CBS_data(&certificate), CBS_len(&certificate),
-             ssl->s3->new_session->peer_sha256);
+    if (sk_CRYPTO_BUFFER_num(certs) == 0) {
+      pkey = ssl_cert_parse_pubkey(&certificate);
+      if (pkey == NULL) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        goto err;
+      }
+
+      if (retain_sha256) {
+        /* Retain the hash of the leaf certificate if requested. */
+        SHA256(CBS_data(&certificate), CBS_len(&certificate),
+               ssl->s3->new_session->peer_sha256);
+      }
     }
 
     CRYPTO_BUFFER *buf =
@@ -289,6 +300,10 @@
     goto err;
   }
 
+  EVP_PKEY_free(hs->peer_pubkey);
+  hs->peer_pubkey = pkey;
+  pkey = NULL;
+
   sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
   ssl->s3->new_session->certs = certs;
   certs = NULL;
@@ -326,19 +341,17 @@
 
 err:
   sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free);
+  EVP_PKEY_free(pkey);
   return ret;
 }
 
-int tls13_process_certificate_verify(SSL *ssl) {
+int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret = 0;
-  X509 *peer = ssl->s3->new_session->x509_peer;
-  EVP_PKEY *pkey = NULL;
   uint8_t *msg = NULL;
   size_t msg_len;
 
-  /* Filter out unsupported certificate types. */
-  pkey = X509_get_pubkey(peer);
-  if (pkey == NULL) {
+  if (hs->peer_pubkey == NULL) {
     goto err;
   }
 
@@ -369,7 +382,7 @@
 
   int sig_ok =
       ssl_public_key_verify(ssl, CBS_data(&signature), CBS_len(&signature),
-                            signature_algorithm, pkey, msg, msg_len);
+                            signature_algorithm, hs->peer_pubkey, msg, msg_len);
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
   sig_ok = 1;
   ERR_clear_error();
@@ -383,7 +396,6 @@
   ret = 1;
 
 err:
-  EVP_PKEY_free(pkey);
   OPENSSL_free(msg);
   return ret;
 }
diff --git a/ssl/tls13_client.c b/ssl/tls13_client.c
index f106c16..4a202d7 100644
--- a/ssl/tls13_client.c
+++ b/ssl/tls13_client.c
@@ -404,7 +404,7 @@
 static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
-      !tls13_process_certificate(ssl, 0 /* certificate required */) ||
+      !tls13_process_certificate(hs, 0 /* certificate required */) ||
       !ssl_hash_current_message(ssl)) {
     return ssl_hs_error;
   }
@@ -417,7 +417,7 @@
     SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
   if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
-      !tls13_process_certificate_verify(ssl) ||
+      !tls13_process_certificate_verify(hs) ||
       !ssl_hash_current_message(ssl)) {
     return ssl_hs_error;
   }
diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c
index 367ea5a..1aca634 100644
--- a/ssl/tls13_server.c
+++ b/ssl/tls13_server.c
@@ -547,7 +547,7 @@
       (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
 
   if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
-      !tls13_process_certificate(ssl, allow_anonymous) ||
+      !tls13_process_certificate(hs, allow_anonymous) ||
       !ssl_hash_current_message(ssl)) {
     return ssl_hs_error;
   }
@@ -566,7 +566,7 @@
   }
 
   if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
-      !tls13_process_certificate_verify(ssl) ||
+      !tls13_process_certificate_verify(hs) ||
       !ssl_hash_current_message(ssl)) {
     return ssl_hs_error;
   }