Skip to content
Permalink
Browse files

Fix reachable assert in SSLv2 servers.

This assert is reachable for servers that support SSLv2 and export ciphers.
Therefore, such servers can be DoSed by sending a specially crafted
SSLv2 CLIENT-MASTER-KEY.

Also fix s2_srvr.c to error out early if the key lengths are malformed.
These lengths are sent unencrypted, so this does not introduce an oracle.

CVE-2015-0293

This issue was discovered by Sean Burford (Google) and Emilia Käsper of
the OpenSSL development team.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
  • Loading branch information
ekasper authored and mattcaswell committed Mar 19, 2015
1 parent c0334c2 commit 86f8fb0e344d62454f8daf3e15236b2b59210756
Showing with 46 additions and 13 deletions.
  1. +1 −1 ssl/s2_lib.c
  2. +45 −12 ssl/s2_srvr.c
@@ -493,7 +493,7 @@ int ssl2_generate_key_material(SSL *s)

OPENSSL_assert(s->session->master_key_length >= 0
&& s->session->master_key_length
< (int)sizeof(s->session->master_key));
<= (int)sizeof(s->session->master_key));
EVP_DigestUpdate(&ctx, s->session->master_key,
s->session->master_key_length);
EVP_DigestUpdate(&ctx, &c, 1);
@@ -454,11 +454,6 @@ static int get_client_master_key(SSL *s)
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_PRIVATEKEY);
return (-1);
}
i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc,
&(p[s->s2->tmp.clear]),
&(p[s->s2->tmp.clear]),
(s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING :
RSA_PKCS1_PADDING);

is_export = SSL_C_IS_EXPORT(s->session->cipher);

@@ -475,23 +470,61 @@ static int get_client_master_key(SSL *s)
} else
ek = 5;

/*
* The format of the CLIENT-MASTER-KEY message is
* 1 byte message type
* 3 bytes cipher
* 2-byte clear key length (stored in s->s2->tmp.clear)
* 2-byte encrypted key length (stored in s->s2->tmp.enc)
* 2-byte key args length (IV etc)
* clear key
* encrypted key
* key args
*
* If the cipher is an export cipher, then the encrypted key bytes
* are a fixed portion of the total key (5 or 8 bytes). The size of
* this portion is in |ek|. If the cipher is not an export cipher,
* then the entire key material is encrypted (i.e., clear key length
* must be zero).
*/
if ((!is_export && s->s2->tmp.clear != 0) ||
(is_export && s->s2->tmp.clear + ek != EVP_CIPHER_key_length(c))) {
ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH);
return -1;
}
/*
* The encrypted blob must decrypt to the encrypted portion of the key.
* Decryption can't be expanding, so if we don't have enough encrypted
* bytes to fit the key in the buffer, stop now.
*/
if ((is_export && s->s2->tmp.enc < ek) ||
(!is_export && s->s2->tmp.enc < EVP_CIPHER_key_length(c))) {
ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT);
return -1;
}

i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc,
&(p[s->s2->tmp.clear]),
&(p[s->s2->tmp.clear]),
(s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING :
RSA_PKCS1_PADDING);

/* bad decrypt */
# if 1
/*
* If a bad decrypt, continue with protocol but with a random master
* secret (Bleichenbacher attack)
*/
if ((i < 0) || ((!is_export && (i != EVP_CIPHER_key_length(c)))
|| (is_export && ((i != ek)
|| (s->s2->tmp.clear +
(unsigned int)i != (unsigned int)
EVP_CIPHER_key_length(c)))))) {
if ((i < 0) || ((!is_export && i != EVP_CIPHER_key_length(c))
|| (is_export && i != ek))) {
ERR_clear_error();
if (is_export)
i = ek;
else
i = EVP_CIPHER_key_length(c);
if (RAND_pseudo_bytes(p, i) <= 0)
if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0)
return 0;
}
# else
@@ -513,7 +546,7 @@ static int get_client_master_key(SSL *s)
# endif

if (is_export)
i += s->s2->tmp.clear;
i = EVP_CIPHER_key_length(c);

if (i > SSL_MAX_MASTER_KEY_LENGTH) {
ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);

0 comments on commit 86f8fb0

Please sign in to comment.