Move the Digest/Sign split for SignatureAlgorithms to a lower level. In order to delay the digest of the handshake transcript and unify around message-based signing callbacks, a copy of the transcript is kept around until we are sure there is no certificate authentication. This removes support for SSL_PRIVATE_KEY_METHOD as a client in SSL 3.0. Change-Id: If8999a19ca021b4ff439319ab91e2cd2103caa64 Reviewed-on: https://boringssl-review.googlesource.com/8561 Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 66e73b4..a65f6f4 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c
@@ -372,9 +372,24 @@ return ssl_private_key_failure; } + EVP_MD_CTX mctx; + uint8_t hash[EVP_MAX_MD_SIZE]; + unsigned hash_len; + + EVP_MD_CTX_init(&mctx); + if (!EVP_DigestInit_ex(&mctx, md, NULL) || + !EVP_DigestUpdate(&mctx, in, in_len) || + !EVP_DigestFinal(&mctx, hash, &hash_len)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); + EVP_MD_CTX_cleanup(&mctx); + return 0; + } + EVP_MD_CTX_cleanup(&mctx); + + if (ssl->cert->key_method != NULL) { - return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in, - in_len); + return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, hash, + hash_len); } enum ssl_private_key_result_t ret = ssl_private_key_failure; @@ -386,7 +401,7 @@ size_t len = max_out; if (!EVP_PKEY_sign_init(ctx) || !EVP_PKEY_CTX_set_signature_md(ctx, md) || - !EVP_PKEY_sign(ctx, out, &len, in, in_len)) { + !EVP_PKEY_sign(ctx, out, &len, hash, hash_len)) { goto end; } *out_len = len; @@ -403,6 +418,23 @@ return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out); } +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 = tls12_get_hash(signature_algorithm); + if (md == NULL) { + 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; +} + enum ssl_private_key_result_t ssl_private_key_decrypt( SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const uint8_t *in, size_t in_len) {