diff options
Diffstat (limited to 'openssl/ssl/s2_srvr.c')
-rw-r--r-- | openssl/ssl/s2_srvr.c | 104 |
1 files changed, 51 insertions, 53 deletions
diff --git a/openssl/ssl/s2_srvr.c b/openssl/ssl/s2_srvr.c index 19bb48c9c..4289272b7 100644 --- a/openssl/ssl/s2_srvr.c +++ b/openssl/ssl/s2_srvr.c @@ -111,6 +111,7 @@ #include "ssl_locl.h" #ifndef OPENSSL_NO_SSL2 +#include "../crypto/constant_time_locl.h" # include <stdio.h> # include <openssl/bio.h> # include <openssl/rand.h> @@ -372,12 +373,15 @@ int ssl2_accept(SSL *s) static int get_client_master_key(SSL *s) { int is_export, i, n, keya; - unsigned int ek; + unsigned int num_encrypted_key_bytes, key_length; unsigned long len; unsigned char *p; const SSL_CIPHER *cp; const EVP_CIPHER *c; const EVP_MD *md; + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char decrypt_good; + size_t j; p = (unsigned char *)s->init_buf->data; if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A) { @@ -465,12 +469,6 @@ static int get_client_master_key(SSL *s) return (0); } - if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) { - is_export = 1; - ek = 8; - } else - ek = 5; - /* * The format of the CLIENT-MASTER-KEY message is * 1 byte message type @@ -484,12 +482,27 @@ static int get_client_master_key(SSL *s) * * 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). + * this portion is in |num_encrypted_key_bytes|. 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 != (unsigned int)EVP_CIPHER_key_length(c))) { + key_length = (unsigned int)EVP_CIPHER_key_length(c); + if (key_length > SSL_MAX_MASTER_KEY_LENGTH) { + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) { + is_export = 1; + num_encrypted_key_bytes = 8; + } else if (is_export) { + num_encrypted_key_bytes = 5; + } else { + num_encrypted_key_bytes = key_length; + } + + if (s->s2->tmp.clear + num_encrypted_key_bytes != key_length) { ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH); return -1; @@ -499,64 +512,49 @@ static int get_client_master_key(SSL *s) * 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 < (unsigned int)EVP_CIPHER_key_length(c))) { + if (s->s2->tmp.enc < num_encrypted_key_bytes) { ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT); return -1; } + /* + * We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt + * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 + */ + + /* + * should be RAND_bytes, but we cannot work around a failure. + */ + if (RAND_pseudo_bytes(rand_premaster_secret, + (int)num_encrypted_key_bytes) <= 0) + return 0; + 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 + ERR_clear_error(); /* * 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 != (int)ek))) { - ERR_clear_error(); - if (is_export) - i = ek; - else - i = EVP_CIPHER_key_length(c); - if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0) - return 0; - } -# else - if (i < 0) { - error = 1; - SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_BAD_RSA_DECRYPT); - } - /* incorrect number of key bytes for non export cipher */ - else if ((!is_export && (i != EVP_CIPHER_key_length(c))) - || (is_export && ((i != ek) || (s->s2->tmp.clear + i != - EVP_CIPHER_key_length(c))))) { - error = 1; - SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_WRONG_NUMBER_OF_KEY_BITS); - } - if (error) { - ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); - return (-1); + decrypt_good = constant_time_eq_int_8(i, (int)num_encrypted_key_bytes); + for (j = 0; j < num_encrypted_key_bytes; j++) { + p[s->s2->tmp.clear + j] = + constant_time_select_8(decrypt_good, p[s->s2->tmp.clear + j], + rand_premaster_secret[j]); } -# endif - if (is_export) - i = EVP_CIPHER_key_length(c); + s->session->master_key_length = (int)key_length; + memcpy(s->session->master_key, p, key_length); + OPENSSL_cleanse(p, key_length); - if (i > SSL_MAX_MASTER_KEY_LENGTH) { - ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); - SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); - return -1; - } - s->session->master_key_length = i; - memcpy(s->session->master_key, p, (unsigned int)i); - return (1); + return 1; } static int get_client_hello(SSL *s) |