Moving ssl_check_leaf_certificate to ssl_cert.

Change-Id: I9ec1a8c87e29ffd4fabef68beb6d094aa7d9a215
Reviewed-on: https://boringssl-review.googlesource.com/8795
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index 34681d3..09f8070 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -922,49 +922,6 @@
   return -1;
 }
 
-/* ssl3_check_leaf_certificate returns one if |leaf| is a suitable leaf server
- * certificate for |ssl|. Otherwise, it returns zero and pushes an error on the
- * error queue. */
-static int ssl3_check_leaf_certificate(SSL *ssl, X509 *leaf) {
-  int ret = 0;
-  EVP_PKEY *pkey = X509_get_pubkey(leaf);
-  if (pkey == NULL) {
-    goto err;
-  }
-
-  /* Check the certificate's type matches the cipher. */
-  const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
-  int expected_type = ssl_cipher_get_key_type(cipher);
-  assert(expected_type != EVP_PKEY_NONE);
-  if (pkey->type != expected_type) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
-    goto err;
-  }
-
-  if (cipher->algorithm_auth & SSL_aECDSA) {
-    /* TODO(davidben): This behavior is preserved from upstream. Should key
-     * usages be checked in other cases as well? */
-    /* This call populates the ex_flags field correctly */
-    X509_check_purpose(leaf, -1, 0);
-    if ((leaf->ex_flags & EXFLAG_KUSAGE) &&
-        !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
-      goto err;
-    }
-
-    if (!tls1_check_ec_cert(ssl, leaf)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
-      goto err;
-    }
-  }
-
-  ret = 1;
-
-err:
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
 static int ssl3_get_server_certificate(SSL *ssl) {
   int ret =
       ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message);
@@ -988,7 +945,7 @@
   }
 
   X509 *leaf = sk_X509_value(chain, 0);
-  if (!ssl3_check_leaf_certificate(ssl, leaf)) {
+  if (!ssl_check_leaf_certificate(ssl, leaf)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
     goto err;
   }
diff --git a/ssl/internal.h b/ssl/internal.h
index a6567ab..be7bde2 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -768,6 +768,11 @@
  * on error. */
 int ssl_add_client_CA_list(SSL *ssl, CBB *cbb);
 
+/* ssl_check_leaf_certificate returns one if |leaf| is a suitable leaf server
+ * certificate for |ssl|. Otherwise, it returns zero and pushes an error on the
+ * error queue. */
+int ssl_check_leaf_certificate(SSL *ssl, X509 *leaf);
+
 
 /* Underdocumented functions.
  *
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 952bf45..5138f15 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -114,6 +114,7 @@
 
 #include <openssl/ssl.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include <openssl/bn.h>
@@ -727,3 +728,43 @@
   *out_chain = ssl->cert->chain;
   return 1;
 }
+
+int ssl_check_leaf_certificate(SSL *ssl, X509 *leaf) {
+  int ret = 0;
+  EVP_PKEY *pkey = X509_get_pubkey(leaf);
+  if (pkey == NULL) {
+    goto err;
+  }
+
+  /* Check the certificate's type matches the cipher. */
+  const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
+  int expected_type = ssl_cipher_get_key_type(cipher);
+  assert(expected_type != EVP_PKEY_NONE);
+  if (pkey->type != expected_type) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
+    goto err;
+  }
+
+  if (cipher->algorithm_auth & SSL_aECDSA) {
+    /* TODO(davidben): This behavior is preserved from upstream. Should key
+     * usages be checked in other cases as well? */
+    /* This call populates the ex_flags field correctly */
+    X509_check_purpose(leaf, -1, 0);
+    if ((leaf->ex_flags & EXFLAG_KUSAGE) &&
+        !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+      goto err;
+    }
+
+    if (!tls1_check_ec_cert(ssl, leaf)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
+      goto err;
+    }
+  }
+
+  ret = 1;
+
+err:
+  EVP_PKEY_free(pkey);
+  return ret;
+}