Fix ABI break with HMAC
[openssl.git] / ssl / s2_srvr.c
index daba6dd7addc6177d1cc465a5b6ea60adc094a13..4289272b73d3dc29691de99d29a37ecf8090fefd 100644 (file)
 
 #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>
@@ -371,12 +372,16 @@ int ssl2_accept(SSL *s)
 
 static int get_client_master_key(SSL *s)
 {
-    int is_export, i, n, keya, ek;
+    int is_export, i, n, keya;
+    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) {
@@ -454,11 +459,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);
 
@@ -469,60 +469,92 @@ static int get_client_master_key(SSL *s)
         return (0);
     }
 
+    /*
+     * 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 |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).
+     */
+    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;
-        ek = 8;
-    } else
-        ek = 5;
+        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;
+    }
+    /*
+     * 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 (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;
+    }
 
-    /* bad decrypt */
-# if 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);
+    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 != ek)
-                                      || (s->s2->tmp.clear +
-                                          (unsigned int)i != (unsigned int)
-                                          EVP_CIPHER_key_length(c)))))) {
-        ERR_clear_error();
-        if (is_export)
-            i = ek;
-        else
-            i = EVP_CIPHER_key_length(c);
-        if (RAND_pseudo_bytes(p, i) <= 0)
-            return 0;
+    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]);
     }
-# 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);
-    }
-# endif
 
-    if (is_export)
-        i += s->s2->tmp.clear;
+    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)