Add back check for the DH public key size

This is needed for TLS-1.3.

Also add check for uncompressed point format for ECDHE as
the other formats are not allowed by RFC 8446.

Fixes #17667

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17678)
This commit is contained in:
Tomas Mraz 2022-02-10 11:49:37 +01:00 committed by Pauli
parent 3d27ac8d92
commit d5530efada
4 changed files with 27 additions and 5 deletions

View File

@ -811,6 +811,9 @@ int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len,
size_t ssl_hmac_size(const SSL_HMAC *ctx);
int ssl_get_EC_curve_nid(const EVP_PKEY *pkey);
__owur int tls13_set_encoded_pub_key(EVP_PKEY *pkey,
const unsigned char *enckey,
size_t enckeylen);
typedef struct tls_group_info_st {
char *tlsname; /* Curve Name as in TLS specs */

View File

@ -1856,8 +1856,8 @@ int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0;
}
if (EVP_PKEY_set1_encoded_public_key(skey, PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt)) <= 0) {
if (tls13_set_encoded_pub_key(skey, PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt)) <= 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);
EVP_PKEY_free(skey);
return 0;

View File

@ -665,9 +665,9 @@ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
return 0;
}
if (EVP_PKEY_set1_encoded_public_key(s->s3.peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt)) <= 0) {
if (tls13_set_encoded_pub_key(s->s3.peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt)) <= 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_ECPOINT);
return 0;
}

View File

@ -3532,3 +3532,22 @@ int ssl_get_EC_curve_nid(const EVP_PKEY *pkey)
return NID_undef;
}
__owur int tls13_set_encoded_pub_key(EVP_PKEY *pkey,
const unsigned char *enckey,
size_t enckeylen)
{
if (EVP_PKEY_is_a(pkey, "DH")) {
int bits = EVP_PKEY_get_bits(pkey);
if (bits <= 0 || enckeylen != (size_t)bits / 8)
/* the encoded key must be padded to the length of the p */
return 0;
} else if (EVP_PKEY_is_a(pkey, "EC")) {
if (enckeylen < 3 /* point format and at least 1 byte for x and y */
|| enckey[0] != 0x04)
return 0;
}
return EVP_PKEY_set1_encoded_public_key(pkey, enckey, enckeylen);
}