Move a number of certificate-related functions from ssl_rsa.c to ssl_cert.c

This leaves ssl_rsa.c dealing only with private-key matters.

Change-Id: I46aa80abd8374d8cc6d2b0f7a9a345214ec86084
Reviewed-on: https://boringssl-review.googlesource.com/13582
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/internal.h b/ssl/internal.h
index a53bd07..18ef26a 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1882,6 +1882,7 @@
 void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
 int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer);
+int ssl_is_key_type_supported(int key_type);
 /* ssl_compare_public_and_private_key returns one if |pubkey| is the public
  * counterpart to |privkey|. Otherwise it returns zero and pushes a helpful
  * message on the error queue. */
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 1a79327..4177a48 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -245,6 +245,93 @@
   c->cert_cb_arg = arg;
 }
 
+int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
+  CBS cert_cbs;
+  CRYPTO_BUFFER_init_CBS(buffer, &cert_cbs);
+  EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
+  if (pubkey == NULL) {
+    return 0;
+  }
+
+  if (!ssl_is_key_type_supported(pubkey->type)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+    EVP_PKEY_free(pubkey);
+    return 0;
+  }
+
+  /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
+   * certificates, so sanity-check the key usage extension. */
+  if (pubkey->type == EVP_PKEY_EC &&
+      !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+    EVP_PKEY_free(pubkey);
+    return 0;
+  }
+
+  if (cert->privatekey != NULL) {
+    /* Sanity-check that the private key and the certificate match, unless the
+     * key is opaque (in case of, say, a smartcard). */
+    if (!EVP_PKEY_is_opaque(cert->privatekey) &&
+        !ssl_compare_public_and_private_key(pubkey, cert->privatekey)) {
+      /* don't fail for a cert/key mismatch, just free current private key
+       * (when switching to a different cert & key, first this function should
+       * be used, then ssl_set_pkey */
+      EVP_PKEY_free(cert->privatekey);
+      cert->privatekey = NULL;
+      /* clear error queue */
+      ERR_clear_error();
+    }
+  }
+
+  EVP_PKEY_free(pubkey);
+
+  cert->x509_method->cert_flush_cached_leaf(cert);
+
+  if (cert->chain != NULL) {
+    CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
+    sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
+    CRYPTO_BUFFER_up_ref(buffer);
+    return 1;
+  }
+
+  cert->chain = sk_CRYPTO_BUFFER_new_null();
+  if (cert->chain == NULL) {
+    return 0;
+  }
+
+  if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
+    sk_CRYPTO_BUFFER_free(cert->chain);
+    cert->chain = NULL;
+    return 0;
+  }
+  CRYPTO_BUFFER_up_ref(buffer);
+
+  return 1;
+}
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
+                                 const uint8_t *der) {
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(ctx->cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
+int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(ssl->cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
 int ssl_verify_cert_chain(SSL *ssl, long *out_verify_result,
                           STACK_OF(X509) *cert_chain) {
   if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index f3e8bf3..7962247 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -70,21 +70,30 @@
 #include "internal.h"
 
 
-static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey);
-
-static int is_key_type_supported(int key_type) {
+int ssl_is_key_type_supported(int key_type) {
   return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
 }
 
-int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
-  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
-  if (buffer == NULL) {
+static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) {
+  if (!ssl_is_key_type_supported(pkey->type)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
     return 0;
   }
 
-  const int ok = ssl_set_cert(ssl->cert, buffer);
-  CRYPTO_BUFFER_free(buffer);
-  return ok;
+  if (cert->chain != NULL &&
+      sk_CRYPTO_BUFFER_value(cert->chain, 0) != NULL &&
+      /* Sanity-check that the private key and the certificate match, unless
+       * the key is opaque (in case of, say, a smartcard). */
+      !EVP_PKEY_is_opaque(pkey) &&
+      !ssl_cert_check_private_key(cert, pkey)) {
+    return 0;
+  }
+
+  EVP_PKEY_free(cert->privatekey);
+  EVP_PKEY_up_ref(pkey);
+  cert->privatekey = pkey;
+
+  return 1;
 }
 
 int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
@@ -111,28 +120,6 @@
   return ret;
 }
 
-static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) {
-  if (!is_key_type_supported(pkey->type)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-    return 0;
-  }
-
-  if (cert->chain != NULL &&
-      sk_CRYPTO_BUFFER_value(cert->chain, 0) != NULL &&
-      /* Sanity-check that the private key and the certificate match, unless
-       * the key is opaque (in case of, say, a smartcard). */
-      !EVP_PKEY_is_opaque(pkey) &&
-      !ssl_cert_check_private_key(cert, pkey)) {
-    return 0;
-  }
-
-  EVP_PKEY_free(cert->privatekey);
-  EVP_PKEY_up_ref(pkey);
-  cert->privatekey = pkey;
-
-  return 1;
-}
-
 int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
   if (pkey == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
@@ -162,82 +149,6 @@
   return ret;
 }
 
-int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
-  CBS cert_cbs;
-  CRYPTO_BUFFER_init_CBS(buffer, &cert_cbs);
-  EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
-  if (pubkey == NULL) {
-    return 0;
-  }
-
-  if (!is_key_type_supported(pubkey->type)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-    EVP_PKEY_free(pubkey);
-    return 0;
-  }
-
-  /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
-   * certificates, so sanity-check the key usage extension. */
-  if (pubkey->type == EVP_PKEY_EC &&
-      !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-    EVP_PKEY_free(pubkey);
-    return 0;
-  }
-
-  if (cert->privatekey != NULL) {
-    /* Sanity-check that the private key and the certificate match, unless the
-     * key is opaque (in case of, say, a smartcard). */
-    if (!EVP_PKEY_is_opaque(cert->privatekey) &&
-        !ssl_compare_public_and_private_key(pubkey, cert->privatekey)) {
-      /* don't fail for a cert/key mismatch, just free current private key
-       * (when switching to a different cert & key, first this function should
-       * be used, then ssl_set_pkey */
-      EVP_PKEY_free(cert->privatekey);
-      cert->privatekey = NULL;
-      /* clear error queue */
-      ERR_clear_error();
-    }
-  }
-
-  EVP_PKEY_free(pubkey);
-
-  cert->x509_method->cert_flush_cached_leaf(cert);
-
-  if (cert->chain != NULL) {
-    CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
-    sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
-    CRYPTO_BUFFER_up_ref(buffer);
-    return 1;
-  }
-
-  cert->chain = sk_CRYPTO_BUFFER_new_null();
-  if (cert->chain == NULL) {
-    return 0;
-  }
-
-  if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
-    sk_CRYPTO_BUFFER_free(cert->chain);
-    cert->chain = NULL;
-    return 0;
-  }
-  CRYPTO_BUFFER_up_ref(buffer);
-
-  return 1;
-}
-
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
-                                 const uint8_t *der) {
-  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
-  if (buffer == NULL) {
-    return 0;
-  }
-
-  const int ok = ssl_set_cert(ctx->cert, buffer);
-  CRYPTO_BUFFER_free(buffer);
-  return ok;
-}
-
 int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
   int ret;
   EVP_PKEY *pkey;