Convert ssl_privkey.c to message-based signing APIs.

This allows us to share some of the is_ecdsa mess between signing and
verifying in a way that will generalize to Ed25519. This makes it a lot
shorter and gets us closer to Ed25519.

Later work will tidy this up further.

BUG=187

Change-Id: Ibf3c07c48824061389b8c86294225d9ef25dd82d
Reviewed-on: https://boringssl-review.googlesource.com/14448
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2017-03-28 14:17:01 -05:00 committed by Adam Langley
parent 7c83fdaf5b
commit 76feb1f97f

View File

@ -332,9 +332,6 @@ size_t ssl_private_key_max_signature_len(SSL *ssl) {
return EVP_PKEY_size(ssl->cert->privatekey);
}
/* TODO(davidben): Forbid RSA-PKCS1 in TLS 1.3. For now we allow it because NSS
* has yet to start doing RSA-PSS, so enforcing it would complicate interop
* testing. */
static int is_rsa_pkcs1(const EVP_MD **out_md, uint16_t sigalg) {
switch (sigalg) {
case SSL_SIGN_RSA_PKCS1_MD5_SHA1:
@ -357,35 +354,20 @@ static int is_rsa_pkcs1(const EVP_MD **out_md, uint16_t sigalg) {
}
}
static int ssl_sign_rsa_pkcs1(SSL *ssl, uint8_t *out, size_t *out_len,
size_t max_out, const EVP_MD *md,
const uint8_t *in, size_t in_len) {
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
*out_len = max_out;
int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
EVP_DigestSignUpdate(&ctx, in, in_len) &&
EVP_DigestSignFinal(&ctx, out, out_len);
EVP_MD_CTX_cleanup(&ctx);
return ret;
}
static int ssl_verify_rsa_pkcs1(SSL *ssl, const uint8_t *signature,
size_t signature_len, const EVP_MD *md,
EVP_PKEY *pkey, const uint8_t *in,
size_t in_len) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
static int is_rsa_pss(const EVP_MD **out_md, uint16_t sigalg) {
switch (sigalg) {
case SSL_SIGN_RSA_PSS_SHA256:
*out_md = EVP_sha256();
return 1;
case SSL_SIGN_RSA_PSS_SHA384:
*out_md = EVP_sha384();
return 1;
case SSL_SIGN_RSA_PSS_SHA512:
*out_md = EVP_sha512();
return 1;
default:
return 0;
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
EVP_MD_CTX_cleanup(&md_ctx);
return ret;
}
static int is_ecdsa(int *out_curve, const EVP_MD **out_md, uint16_t sigalg) {
@ -411,112 +393,53 @@ static int is_ecdsa(int *out_curve, const EVP_MD **out_md, uint16_t sigalg) {
}
}
static int ssl_sign_ecdsa(SSL *ssl, uint8_t *out, size_t *out_len,
size_t max_out, int curve, const EVP_MD *md,
const uint8_t *in, size_t in_len) {
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey);
if (ec_key == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
static int setup_ctx(SSL *ssl, EVP_PKEY_CTX *ctx,
uint16_t signature_algorithm) {
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
/* In TLS 1.3, the curve is also specified by the signature algorithm. */
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
(curve == NID_undef ||
EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
*out_len = max_out;
int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
EVP_DigestSignUpdate(&ctx, in, in_len) &&
EVP_DigestSignFinal(&ctx, out, out_len);
EVP_MD_CTX_cleanup(&ctx);
return ret;
}
static int ssl_verify_ecdsa(SSL *ssl, const uint8_t *signature,
size_t signature_len, int curve, const EVP_MD *md,
EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (ec_key == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* In TLS 1.3, the curve is also specified by the signature algorithm. */
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
(curve == NID_undef ||
EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
EVP_MD_CTX_cleanup(&md_ctx);
return ret;
}
static int is_rsa_pss(const EVP_MD **out_md, uint16_t sigalg) {
switch (sigalg) {
case SSL_SIGN_RSA_PSS_SHA256:
*out_md = EVP_sha256();
return 1;
case SSL_SIGN_RSA_PSS_SHA384:
*out_md = EVP_sha384();
return 1;
case SSL_SIGN_RSA_PSS_SHA512:
*out_md = EVP_sha512();
return 1;
default:
const EVP_MD *md;
if (is_rsa_pkcs1(&md, signature_algorithm) &&
ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
}
static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len,
size_t max_out, const EVP_MD *md,
const uint8_t *in, size_t in_len) {
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
*out_len = max_out;
EVP_PKEY_CTX *pctx;
int ret =
EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) &&
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
EVP_DigestSignUpdate(&ctx, in, in_len) &&
EVP_DigestSignFinal(&ctx, out, out_len);
EVP_MD_CTX_cleanup(&ctx);
return ret;
}
static int ssl_verify_rsa_pss(SSL *ssl, const uint8_t *signature,
size_t signature_len, const EVP_MD *md,
EVP_PKEY *pkey, const uint8_t *in,
size_t in_len) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
return EVP_PKEY_CTX_set_signature_md(ctx, md);
}
EVP_MD_CTX md_ctx;
EVP_MD_CTX_init(&md_ctx);
EVP_PKEY_CTX *pctx;
int ret =
EVP_DigestVerifyInit(&md_ctx, &pctx, md, NULL, pkey) &&
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
EVP_MD_CTX_cleanup(&md_ctx);
return ret;
if (is_rsa_pss(&md, signature_algorithm)) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
return EVP_PKEY_CTX_set_signature_md(ctx, md) &&
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) &&
EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1 /* salt len = hash len */);
}
int curve;
if (is_ecdsa(&curve, &md, signature_algorithm)) {
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (ec_key == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
/* In TLS 1.3, the curve is also specified by the signature algorithm. */
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
(curve == NID_undef ||
EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
return EVP_PKEY_CTX_set_signature_md(ctx, md);
}
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
enum ssl_private_key_result_t ssl_private_key_sign(
@ -548,54 +471,26 @@ enum ssl_private_key_result_t ssl_private_key_sign(
hash, hash_len);
}
const EVP_MD *md;
if (is_rsa_pkcs1(&md, signature_algorithm) &&
ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
return ssl_sign_rsa_pkcs1(ssl, out, out_len, max_out, md, in, in_len)
? ssl_private_key_success
: ssl_private_key_failure;
}
int curve;
if (is_ecdsa(&curve, &md, signature_algorithm)) {
return ssl_sign_ecdsa(ssl, out, out_len, max_out, curve, md, in, in_len)
? ssl_private_key_success
: ssl_private_key_failure;
}
if (is_rsa_pss(&md, signature_algorithm)) {
return ssl_sign_rsa_pss(ssl, out, out_len, max_out, md, in, in_len)
? ssl_private_key_success
: ssl_private_key_failure;
}
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return ssl_private_key_failure;
*out_len = max_out;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
int ret = ctx != NULL &&
EVP_PKEY_sign_init(ctx) &&
setup_ctx(ssl, ctx, signature_algorithm) &&
EVP_PKEY_sign_message(ctx, out, out_len, in, in_len);
EVP_PKEY_CTX_free(ctx);
return ret ? ssl_private_key_success : ssl_private_key_failure;
}
int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
size_t signature_len, uint16_t signature_algorithm,
EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
const EVP_MD *md;
if (is_rsa_pkcs1(&md, signature_algorithm) &&
ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
return ssl_verify_rsa_pkcs1(ssl, signature, signature_len, md, pkey, in,
in_len);
}
int curve;
if (is_ecdsa(&curve, &md, signature_algorithm)) {
return ssl_verify_ecdsa(ssl, signature, signature_len, curve, md, pkey, in,
in_len);
}
if (is_rsa_pss(&md, signature_algorithm)) {
return ssl_verify_rsa_pss(ssl, signature, signature_len, md, pkey, in,
in_len);
}
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL);
int ret = ctx != NULL &&
EVP_PKEY_verify_init(ctx) &&
setup_ctx(ssl, ctx, signature_algorithm) &&
EVP_PKEY_verify_message(ctx, signature, signature_len, in, in_len);
EVP_PKEY_CTX_free(ctx);
return ret;
}
enum ssl_private_key_result_t ssl_private_key_decrypt(