Backport TLS v1.1 support from HEAD, ssl/ changes
authorDr. Stephen Henson <steve@openssl.org>
Sun, 27 Jun 2010 14:22:11 +0000 (14:22 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Sun, 27 Jun 2010 14:22:11 +0000 (14:22 +0000)
15 files changed:
ssl/s23_clnt.c
ssl/s23_meth.c
ssl/s23_srvr.c
ssl/s3_pkt.c
ssl/ssl.h
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/ssl_txt.c
ssl/t1_clnt.c
ssl/t1_enc.c
ssl/t1_lib.c
ssl/t1_meth.c
ssl/t1_srvr.c
ssl/tls1.h

index c4d8bf2..e6f9bf9 100644 (file)
@@ -129,6 +129,8 @@ static const SSL_METHOD *ssl23_get_client_method(int ver)
                return(SSLv3_client_method());
        else if (ver == TLS1_VERSION)
                return(TLSv1_client_method());
+       else if (ver == TLS1_1_VERSION)
+               return(TLSv1_1_client_method());
        else
                return(NULL);
        }
@@ -284,7 +286,11 @@ static int ssl23_client_hello(SSL *s)
        if (ssl2_compat && ssl23_no_ssl2_ciphers(s))
                ssl2_compat = 0;
 
-       if (!(s->options & SSL_OP_NO_TLSv1))
+       if (!(s->options & SSL_OP_NO_TLSv1_1))
+               {
+               version = TLS1_1_VERSION;
+               }
+       else if (!(s->options & SSL_OP_NO_TLSv1))
                {
                version = TLS1_VERSION;
                }
@@ -329,7 +335,12 @@ static int ssl23_client_hello(SSL *s)
                if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
                        return -1;
 
-               if (version == TLS1_VERSION)
+               if (version == TLS1_1_VERSION)
+                       {
+                       version_major = TLS1_1_VERSION_MAJOR;
+                       version_minor = TLS1_1_VERSION_MINOR;
+                       }
+               else if (version == TLS1_VERSION)
                        {
                        version_major = TLS1_VERSION_MAJOR;
                        version_minor = TLS1_VERSION_MINOR;
@@ -608,7 +619,7 @@ static int ssl23_get_server_hello(SSL *s)
 #endif
                }
        else if (p[1] == SSL3_VERSION_MAJOR &&
-                (p[2] == SSL3_VERSION_MINOR || p[2] == TLS1_VERSION_MINOR) &&
+                (p[2] >= SSL3_VERSION_MINOR && p[2] <= TLS1_1_VERSION_MINOR) &&
                 ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
                  (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2)))
                {
@@ -626,6 +637,12 @@ static int ssl23_get_server_hello(SSL *s)
                        s->version=TLS1_VERSION;
                        s->method=TLSv1_client_method();
                        }
+               else if ((p[2] == TLS1_1_VERSION_MINOR) &&
+                       !(s->options & SSL_OP_NO_TLSv1_1))
+                       {
+                       s->version=TLS1_1_VERSION;
+                       s->method=TLSv1_1_client_method();
+                       }
                else
                        {
                        SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
index c6099ef..a2b4b22 100644 (file)
@@ -76,6 +76,8 @@ static const SSL_METHOD *ssl23_get_method(int ver)
 #ifndef OPENSSL_NO_TLS1
        if (ver == TLS1_VERSION)
                return(TLSv1_method());
+       else if (ver == TLS1_1_VERSION)
+               return(TLSv1_1_method());
        else
 #endif
                return(NULL);
index 836dd1f..390b99b 100644 (file)
@@ -128,6 +128,8 @@ static const SSL_METHOD *ssl23_get_server_method(int ver)
                return(SSLv3_server_method());
        else if (ver == TLS1_VERSION)
                return(TLSv1_server_method());
+       else if (ver == TLS1_1_VERSION)
+               return(TLSv1_1_server_method());
        else
                return(NULL);
        }
