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/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index 64249ad..700f9df 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -171,6 +171,7 @@
SSL,238,UNSUPPORTED_COMPRESSION_ALGORITHM
SSL,239,UNSUPPORTED_ELLIPTIC_CURVE
SSL,240,UNSUPPORTED_PROTOCOL
+SSL,252,UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY
SSL,241,WRONG_CERTIFICATE_TYPE
SSL,242,WRONG_CIPHER_RETURNED
SSL,243,WRONG_CURVE
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 641b94a..627c288 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4655,6 +4655,7 @@
#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 249
#define SSL_R_SHUTDOWN_WHILE_IN_INIT 250
#define SSL_R_INVALID_OUTER_RECORD_TYPE 251
+#define SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY 252
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index b4123dd..e3cd102 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -880,11 +880,10 @@
goto f_err;
}
- /* If doing a full handshake with TLS 1.2, the server may request a client
- * certificate which requires hashing the handshake transcript under a
- * different hash. Otherwise, the handshake buffer may be released. */
- if (ssl->hit || ssl3_protocol_version(ssl) < TLS1_2_VERSION ||
- !ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
+ /* If doing a full handshake, the server may request a client certificate
+ * which requires hashing the handshake transcript. Otherwise, the handshake
+ * buffer may be released. */
+ if (ssl->hit || !ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
ssl3_free_handshake_buffer(ssl);
}
@@ -1120,7 +1119,6 @@
}
static int ssl3_get_server_key_exchange(SSL *ssl) {
- EVP_MD_CTX md_ctx;
int al, ok;
EVP_PKEY *pkey = NULL;
DH *dh = NULL;
@@ -1158,7 +1156,6 @@
uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
- EVP_MD_CTX_init(&md_ctx);
if (alg_a & SSL_aPSK) {
CBS psk_identity_hint;
@@ -1336,21 +1333,25 @@
goto f_err;
}
- const EVP_MD *md = tls12_get_hash(signature_algorithm);
- if (md == NULL) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+ CBB transcript;
+ uint8_t *transcript_data;
+ size_t transcript_len;
+ if (!CBB_init(&transcript, 2*SSL3_RANDOM_SIZE + CBS_len(¶meter)) ||
+ !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(&transcript, CBS_data(¶meter), CBS_len(¶meter)) ||
+ !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
+ CBB_cleanup(&transcript);
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto f_err;
}
- int sig_ok = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
- EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->client_random,
- SSL3_RANDOM_SIZE) &&
- EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->server_random,
- SSL3_RANDOM_SIZE) &&
- EVP_DigestVerifyUpdate(&md_ctx, CBS_data(¶meter),
- CBS_len(¶meter)) &&
- EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
- CBS_len(&signature));
+
+ int sig_ok = ssl_public_key_verify(
+ ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
+ pkey, transcript_data, transcript_len);
+ OPENSSL_free(transcript_data);
+
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
sig_ok = 1;
ERR_clear_error();
@@ -1372,7 +1373,6 @@
}
}
EVP_PKEY_free(pkey);
- EVP_MD_CTX_cleanup(&md_ctx);
return 1;
f_err:
@@ -1382,7 +1382,6 @@
DH_free(dh);
EC_POINT_free(srvr_ecpoint);
EC_KEY_free(ecdh);
- EVP_MD_CTX_cleanup(&md_ctx);
return -1;
}
@@ -1840,23 +1839,44 @@
goto err;
}
- size_t sig_len;
+ size_t sig_len = max_sig_len;
enum ssl_private_key_result_t sign_result;
if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) {
- /* Compute the digest. In TLS 1.1 and below, the digest type is also
- * selected here. */
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_len;
- if (!ssl3_cert_verify_hash(ssl, digest, &digest_len, signature_algorithm)) {
- goto err;
+ /* The SSL3 construction for CertificateVerify does not decompose into a
+ * single final digest and signature, and must be special-cased. */
+ if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+ if (ssl->cert->key_method != NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+ goto err;
+ }
+
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_len;
+ if (!ssl3_cert_verify_hash(ssl, digest, &digest_len,
+ signature_algorithm)) {
+ goto err;
+ }
+
+ sign_result = ssl_private_key_success;
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
+ if (pctx == NULL ||
+ !EVP_PKEY_sign_init(pctx) ||
+ !EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len)) {
+ EVP_PKEY_CTX_free(pctx);
+ sign_result = ssl_private_key_failure;
+ goto err;
+ }
+ EVP_PKEY_CTX_free(pctx);
+ } else {
+ sign_result = ssl_private_key_sign(
+ ssl, ptr, &sig_len, max_sig_len, signature_algorithm,
+ (const uint8_t *)ssl->s3->handshake_buffer->data,
+ ssl->s3->handshake_buffer->length);
}
/* The handshake buffer is no longer necessary. */
ssl3_free_handshake_buffer(ssl);
-
- /* Sign the digest. */
- sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len,
- signature_algorithm, digest, digest_len);
} else {
assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B);
sign_result =
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index e0e1cd7..d302f11 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -1036,10 +1036,8 @@
goto f_err;
}
- /* In TLS 1.2, client authentication requires hashing the handshake transcript
- * under a different hash. Otherwise, release the handshake buffer. */
- if (!ssl->s3->tmp.cert_request ||
- ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
+ /* Release the handshake buffer if client authentication isn't required. */
+ if (!ssl->s3->tmp.cert_request) {
ssl3_free_handshake_buffer(ssl);
}
@@ -1279,33 +1277,26 @@
size_t sig_len;
enum ssl_private_key_result_t sign_result;
if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
- /* Compute the digest and sign it. */
- uint8_t digest[EVP_MAX_MD_SIZE];
- unsigned digest_len = 0;
- EVP_MD_CTX md_ctx;
- EVP_MD_CTX_init(&md_ctx);
-
- const EVP_MD *md = tls12_get_hash(signature_algorithm);
- if (md == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ CBB transcript;
+ uint8_t *transcript_data;
+ size_t transcript_len;
+ if (!CBB_init(&transcript,
+ 2*SSL3_RANDOM_SIZE + ssl->s3->tmp.server_params_len) ||
+ !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(&transcript, ssl->s3->tmp.server_params,
+ ssl->s3->tmp.server_params_len) ||
+ !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
+ CBB_cleanup(&transcript);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
- int digest_ret =
- EVP_DigestInit_ex(&md_ctx, md, NULL) &&
- EVP_DigestUpdate(&md_ctx, ssl->s3->client_random, SSL3_RANDOM_SIZE) &&
- EVP_DigestUpdate(&md_ctx, ssl->s3->server_random, SSL3_RANDOM_SIZE) &&
- EVP_DigestUpdate(&md_ctx, ssl->s3->tmp.server_params,
- ssl->s3->tmp.server_params_len) &&
- EVP_DigestFinal_ex(&md_ctx, digest, &digest_len);
- EVP_MD_CTX_cleanup(&md_ctx);
- if (!digest_ret) {
- goto err;
- }
sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len,
- signature_algorithm, digest,
- digest_len);
+ signature_algorithm, transcript_data,
+ transcript_len);
+ OPENSSL_free(transcript_data);
} else {
assert(ssl->state == SSL3_ST_SW_KEY_EXCH_B);
sign_result =
@@ -1876,9 +1867,6 @@
CBS certificate_verify, signature;
X509 *peer = ssl->session->peer;
EVP_PKEY *pkey = NULL;
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_length;
- EVP_PKEY_CTX *pctx = NULL;
/* Only RSA and ECDSA client certificates are supported, so a
* CertificateVerify is required if and only if there's a client certificate.
@@ -1927,19 +1915,6 @@
signature_algorithm = SSL_SIGN_ECDSA_SHA1;
}
- /* Compute the digest. */
- if (!ssl3_cert_verify_hash(ssl, digest, &digest_length,
- signature_algorithm)) {
- goto err;
- }
-
- /* The handshake buffer is no longer necessary, and we may hash the current
- * message.*/
- ssl3_free_handshake_buffer(ssl);
- if (!ssl3_hash_current_message(ssl)) {
- goto err;
- }
-
/* Parse and verify the signature. */
if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
CBS_len(&certificate_verify) != 0) {
@@ -1948,22 +1923,40 @@
goto f_err;
}
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (pctx == NULL) {
- goto err;
+ int sig_ok;
+ /* The SSL3 construction for CertificateVerify does not decompose into a
+ * single final digest and signature, and must be special-cased. */
+ if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+ if (ssl->cert->key_method != NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+ goto err;
+ }
+
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_len;
+ if (!ssl3_cert_verify_hash(ssl, digest, &digest_len,
+ signature_algorithm)) {
+ goto err;
+ }
+
+ const EVP_MD *md = tls12_get_hash(signature_algorithm);
+ assert(md != NULL);
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ sig_ok = pctx != NULL &&
+ EVP_PKEY_verify_init(pctx) &&
+ EVP_PKEY_CTX_set_signature_md(pctx, md) &&
+ EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
+ digest, digest_len);
+
+ EVP_PKEY_CTX_free(pctx);
+ } else {
+ sig_ok = ssl_public_key_verify(
+ ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
+ pkey, (const uint8_t *)ssl->s3->handshake_buffer->data,
+ ssl->s3->handshake_buffer->length);
}
- const EVP_MD *md = tls12_get_hash(signature_algorithm);
- if (md == NULL) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
- goto f_err;
- }
-
- int sig_ok = EVP_PKEY_verify_init(pctx) &&
- EVP_PKEY_CTX_set_signature_md(pctx, md) &&
- EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
- digest, digest_length);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
sig_ok = 1;
ERR_clear_error();
@@ -1974,6 +1967,13 @@
goto f_err;
}
+ /* The handshake buffer is no longer necessary, and we may hash the current
+ * message.*/
+ ssl3_free_handshake_buffer(ssl);
+ if (!ssl3_hash_current_message(ssl)) {
+ goto err;
+ }
+
ret = 1;
if (0) {
@@ -1982,7 +1982,6 @@
}
err:
- EVP_PKEY_CTX_free(pctx);
EVP_PKEY_free(pkey);
return ret;
diff --git a/ssl/internal.h b/ssl/internal.h
index d0eca69..ab79dcc 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -490,6 +490,12 @@
enum ssl_private_key_result_t ssl_private_key_decrypt_complete(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out);
+/* ssl_public_key_verify verifies that the |signature| is valid for the public
+ * key |pkey| and input |in|, using the |signature_algorithm| specified. */
+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);
/* Custom extensions */
@@ -865,7 +871,6 @@
size_t label_len, const uint8_t *seed1, size_t seed1_len,
const uint8_t *seed2, size_t seed2_len);
int (*final_finish_mac)(SSL *ssl, int from_server, uint8_t *out);
- int (*cert_verify_mac)(SSL *, int, uint8_t *);
};
/* lengths of messages */
@@ -1008,12 +1013,10 @@
* handshake hash. It returns one on success and zero on allocation failure. */
int ssl3_hash_current_message(SSL *ssl);
-/* ssl3_cert_verify_hash writes the CertificateVerify hash into the bytes
- * pointed to by |out| and writes the number of bytes to |*out_len|. |out| must
- * have room for EVP_MAX_MD_SIZE bytes. For TLS 1.2 and up,
- * |signature_algorithm| is used to determine the hash function, otherwise the
- * hash function depends on the private key type. It returns one on success and
- * zero on failure. */
+/* ssl3_cert_verify_hash writes the SSL 3.0 CertificateVerify hash into the
+ * bytes pointed to by |out| and writes the number of bytes to |*out_len|. |out|
+ * must have room for EVP_MAX_MD_SIZE bytes. It returns one on success and zero
+ * on failure. */
int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len,
uint16_t signature_algorithm);
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 8dee4d8..f28e50f 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -463,55 +463,6 @@
ssl->init_num + header_len);
}
-/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
- * is sufficient pre-TLS1.2 as well. */
-OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
- combined_tls_hash_fits_in_max);
-
-int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len,
- uint16_t signature_algorithm) {
- /* For TLS v1.2 send signature algorithm and signature using
- * agreed digest and cached handshake records. Otherwise, use
- * SHA1 or MD5 + SHA1 depending on key type. */
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- EVP_MD_CTX mctx;
- unsigned len;
-
- const EVP_MD *md = tls12_get_hash(signature_algorithm);
- if (md == NULL) {
- return 0;
- }
-
- EVP_MD_CTX_init(&mctx);
- if (!EVP_DigestInit_ex(&mctx, md, NULL) ||
- !EVP_DigestUpdate(&mctx, ssl->s3->handshake_buffer->data,
- ssl->s3->handshake_buffer->length) ||
- !EVP_DigestFinal(&mctx, out, &len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
- EVP_MD_CTX_cleanup(&mctx);
- return 0;
- }
- *out_len = len;
- } else if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
- if (ssl->s3->enc_method->cert_verify_mac(ssl, NID_md5, out) == 0 ||
- ssl->s3->enc_method->cert_verify_mac(ssl, NID_sha1,
- out + MD5_DIGEST_LENGTH) == 0) {
- return 0;
- }
- *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
- } else if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
- if (ssl->s3->enc_method->cert_verify_mac(ssl, NID_sha1, out) == 0) {
- return 0;
- }
- *out_len = SHA_DIGEST_LENGTH;
- } else {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
-}
-
int ssl_verify_alarm_type(long type) {
int al;
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 04aa08c..d70f373 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -146,10 +146,6 @@
#include "internal.h"
-
-static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender,
- size_t sender_len, uint8_t *p);
-
static int ssl3_prf(const SSL *ssl, uint8_t *out, size_t out_len,
const uint8_t *secret, size_t secret_len, const char *label,
size_t label_len, const uint8_t *seed1, size_t seed1_len,
@@ -294,31 +290,6 @@
return 1;
}
-static int ssl3_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *p) {
- return ssl3_handshake_mac(ssl, md_nid, NULL, 0, p);
-}
-
-static int ssl3_final_finish_mac(SSL *ssl, int from_server, uint8_t *out) {
- const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
- : SSL3_MD_CLIENT_FINISHED_CONST;
- const size_t sender_len = 4;
- int ret, sha1len;
- ret = ssl3_handshake_mac(ssl, NID_md5, sender, sender_len, out);
- if (ret == 0) {
- return 0;
- }
-
- out += ret;
-
- sha1len = ssl3_handshake_mac(ssl, NID_sha1, sender, sender_len, out);
- if (sha1len == 0) {
- return 0;
- }
-
- ret += sha1len;
- return ret;
-}
-
static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender,
size_t sender_len, uint8_t *p) {
unsigned int ret;
@@ -385,10 +356,57 @@
return ret;
}
+static int ssl3_final_finish_mac(SSL *ssl, int from_server, uint8_t *out) {
+ const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
+ : SSL3_MD_CLIENT_FINISHED_CONST;
+ const size_t sender_len = 4;
+ int ret, sha1len;
+ ret = ssl3_handshake_mac(ssl, NID_md5, sender, sender_len, out);
+ if (ret == 0) {
+ return 0;
+ }
+ out += ret;
+
+ sha1len = ssl3_handshake_mac(ssl, NID_sha1, sender, sender_len, out);
+ if (sha1len == 0) {
+ return 0;
+ }
+
+ ret += sha1len;
+ return ret;
+}
+
+/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
+ * is sufficient pre-TLS1.2 as well. */
+OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+ combined_tls_hash_fits_in_max);
+
+int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len,
+ uint16_t signature_algorithm) {
+ assert(ssl3_protocol_version(ssl) == SSL3_VERSION);
+
+ if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
+ if (ssl3_handshake_mac(ssl, NID_md5, NULL, 0, out) == 0 ||
+ ssl3_handshake_mac(ssl, NID_sha1, NULL, 0,
+ out + MD5_DIGEST_LENGTH) == 0) {
+ return 0;
+ }
+ *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
+ } else if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
+ if (ssl3_handshake_mac(ssl, NID_sha1, NULL, 0, out) == 0) {
+ return 0;
+ }
+ *out_len = SHA_DIGEST_LENGTH;
+ } else {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+}
const SSL3_ENC_METHOD SSLv3_enc_data = {
ssl3_prf,
ssl3_final_finish_mac,
- ssl3_cert_verify_mac,
};
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) {
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index b599207..453adf3 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -389,29 +389,6 @@
return 1;
}
-static int tls1_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *out) {
- const EVP_MD_CTX *ctx_template;
- if (md_nid == NID_md5) {
- ctx_template = &ssl->s3->handshake_md5;
- } else if (md_nid == EVP_MD_CTX_type(&ssl->s3->handshake_hash)) {
- ctx_template = &ssl->s3->handshake_hash;
- } else {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_REQUIRED_DIGEST);
- return 0;
- }
-
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
- if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
- EVP_MD_CTX_cleanup(&ctx);
- return 0;
- }
- unsigned ret;
- EVP_DigestFinal_ex(&ctx, out, &ret);
- EVP_MD_CTX_cleanup(&ctx);
- return ret;
-}
-
static int append_digest(const EVP_MD_CTX *ctx, uint8_t *out, size_t *out_len,
size_t max_out) {
int ret = 0;
@@ -558,5 +535,4 @@
const SSL3_ENC_METHOD TLSv1_enc_data = {
tls1_prf,
tls1_final_finish_mac,
- tls1_cert_verify_mac,
};