Do not resume a session if the negotiated protocol version does not match
[openssl.git] / ssl / s3_srvr.c
index c907f2bb5b43a015d099d42d6ef1abd75086e13a..59ff27138145ba777b2a8d7c7547858170e3f348 100644 (file)
 #include <stdio.h>
 #include "ssl_locl.h"
 #include "kssl_lcl.h"
+#include "../crypto/constant_time_locl.h"
 #include <openssl/buffer.h>
 #include <openssl/rand.h>
 #include <openssl/objects.h>
 #endif
 #include <openssl/md5.h>
 
+#ifndef OPENSSL_NO_SSL3_METHOD
 static const SSL_METHOD *ssl3_get_server_method(int ver);
 
 static const SSL_METHOD *ssl3_get_server_method(int ver)
@@ -179,6 +181,12 @@ static const SSL_METHOD *ssl3_get_server_method(int ver)
                return(NULL);
        }
 
+IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
+                       ssl3_accept,
+                       ssl_undefined_function,
+                       ssl3_get_server_method)
+#endif
+
 #ifndef OPENSSL_NO_SRP
 static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
        {
@@ -205,11 +213,6 @@ static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
        }
 #endif
 
-IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
-                       ssl3_accept,
-                       ssl_undefined_function,
-                       ssl3_get_server_method)
-
 int ssl3_accept(SSL *s)
        {
        BUF_MEM *buf;
@@ -297,6 +300,9 @@ int ssl3_accept(SSL *s)
 
                        s->init_num=0;
                        s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE;
+                       s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
+                       /* Should have been reset by ssl3_get_finished, too. */
+                       s->s3->change_cipher_spec = 0;
 
                        if (s->state != SSL_ST_RENEGOTIATE)
                                {
@@ -673,8 +679,14 @@ int ssl3_accept(SSL *s)
 
                case SSL3_ST_SR_CERT_VRFY_A:
                case SSL3_ST_SR_CERT_VRFY_B:
-
-                       s->s3->flags |= SSL3_FLAGS_CCS_OK;
+                       /*
+                        * This *should* be the first time we enable CCS, but be
+                        * extra careful about surrounding code changes. We need
+                        * to set this here because we don't know if we're
+                        * expecting a CertificateVerify or not.
+                        */
+                       if (!s->s3->change_cipher_spec)
+                               s->s3->flags |= SSL3_FLAGS_CCS_OK;
                        /* we should decide if we expected this one */
                        ret=ssl3_get_cert_verify(s);
                        if (ret <= 0) goto end;
@@ -693,6 +705,19 @@ int ssl3_accept(SSL *s)
 #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
                case SSL3_ST_SR_NEXT_PROTO_A:
                case SSL3_ST_SR_NEXT_PROTO_B:
+                       /*
+                        * Enable CCS for resumed handshakes with NPN.
+                        * In a full handshake with NPN, we end up here through
+                        * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was
+                        * already set. Receiving a CCS clears the flag, so make
+                        * sure not to re-enable it to ban duplicates.
+                        * s->s3->change_cipher_spec is set when a CCS is
+                        * processed in s3_pkt.c, and remains set until
+                        * the client's Finished message is read.
+                        */
+                       if (!s->s3->change_cipher_spec)
+                               s->s3->flags |= SSL3_FLAGS_CCS_OK;
+
                        ret=ssl3_get_next_proto(s);
                        if (ret <= 0) goto end;
                        s->init_num = 0;
@@ -702,7 +727,18 @@ int ssl3_accept(SSL *s)
 
                case SSL3_ST_SR_FINISHED_A:
                case SSL3_ST_SR_FINISHED_B:
-                       s->s3->flags |= SSL3_FLAGS_CCS_OK;
+                       /*
+                        * Enable CCS for resumed handshakes without NPN.
+                        * In a full handshake, we end up here through
+                        * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was
+                        * already set. Receiving a CCS clears the flag, so make
+                        * sure not to re-enable it to ban duplicates.
+                        * s->s3->change_cipher_spec is set when a CCS is
+                        * processed in s3_pkt.c, and remains set until
+                        * the client's Finished message is read.
+                        */
+                       if (!s->s3->change_cipher_spec)
+                               s->s3->flags |= SSL3_FLAGS_CCS_OK;
                        ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
                                SSL3_ST_SR_FINISHED_B);
                        if (ret <= 0) goto end;
@@ -774,7 +810,6 @@ int ssl3_accept(SSL *s)
 #else
                                if (s->s3->next_proto_neg_seen)
                                        {
-                                       s->s3->flags |= SSL3_FLAGS_CCS_OK;
                                        s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
                                        }
                                else
@@ -1016,7 +1051,16 @@ int ssl3_get_client_hello(SSL *s)
        else
                {
                i=ssl_get_prev_session(s, p, j, d + n);
-               if (i == 1)
+               /*
+                * Only resume if the session's version matches the negotiated
+                * version.
+                * RFC 5246 does not provide much useful advice on resumption
+                * with a different protocol version. It doesn't forbid it but
+                * the sanity of such behaviour would be questionable.
+                * In practice, clients do not accept a version mismatch and
+                * will abort the handshake with an error.
+                */
+               if (i == 1 && s->version == s->session->ssl_version)
                        { /* previous session */
                        s->hit=1;
                        }
@@ -2167,6 +2211,10 @@ int ssl3_get_client_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_RSA
        if (alg_k & SSL_kRSA)
                {
+               unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+               int decrypt_len;
+               unsigned char decrypt_good, version_good;
+
                /* FIX THIS UP EAY EAY EAY EAY */
                if (s->s3->tmp.use_rsa_tmp)
                        {
@@ -2214,54 +2262,61 @@ int ssl3_get_client_key_exchange(SSL *s)
                                n=i;
                        }
 
-               i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
-
-               al = -1;
-               
-               if (i != SSL_MAX_MASTER_KEY_LENGTH)
-                       {
-                       al=SSL_AD_DECODE_ERROR;
-                       /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */
-                       }
-
-               if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
-                       {
-                       /* The premaster secret must contain the same version number as the
-                        * ClientHello to detect version rollback attacks (strangely, the
-                        * protocol does not offer such protection for DH ciphersuites).
-                        * However, buggy clients exist that send the negotiated protocol
-                        * version instead if the server does not support the requested
-                        * protocol version.
-                        * If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
-                       if (!((s->options & SSL_OP_TLS_ROLLBACK_BUG) &&
-                               (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff))))
-                               {
-                               al=SSL_AD_DECODE_ERROR;
-                               /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */
+               /* 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 */
 
-                               /* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
-                                * (http://eprint.iacr.org/2003/052/) exploits the version
-                                * number check as a "bad version oracle" -- an alert would
-                                * reveal that the plaintext corresponding to some ciphertext
-                                * made up by the adversary is properly formatted except
-                                * that the version number is wrong.  To avoid such attacks,
-                                * we should treat this just like any other decryption error. */
-                               }
+               /* should be RAND_bytes, but we cannot work around a failure. */
+               if (RAND_pseudo_bytes(rand_premaster_secret,
+                                     sizeof(rand_premaster_secret)) <= 0)
+                       goto err;
+               decrypt_len = RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
+               ERR_clear_error();
+
+               /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
+                * decrypt_good will be 0xff if so and zero otherwise. */
+               decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);
+
+               /* If the version in the decrypted pre-master secret is correct
+                * then version_good will be 0xff, otherwise it'll be zero.
+                * The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
+                * (http://eprint.iacr.org/2003/052/) exploits the version
+                * number check as a "bad version oracle". Thus version checks
+                * are done in constant time and are treated like any other
+                * decryption error. */
+               version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
+               version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));
+
+               /* The premaster secret must contain the same version number as
+                * the ClientHello to detect version rollback attacks
+                * (strangely, the protocol does not offer such protection for
+                * DH ciphersuites). However, buggy clients exist that send the
+                * negotiated protocol version instead if the server does not
+                * support the requested protocol version. If
+                * SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
+               if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
+                       {
+                       unsigned char workaround_good;
+                       workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8));
+                       workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff));
+                       version_good |= workaround_good;
+                       }
+
+               /* Both decryption and version must be good for decrypt_good
+                * to remain non-zero (0xff). */
+               decrypt_good &= version_good;
+
+               /* Now copy rand_premaster_secret over p using
+                * decrypt_good_mask. */
+               for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
+                       {
+                       p[i] = constant_time_select_8(decrypt_good, p[i],
+                                                     rand_premaster_secret[i]);
                        }
 
-               if (al != -1)
-                       {
-                       /* Some decryption failure -- use random value instead as countermeasure
-                        * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding
-                        * (see RFC 2246, section 7.4.7.1). */
-                       ERR_clear_error();
-                       i = SSL_MAX_MASTER_KEY_LENGTH;
-                       p[0] = s->client_version >> 8;
-                       p[1] = s->client_version & 0xff;
-                       if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */
-                               goto err;
-                       }
-       
                s->session->master_key_length=
                        s->method->ssl3_enc->generate_master_secret(s,
                                s->session->master_key,