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>
This commit is contained in:
Steven Valdez 2016-07-15 07:07:40 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 2aad406b1b
commit bf5aa846d6
3 changed files with 47 additions and 44 deletions

View File

@ -922,49 +922,6 @@ err:
return -1; 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) { static int ssl3_get_server_certificate(SSL *ssl) {
int ret = int ret =
ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message); ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message);
@ -988,7 +945,7 @@ static int ssl3_get_server_certificate(SSL *ssl) {
} }
X509 *leaf = sk_X509_value(chain, 0); 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); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
goto err; goto err;
} }

View File

@ -768,6 +768,11 @@ STACK_OF(X509_NAME) *
* on error. */ * on error. */
int ssl_add_client_CA_list(SSL *ssl, CBB *cbb); 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. /* Underdocumented functions.
* *

View File

@ -114,6 +114,7 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <assert.h>
#include <string.h> #include <string.h>
#include <openssl/bn.h> #include <openssl/bn.h>
@ -727,3 +728,43 @@ int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
*out_chain = ssl->cert->chain; *out_chain = ssl->cert->chain;
return 1; 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;
}