@@ -283,7 +285,13 @@ int ssl23_get_client_hello(SSL *s)
                                /* SSLv3/TLSv1 */
                                if (p[4] >= TLS1_VERSION_MINOR)
                                        {
-                                       if (!(s->options & SSL_OP_NO_TLSv1))
+                                       if (p[4] >= TLS1_1_VERSION_MINOR &&
+                                          !(s->options & SSL_OP_NO_TLSv1_1))
+                                               {
+                                               s->version=TLS1_1_VERSION;
+                                               s->state=SSL23_ST_SR_CLNT_HELLO_B;
+                                               }
+                                       else if (!(s->options & SSL_OP_NO_TLSv1))
                                                {
                                                s->version=TLS1_VERSION;
                                                /* type=2; */ /* done later to survive restarts */
@@ -350,7 +358,13 @@ int ssl23_get_client_hello(SSL *s)
                                v[1]=p[10]; /* minor version according to client_version */
                        if (v[1] >= TLS1_VERSION_MINOR)
                                {
-                               if (!(s->options & SSL_OP_NO_TLSv1))
+                               if (v[1] >= TLS1_1_VERSION_MINOR &&
+                                       !(s->options & SSL_OP_NO_TLSv1_1))
+                                       {
+                                       s->version=TLS1_1_VERSION;
+                                       type=3;
+                                       }
+                               else if (!(s->options & SSL_OP_NO_TLSv1))
                                        {
                                        s->version=TLS1_VERSION;
                                        type=3;
@@ -568,7 +582,9 @@ int ssl23_get_client_hello(SSL *s)
                        s->s3->rbuf.offset=0;
                        }
 
-               if (s->version == TLS1_VERSION)
+               if (s->version == TLS1_1_VERSION)
+                       s->method = TLSv1_1_server_method();
+               else if (s->version == TLS1_VERSION)
                        s->method = TLSv1_server_method();
                else
                        s->method = SSLv3_server_method();
index e3f6050..b30c032 100644 (file)
 #include "ssl_locl.h"
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
+#include <openssl/rand.h>
 
 static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
                         unsigned int len, int create_empty_fragment);
@@ -629,6 +630,7 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        unsigned char *p,*plen;
        int i,mac_size,clear=0;
        int prefix_len=0;
+       int eivlen;
        long align=0;
        SSL3_RECORD *wr;
        SSL3_BUFFER *wb=&(s->s3->wbuf);
@@ -738,9 +740,18 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        /* field where we are to write out packet length */
        plen=p; 
        p+=2;
+       /* Explicit IV length, block ciphers and TLS version 1.1 or later */
+       if (s->enc_write_ctx && s->version >= TLS1_1_VERSION)
+               {
+               eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
+               if (eivlen <= 1)
+                       eivlen = 0;
+               }
+       else 
+               eivlen = 0;
 
        /* lets setup the record stuff. */
-       wr->data=p;
+       wr->data=p + eivlen;
        wr->length=(int)len;
        wr->input=(unsigned char *)buf;
 
@@ -768,11 +779,19 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
 
        if (mac_size != 0)
                {
-               if (s->method->ssl3_enc->mac(s,&(p[wr->length]),1) < 0)
+               if (s->method->ssl3_enc->mac(s,&(p[wr->length + eivlen]),1) < 0)
                        goto err;
                wr->length+=mac_size;
-               wr->input=p;
-               wr->data=p;
+               }
+
+       wr->input=p;
+       wr->data=p;
+
+       if (eivlen)
+               {
+       /*      if (RAND_pseudo_bytes(p, eivlen) <= 0)
+                       goto err; */
+               wr->length += eivlen;
                }
 
        /* ssl3_enc can only have an error on read */
@@ -1295,7 +1314,7 @@ start:
        default:
 #ifndef OPENSSL_NO_TLS
                /* TLS just ignores unknown message types */
-               if (s->version == TLS1_VERSION)
+               if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION)
                        {
                        rr->length = 0;
                        goto start;
index e4c3f65..761c6f3 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -298,6 +298,7 @@ extern "C" {
 #define SSL_TXT_SSLV2          "SSLv2"
 #define SSL_TXT_SSLV3          "SSLv3"
 #define SSL_TXT_TLSV1          "TLSv1"
+#define SSL_TXT_TLSV1_1                "TLSv1.1"
 
 #define SSL_TXT_EXP            "EXP"
 #define SSL_TXT_EXPORT         "EXPORT"
@@ -526,6 +527,7 @@ typedef struct ssl_session_st
 #define SSL_OP_SSLEAY_080_CLIENT_DH_BUG                        0x00000080L
 #define SSL_OP_TLS_D5_BUG                              0x00000100L
 #define SSL_OP_TLS_BLOCK_PADDING_BUG                   0x00000200L
+#define SSL_OP_NO_TLSv1_1                              0x00000400L
 
 /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added
  * in OpenSSL 0.9.6d.  Usually (depending on the application protocol)
@@ -536,7 +538,7 @@ typedef struct ssl_session_st
 
 /* SSL_OP_ALL: various bug workarounds that should be rather harmless.
  *             This used to be 0x000FFFFFL before 0.9.7. */
-#define SSL_OP_ALL                                     0x80000FFFL
+#define SSL_OP_ALL                                     0x80000BFFL
 
 /* DTLS options */
 #define SSL_OP_NO_QUERY_MTU                 0x00001000L
@@ -1647,6 +1649,10 @@ const SSL_METHOD *TLSv1_method(void);            /* TLSv1.0 */
 const SSL_METHOD *TLSv1_server_method(void);   /* TLSv1.0 */
 const SSL_METHOD *TLSv1_client_method(void);   /* TLSv1.0 */
 
+const SSL_METHOD *TLSv1_1_method(void);                /* TLSv1.1 */
+const SSL_METHOD *TLSv1_1_server_method(void); /* TLSv1.1 */
+const SSL_METHOD *TLSv1_1_client_method(void); /* TLSv1.1 */
+
 const SSL_METHOD *DTLSv1_method(void);         /* DTLSv1.0 */
 const SSL_METHOD *DTLSv1_server_method(void);  /* DTLSv1.0 */
 const SSL_METHOD *DTLSv1_client_method(void);  /* DTLSv1.0 */
index 912592b..3c74ec1 100644 (file)
@@ -2423,8 +2423,10 @@ SSL_METHOD *ssl_bad_method(int ver)
 
 const char *SSL_get_version(const SSL *s)
        {
-       if (s->version == TLS1_VERSION)
-               return("TLSv1");
+       if (s->version == TLS1_1_VERSION)
+               return("TLSv1.1");
+       else if (s->version == SSL3_VERSION)
+               return("SSLv3");
        else if (s->version == SSL3_VERSION)
                return("SSLv3");
        else if (s->version == SSL2_VERSION)
index 4c78393..41f0f77 100644 (file)
@@ -591,11 +591,12 @@ extern SSL3_ENC_METHOD TLSv1_enc_data;
 extern SSL3_ENC_METHOD SSLv3_enc_data;
 extern SSL3_ENC_METHOD DTLSv1_enc_data;
 
-#define IMPLEMENT_tls1_meth_func(func_name, s_accept, s_connect, s_get_meth) \
+#define IMPLEMENT_tls_meth_func(version, func_name, s_accept, s_connect, \
+                               s_get_meth) \
 const SSL_METHOD *func_name(void)  \
        { \
        static const SSL_METHOD func_name##_data= { \
-               TLS1_VERSION, \
+               version, \
                tls1_new, \
                tls1_clear, \
                tls1_free, \
@@ -669,7 +670,7 @@ const SSL_METHOD *func_name(void)  \
 const SSL_METHOD *func_name(void)  \
        { \
        static const SSL_METHOD func_name##_data= { \
-       TLS1_VERSION, \
+       TLS1_1_VERSION, \
        tls1_new, \
        tls1_clear, \
        tls1_free, \
index 8e5d8a0..56b9e15 100644 (file)
@@ -300,6 +300,11 @@ int ssl_get_new_session(SSL *s, int session)
                        ss->ssl_version=TLS1_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        }
+               else if (s->version == TLS1_1_VERSION)
+                       {
+                       ss->ssl_version=TLS1_1_VERSION;
+                       ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+                       }
                else if (s->version == DTLS1_BAD_VER)
                        {
                        ss->ssl_version=DTLS1_BAD_VER;
index 3122440..cab712b 100644 (file)
@@ -115,6 +115,8 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
                s="SSLv2";
        else if (x->ssl_version == SSL3_VERSION)
                s="SSLv3";
+       else if (x->ssl_version == TLS1_1_VERSION)
+               s="TLSv1.1";
        else if (x->ssl_version == TLS1_VERSION)
                s="TLSv1";
        else if (x->ssl_version == DTLS1_VERSION)
index c87af17..b06bada 100644 (file)
 static const SSL_METHOD *tls1_get_client_method(int ver);
 static const SSL_METHOD *tls1_get_client_method(int ver)
        {
+       if (ver == TLS1_1_VERSION)
+               return TLSv1_1_client_method();
        if (ver == TLS1_VERSION)
-               return(TLSv1_client_method());
-       else
-               return(NULL);
+               return TLSv1_client_method();
+       return NULL;
        }
 
-IMPLEMENT_tls1_meth_func(TLSv1_client_method,
+IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_client_method,
+                       ssl_undefined_function,
+                       ssl3_connect,
+                       tls1_get_client_method)
+
+IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_client_method,
                        ssl_undefined_function,
                        ssl3_connect,
                        tls1_get_client_method)
index 793ea43..b5c3179 100644 (file)
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
+#include <openssl/rand.h>
 #ifdef KSSL_DEBUG
 #include <openssl/des.h>
 #endif
@@ -655,7 +656,27 @@ int tls1_enc(SSL *s, int send)
                if (s->enc_write_ctx == NULL)
                        enc=NULL;
                else
+                       {
+                       int ivlen;
                        enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+                       /* For TLSv1.1 and later explicit IV */
+                       if (s->version >= TLS1_1_VERSION)
+                               ivlen = EVP_CIPHER_iv_length(enc);
+                       else
+                               ivlen = 0;
+                       if (ivlen > 1)
+                               {
+                               if ( rec->data != rec->input)
+                               /* we can't write into the input stream:
+                                * Can this ever happen?? (steve)
+                                */
+                               fprintf(stderr,
+                                       "%s:%d: rec->data != rec->input\n",
+                                       __FILE__, __LINE__);
+                               else if (RAND_bytes(rec->input, ivlen) <= 0)
+                                       return -1;
+                               }
+                       }
                }
        else
                {
@@ -784,7 +805,13 @@ int tls1_enc(SSL *s, int send)
                                        return -1;
                                        }
                                }
-                       rec->length-=i;
+                       rec->length -=i;
+                       if (s->version >= TLS1_1_VERSION)
+                               {
+                               rec->data += bs;    /* skip the explicit IV */
+                               rec->input += bs;
+                               rec->length -= bs;
+                               }
                        }
                }
        return(1);
