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;
+}