Only allow ephemeral RSA keys in export ciphersuites.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 23 Oct 2014 16:09:57 +0000 (17:09 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 6 Jan 2015 13:27:22 +0000 (13:27 +0000)
OpenSSL clients would tolerate temporary RSA keys in non-export
ciphersuites. It also had an option SSL_OP_EPHEMERAL_RSA which
enabled this server side. Remove both options as they are a
protocol violation.

Thanks to Karthikeyan Bhargavan for reporting this issue.
(CVE-2015-0204)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(cherry picked from commit 4b4c1fcc88aec8c9e001b0a0077d3cd4de1ed0e6)

Conflicts:
CHANGES
doc/ssl/SSL_CTX_set_options.pod
ssl/d1_srvr.c
ssl/s3_srvr.c

CHANGES
doc/ssl/SSL_CTX_set_options.pod
doc/ssl/SSL_CTX_set_tmp_rsa_callback.pod
ssl/d1_srvr.c
ssl/s3_clnt.c
ssl/s3_srvr.c
ssl/ssl.h

diff --git a/CHANGES b/CHANGES
index 75da406b620b91d90e3f4a58afa87a52871fe3e7..ea460d68808166b7c51428083a28edd18b47bb3c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
      (CVE-2014-3572)
      [Steve Henson]
 
+  *) Remove non-export ephemeral RSA code on client and server. This code
+     violated the TLS standard by allowing the use of temporary RSA keys in
+     non-export ciphersuites and could be used by a server to effectively
+     downgrade the RSA key length used to a value smaller than the server
+     certificate. Thanks for Karthikeyan Bhargavan for reporting this issue.
+     (CVE-2015-0204)
+     [Steve Henson]
+
   *) Fix various certificate fingerprint issues.
 
      By using non-DER or invalid encodings outside the signed portion of a
index a2a570b610eecd39cd90752ba4f20852a0a538e8..307b157c5d58fd736e3e3f6369fe245f0f5fde0d 100644 (file)
@@ -152,15 +152,7 @@ temporary/ephemeral DH parameters are used.
 
 =item SSL_OP_EPHEMERAL_RSA
 
-Always use ephemeral (temporary) RSA key when doing RSA operations
-(see L<SSL_CTX_set_tmp_rsa_callback(3)|SSL_CTX_set_tmp_rsa_callback(3)>).
-According to the specifications this is only done, when a RSA key
-can only be used for signature operations (namely under export ciphers
-with restricted RSA keylength). By setting this option, ephemeral
-RSA keys are always used. This option breaks compatibility with the
-SSL/TLS specifications and may lead to interoperability problems with
-clients and should therefore never be used. Ciphers with EDH (ephemeral
-Diffie-Hellman) key exchange should be used instead.
+This option is no longer implemented and is treated as no op.
 
 =item SSL_OP_CIPHER_SERVER_PREFERENCE
 
index 534643cd9de4a2fd05192036502650d0f6642999..8794eb7ac360bc0e8ea924e5a305ca573255b983 100644 (file)
@@ -74,21 +74,14 @@ exchange and use EDH (Ephemeral Diffie-Hellman) key exchange instead
 in order to achieve forward secrecy (see
 L<SSL_CTX_set_tmp_dh_callback(3)|SSL_CTX_set_tmp_dh_callback(3)>).
 
-On OpenSSL servers ephemeral RSA key exchange is therefore disabled by default
-and must be explicitly enabled  using the SSL_OP_EPHEMERAL_RSA option of
-L<SSL_CTX_set_options(3)|SSL_CTX_set_options(3)>, violating the TLS/SSL
-standard. When ephemeral RSA key exchange is required for export ciphers,
-it will automatically be used without this option!
-
-An application may either directly specify the key or can supply the key via
-a callback function. The callback approach has the advantage, that the
-callback may generate the key only in case it is actually needed. As the
-generation of a RSA key is however costly, it will lead to a significant
-delay in the handshake procedure.  Another advantage of the callback function
-is that it can supply keys of different size (e.g. for SSL_OP_EPHEMERAL_RSA
-usage) while the explicit setting of the key is only useful for key size of
-512 bits to satisfy the export restricted ciphers and does give away key length
-if a longer key would be allowed.
+An application may either directly specify the key or can supply the key via a
+callback function. The callback approach has the advantage, that the callback
+may generate the key only in case it is actually needed. As the generation of a
+RSA key is however costly, it will lead to a significant delay in the handshake
+procedure.  Another advantage of the callback function is that it can supply
+keys of different size while the explicit setting of the key is only useful for
+key size of 512 bits to satisfy the export restricted ciphers and does give
+away key length if a longer key would be allowed.
 
 The B<tmp_rsa_callback> is called with the B<keylength> needed and
 the B<is_export> information. The B<is_export> flag is set, when the