index e395287..ef40e5e 100644 (file)
@@ -166,7 +166,7 @@ void tls1_free(SSL *s)
 void tls1_clear(SSL *s)
        {
        ssl3_clear(s);
-       s->version=TLS1_VERSION;
+       s->version = s->method->version;
        }
 
 #ifndef OPENSSL_NO_EC
index 6ce7c0b..3257636 100644 (file)
 #include <openssl/objects.h>
 #include "ssl_locl.h"
 
-static const SSL_METHOD *tls1_get_method(int ver);
 static const SSL_METHOD *tls1_get_method(int ver)
        {
+       if (ver == TLS1_1_VERSION)
+               return TLSv1_1_method();
        if (ver == TLS1_VERSION)
-               return(TLSv1_method());
-       else
-               return(NULL);
+               return TLSv1_method();
+       return NULL;
        }
 
-IMPLEMENT_tls1_meth_func(TLSv1_method,
+IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method,
+                       ssl3_accept,
+                       ssl3_connect,
+                       tls1_get_method)
+
+IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_method,
                        ssl3_accept,
                        ssl3_connect,
                        tls1_get_method)
index 42525e9..274a3d6 100644 (file)
 static const SSL_METHOD *tls1_get_server_method(int ver);
 static const SSL_METHOD *tls1_get_server_method(int ver)
        {
+       if (ver == TLS1_1_VERSION)
+               return TLSv1_1_server_method();
        if (ver == TLS1_VERSION)
-               return(TLSv1_server_method());
-       else
-               return(NULL);
+               return TLSv1_server_method();
+       return NULL;
        }
 
-IMPLEMENT_tls1_meth_func(TLSv1_server_method,
+IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_server_method,
+                       ssl3_accept,
+                       ssl_undefined_function,
+                       tls1_get_server_method)
+
+IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_server_method,
                        ssl3_accept,
                        ssl_undefined_function,
                        tls1_get_server_method)
index b3cc8f0..b32b713 100644 (file)
@@ -159,6 +159,10 @@ extern "C" {
 
 #define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES   0
 
+#define TLS1_1_VERSION                 0x0302
+#define TLS1_1_VERSION_MAJOR           0x03
+#define TLS1_1_VERSION_MINOR           0x02
+
 #define TLS1_VERSION                   0x0301
 #define TLS1_VERSION_MAJOR             0x03
 #define TLS1_VERSION_MINOR             0x01