Browse Source

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>
kris/onging/CECPQ3_patch15
Adam Langley 7 years ago
committed by CQ bot account: commit-bot@chromium.org
parent
commit
52940c4945
3 changed files with 106 additions and 107 deletions
  1. +1
    -0
      ssl/internal.h
  2. +87
    -0
      ssl/ssl_cert.c
  3. +18
    -107
      ssl/ssl_rsa.c

+ 1
- 0
ssl/internal.h View File

@@ -1882,6 +1882,7 @@ CERT *ssl_cert_dup(CERT *cert);
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. */


+ 87
- 0
ssl/ssl_cert.c View File

@@ -245,6 +245,93 @@ static void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg),
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) {


+ 18
- 107
ssl/ssl_rsa.c View File

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

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

const int ok = ssl_set_cert(ssl->cert, buffer);
CRYPTO_BUFFER_free(buffer);
return ok;
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 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
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 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
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;


Loading…
Cancel
Save