index 0e6bf46c028b7884a01bd29a4934700ad3e9d896..0e9bb204add7b6abe40983399827383edb0679aa 100644 (file)
@@ -371,23 +371,11 @@ int dtls1_accept(SSL *s)
 
                        /* clear this, it may get reset by
                         * send_server_key_exchange */
-                       if ((s->options & SSL_OP_EPHEMERAL_RSA)
-#ifndef OPENSSL_NO_KRB5
-                               && !(l & SSL_KRB5)
-#endif /* OPENSSL_NO_KRB5 */
-                               )
-                               /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
-                                * even when forbidden by protocol specs
-                                * (handshake may fail as clients are not required to
-                                * be able to handle this) */
-                               s->s3->tmp.use_rsa_tmp=1;
-                       else
-                               s->s3->tmp.use_rsa_tmp=0;
+                       s->s3->tmp.use_rsa_tmp=0;
 
                        /* only send if a DH key exchange, fortezza or
                         * RSA but we have a sign only certificate */
-                       if (s->s3->tmp.use_rsa_tmp
-                           || (l & (SSL_DH|SSL_kFZA))
+                       if ((l & (SSL_DH|SSL_kFZA))
                            || ((l & SSL_kRSA)
                                && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
                                    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
index 256fc94e26693229b4ed5e1538b12bb75e82697c..2402a06163a5c4d0f23cccc41129e1285593975f 100644 (file)
@@ -1180,6 +1180,13 @@ int ssl3_get_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_RSA
        if (alg & SSL_kRSA)
                {
+               /* Temporary RSA keys only allowed in export ciphersuites */
+               if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher))
+                       {
+                       al=SSL_AD_UNEXPECTED_MESSAGE;
+                       SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNEXPECTED_MESSAGE);
+                       goto f_err;
+                       }
                if ((rsa=RSA_new()) == NULL)
                        {
                        SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
index ca3e77aef668e329f424ea39f3df2cc542b40314..18832e910b9cc67a853ee0177e670ced99617918 100644 (file)
@@ -355,18 +355,7 @@ int ssl3_accept(SSL *s)
 
                        /* clear this, it may get reset by
                         * send_server_key_exchange */
-                       if ((s->options & SSL_OP_EPHEMERAL_RSA)
-#ifndef OPENSSL_NO_KRB5
-                               && !(l & SSL_KRB5)
-#endif /* OPENSSL_NO_KRB5 */
-                               )
-                               /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
-                                * even when forbidden by protocol specs
-                                * (handshake may fail as clients are not required to
-                                * be able to handle this) */
-                               s->s3->tmp.use_rsa_tmp=1;
-                       else
-                               s->s3->tmp.use_rsa_tmp=0;
+                       s->s3->tmp.use_rsa_tmp=0;
 
 
                        /* only send if a DH key exchange, fortezza or
@@ -378,8 +367,7 @@ int ssl3_accept(SSL *s)
                         * server certificate contains the server's 
                         * public key for key exchange.
                         */
-                       if (s->s3->tmp.use_rsa_tmp
-                           || (l & SSL_kECDHE)
+                       if ((l & SSL_kECDHE)
                            || (l & (SSL_DH|SSL_kFZA))
                            || ((l & SSL_kRSA)
                                && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
index 4ea0d80124e23e696079e54a57ac41f54b79ae32..8420100cf01a6aef81f675560f5282fd266e7d1d 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -526,9 +526,8 @@ typedef struct ssl_session_st
 #define SSL_OP_SINGLE_ECDH_USE                         0x00080000L
 /* If set, always create a new key when using tmp_dh parameters */
 #define SSL_OP_SINGLE_DH_USE                           0x00100000L
-/* Set to always use the tmp_rsa key when doing RSA operations,
- * even when this violates protocol specs */
-#define SSL_OP_EPHEMERAL_RSA                           0x00200000L
+/* Does nothing: retained for compatibiity */
+#define SSL_OP_EPHEMERAL_RSA                           0x0
 /* Set on servers to choose the cipher according to the server's
  * preferences */
 #define SSL_OP_CIPHER_SERVER_PREFERENCE                        0x00400000L