diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c index 0629078b..f204286f 100644 --- a/ssl/handshake_client.c +++ b/ssl/handshake_client.c @@ -1255,11 +1255,8 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) { goto f_err; } hs->new_session->peer_signature_algorithm = signature_algorithm; - } else if (hs->peer_pubkey->type == EVP_PKEY_RSA) { - signature_algorithm = SSL_SIGN_RSA_PKCS1_MD5_SHA1; - } else if (hs->peer_pubkey->type == EVP_PKEY_EC) { - signature_algorithm = SSL_SIGN_ECDSA_SHA1; - } else { + } else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm, + hs->peer_pubkey)) { al = SSL_AD_UNSUPPORTED_CERTIFICATE; OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); goto f_err; diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c index 63027d60..4eaf3cb0 100644 --- a/ssl/handshake_server.c +++ b/ssl/handshake_server.c @@ -1722,11 +1722,8 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) { goto f_err; } hs->new_session->peer_signature_algorithm = signature_algorithm; - } else if (hs->peer_pubkey->type == EVP_PKEY_RSA) { - signature_algorithm = SSL_SIGN_RSA_PKCS1_MD5_SHA1; - } else if (hs->peer_pubkey->type == EVP_PKEY_EC) { - signature_algorithm = SSL_SIGN_ECDSA_SHA1; - } else { + } else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm, + hs->peer_pubkey)) { al = SSL_AD_UNSUPPORTED_CERTIFICATE; OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); goto f_err; diff --git a/ssl/internal.h b/ssl/internal.h index 1ed7e15c..e7a3f7a2 100644 --- a/ssl/internal.h +++ b/ssl/internal.h @@ -1272,6 +1272,11 @@ uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index); * error. */ int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *sigalgs); +/* tls1_get_legacy_signature_algorithm sets |*out| to the signature algorithm + * that should be used with |pkey| in TLS 1.1 and earlier. It returns one on + * success and zero if |pkey| may not be used at those versions. */ +int tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey); + /* tls1_choose_signature_algorithm sets |*out| to a signature algorithm for use * with |hs|'s private key based on the peer's preferences and the algorithms * supported. It returns one on success and zero on error. */ diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index c2a5dded..000a8cdf 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -3328,24 +3328,31 @@ int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) { return 1; } +int tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) { + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_RSA: + *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1; + return 1; + case EVP_PKEY_EC: + *out = SSL_SIGN_ECDSA_SHA1; + return 1; + default: + return 0; + } +} + int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { SSL *const ssl = hs->ssl; CERT *cert = ssl->cert; /* Before TLS 1.2, the signature algorithm isn't negotiated as part of the - * handshake. It is fixed at MD5-SHA1 for RSA and SHA1 for ECDSA. */ + * handshake. */ if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) { - switch (EVP_PKEY_id(hs->local_pubkey)) { - case EVP_PKEY_RSA: - *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1; - return 1; - case EVP_PKEY_EC: - *out = SSL_SIGN_ECDSA_SHA1; - return 1; - default: - OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); - return 0; + if (!tls1_get_legacy_signature_algorithm(out, hs->local_pubkey)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); + return 0; } + return 1; } const uint16_t *sigalgs = cert->sigalgs;