[openssl-commits] [openssl] OpenSSL_1_0_2-stable update
Emilia Kasper
emilia at openssl.org
Wed Apr 8 14:43:13 UTC 2015
The branch OpenSSL_1_0_2-stable has been updated
via ae50d8270026edf5b3c7f8aaa0c6677462b33d97 (commit)
from ff864ffef33b4b09bb31ca3b0e17e1c85b65c2c8 (commit)
- Log -----------------------------------------------------------------
commit ae50d8270026edf5b3c7f8aaa0c6677462b33d97
Author: Emilia Kasper <emilia at openssl.org>
Date: Wed Apr 1 17:08:45 2015 +0200
Harden SSLv2-supporting servers against Bleichenbacher's attack.
There is no indication that the timing differences are exploitable in
OpenSSL, and indeed there is some indication (Usenix '14) that they
are too small to be exploitable. Nevertheless, be careful and apply
the same countermeasures as in s3_srvr.c
Thanks to Nimrod Aviram, Sebastian Schinzel and Yuval Shavitt for
reporting this issue.
Reviewed-by: Richard Levitte <levitte at openssl.org>
-----------------------------------------------------------------------
Summary of changes:
ssl/s2_srvr.c | 104 ++++++++++++++++++++++++++++------------------------------
1 file changed, 51 insertions(+), 53 deletions(-)
diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c
index 19bb48c..4289272 100644
--- a/ssl/s2_srvr.c
+++ b/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)
More information about the openssl-commits
mailing list