Backport TLS v1.2 support from HEAD.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 11 May 2011 13:37:52 +0000 (13:37 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 11 May 2011 13:37:52 +0000 (13:37 +0000)
This includes TLS v1.2 server and client support but at present
client certificate support is not implemented.

28 files changed:
CHANGES
apps/s_cb.c
apps/s_client.c
apps/s_server.c
ssl/d1_srvr.c
ssl/s23_clnt.c
ssl/s23_meth.c
ssl/s23_srvr.c
ssl/s3_clnt.c
ssl/s3_enc.c
ssl/s3_lib.c
ssl/s3_pkt.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssl_cert.c
ssl/ssl_ciph.c
ssl/ssl_err.c
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

diff --git a/CHANGES b/CHANGES
index deda5ac..5f41869 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,26 @@
  _______________
 
  Changes between 1.0.0d and 1.0.1  [xx XXX xxxx]
+
+  *) Initial TLS v1.2 client support. Add a default signature algorithms
+     extension including all the algorithms we support. Parse new signature
+     format in client key exchange. Relax some ECC signing restrictions for
+     TLS v1.2 as indicated in RFC5246.
+     [Steve Henson]
+
+  *) Add server support for TLS v1.2 signature algorithms extension. Switch
+     to new signature format when needed using client digest preference.
+     All server ciphersuites should now work correctly in TLS v1.2. No client
+     support yet and no support for client certificates.
+     [Steve Henson]
+
+  *) Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch
+     to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based
+     ciphersuites. At present only RSA key exchange ciphersuites work with
+     TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete
+     SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods
+     and version checking.
+     [Steve Henson]
  
   *) New option OPENSSL_NO_SSL_INTERN. If an application can be compiled
      with this defined it will not be affected by any changes to ssl internal
index c4f5512..865c418 100644 (file)
@@ -673,6 +673,10 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
                extname = "renegotiate";
                break;
 
+               case TLSEXT_TYPE_signature_algorithms:
+               extname = "signature algorithms";
+               break;
+
 #ifdef TLSEXT_TYPE_opaque_prf_input
                case TLSEXT_TYPE_opaque_prf_input:
                extname = "opaque PRF input";
index d108534..55869b4 100644 (file)
@@ -328,11 +328,12 @@ static void sc_usage(void)
 #endif
        BIO_printf(bio_err," -ssl2         - just use SSLv2\n");
        BIO_printf(bio_err," -ssl3         - just use SSLv3\n");
+       BIO_printf(bio_err," -tls1_2       - just use TLSv1.2\n");
        BIO_printf(bio_err," -tls1_1       - just use TLSv1.1\n");
        BIO_printf(bio_err," -tls1         - just use TLSv1\n");
        BIO_printf(bio_err," -dtls1        - just use DTLSv1\n");    
        BIO_printf(bio_err," -mtu          - set the link layer MTU\n");
-       BIO_printf(bio_err," -no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
+       BIO_printf(bio_err," -no_tls1_2/-no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
        BIO_printf(bio_err," -bugs         - Switch on all SSL implementation bug workarounds\n");
        BIO_printf(bio_err," -serverpref   - Use server's cipher preferences (only SSLv2)\n");
        BIO_printf(bio_err," -cipher       - preferred cipher to use, use the 'openssl ciphers'\n");
@@ -750,6 +751,8 @@ int MAIN(int argc, char **argv)
                        meth=SSLv3_client_method();
 #endif
 #ifndef OPENSSL_NO_TLS1
+               else if (strcmp(*argv,"-tls1_2") == 0)
+                       meth=TLSv1_2_client_method();
                else if (strcmp(*argv,"-tls1_1") == 0)
                        meth=TLSv1_1_client_method();
                else if (strcmp(*argv,"-tls1") == 0)
@@ -800,6 +803,8 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        CAfile= *(++argv);
                        }
+               else if (strcmp(*argv,"-no_tls1_2") == 0)
+                       off|=SSL_OP_NO_TLSv1_2;
                else if (strcmp(*argv,"-no_tls1_1") == 0)
                        off|=SSL_OP_NO_TLSv1_1;
                else if (strcmp(*argv,"-no_tls1") == 0)
@@ -1036,6 +1041,9 @@ bad:
                SSL_CTX_set_psk_client_callback(ctx, psk_client_cb);
                }
 #endif
+       /* HACK while TLS v1.2 is disabled by default */
+       if (!(off & SSL_OP_NO_TLSv1_2))
+               SSL_CTX_clear_options(ctx, SSL_OP_NO_TLSv1_2);
        if (bugs)
                SSL_CTX_set_options(ctx,SSL_OP_ALL|off);
        else
@@ -1927,6 +1935,19 @@ static void print_stuff(BIO *bio, SSL *s, int full)
        BIO_printf(bio,"Expansion: %s\n",
                expansion ? SSL_COMP_get_name(expansion) : "NONE");
 #endif
+#ifdef SSL_DEBUG
+       {
+       /* Print out local port of connection: useful for debugging */
+       int sock;
+       struct sockaddr_in ladd;
+       socklen_t ladd_size = sizeof(ladd);
+       sock = SSL_get_fd(s);
+       getsockname(sock, (struct sockaddr *)&ladd, &ladd_size);
+       BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port));
+       }
+#endif
+
        SSL_SESSION_print(bio,SSL_get_session(s));
        BIO_printf(bio,"---\n");
        if (peer != NULL)
index b7730f1..39fdc0d 100644 (file)
@@ -499,6 +499,7 @@ static void sv_usage(void)
 #endif
        BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
        BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
+       BIO_printf(bio_err," -tls1_2       - Just talk TLSv1.2\n");
        BIO_printf(bio_err," -tls1_1       - Just talk TLSv1.1\n");
        BIO_printf(bio_err," -tls1         - Just talk TLSv1\n");
        BIO_printf(bio_err," -dtls1        - Just talk DTLSv1\n");
@@ -509,6 +510,7 @@ static void sv_usage(void)
        BIO_printf(bio_err," -no_ssl3      - Just disable SSLv3\n");
        BIO_printf(bio_err," -no_tls1      - Just disable TLSv1\n");
        BIO_printf(bio_err," -no_tls1_1    - Just disable TLSv1.1\n");
+       BIO_printf(bio_err," -no_tls1_2    - Just disable TLSv1.2\n");
 #ifndef OPENSSL_NO_DH
        BIO_printf(bio_err," -no_dhe       - Disable ephemeral DH\n");
 #endif
@@ -1190,6 +1192,8 @@ int MAIN(int argc, char *argv[])
                        { off|=SSL_OP_NO_TLSv1; }
                else if (strcmp(*argv,"-no_tls1_1") == 0)
                        { off|=SSL_OP_NO_TLSv1_1; }
+               else if (strcmp(*argv,"-no_tls1_2") == 0)
+                       { off|=SSL_OP_NO_TLSv1_2; }
                else if (strcmp(*argv,"-no_comp") == 0)
                        { off|=SSL_OP_NO_COMPRESSION; }
 #ifndef OPENSSL_NO_TLSEXT
@@ -1209,6 +1213,8 @@ int MAIN(int argc, char *argv[])
                        { meth=TLSv1_server_method(); }
                else if (strcmp(*argv,"-tls1_1") == 0)
                        { meth=TLSv1_1_server_method(); }
+               else if (strcmp(*argv,"-tls1_2") == 0)
+                       { meth=TLSv1_2_server_method(); }
 #endif
 #ifndef OPENSSL_NO_DTLS1
                else if (strcmp(*argv,"-dtls1") == 0)
@@ -1457,6 +1463,9 @@ bad:
        SSL_CTX_set_quiet_shutdown(ctx,1);
        if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL);
        if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
+       /* HACK while TLS v1.2 is disabled by default */
+       if (!(off & SSL_OP_NO_TLSv1_2))
+               SSL_CTX_clear_options(ctx, SSL_OP_NO_TLSv1_2);
        SSL_CTX_set_options(ctx,off);
        /* DTLS: partial reads end up discarding unread UDP bytes :-( 
         * Setting read ahead solves this problem.
index f6d72f5..2d63199 100644 (file)
@@ -1139,7 +1139,7 @@ int dtls1_send_server_key_exchange(SSL *s)
                if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
                        && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
                        {
-                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher, NULL))
                                == NULL)
                                {
                                al=SSL_AD_DECODE_ERROR;
index 47f9389..f49a95b 100644 (file)
@@ -131,6 +131,8 @@ static const SSL_METHOD *ssl23_get_client_method(int ver)
                return(TLSv1_client_method());
        else if (ver == TLS1_1_VERSION)
                return(TLSv1_1_client_method());
+       else if (ver == TLS1_2_VERSION)
+               return(TLSv1_2_client_method());
        else
                return(NULL);
        }
@@ -286,7 +288,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_1))
+       if (!(s->options & SSL_OP_NO_TLSv1_2))
+               {
+               version = TLS1_2_VERSION;
+               }
+       else if (!(s->options & SSL_OP_NO_TLSv1_1))
                {
                version = TLS1_1_VERSION;
                }
@@ -335,7 +341,12 @@ static int ssl23_client_hello(SSL *s)
                if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
                        return -1;
 
-               if (version == TLS1_1_VERSION)
+               if (version == TLS1_2_VERSION)
+                       {
+                       version_major = TLS1_2_VERSION_MAJOR;
+                       version_minor = TLS1_2_VERSION_MINOR;
+                       }
+               else if (version == TLS1_1_VERSION)
                        {
                        version_major = TLS1_1_VERSION_MAJOR;
                        version_minor = TLS1_1_VERSION_MINOR;
@@ -619,7 +630,7 @@ static int ssl23_get_server_hello(SSL *s)
 #endif
                }
        else if (p[1] == SSL3_VERSION_MAJOR &&
-                p[2] <= TLS1_1_VERSION_MINOR &&
+                p[2] <= TLS1_2_VERSION_MINOR &&
                 ((p[0] == SSL3_RT_HANDSHAKE && p[5] == SSL3_MT_SERVER_HELLO) ||
                  (p[0] == SSL3_RT_ALERT && p[3] == 0 && p[4] == 2)))
                {
@@ -643,6 +654,12 @@ static int ssl23_get_server_hello(SSL *s)
                        s->version=TLS1_1_VERSION;
                        s->method=TLSv1_1_client_method();
                        }
+               else if ((p[2] == TLS1_2_VERSION_MINOR) &&
+                       !(s->options & SSL_OP_NO_TLSv1_2))
+                       {
+                       s->version=TLS1_2_VERSION;
+                       s->method=TLSv1_2_client_method();
+                       }
                else
                        {
                        SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_UNSUPPORTED_PROTOCOL);
index a2b4b22..40eae0f 100644 (file)
@@ -78,6 +78,8 @@ static const SSL_METHOD *ssl23_get_method(int ver)
                return(TLSv1_method());
        else if (ver == TLS1_1_VERSION)
                return(TLSv1_1_method());
+       else if (ver == TLS1_2_VERSION)
+               return(TLSv1_2_method());
        else
 #endif
                return(NULL);
index 390b99b..b21c57a 100644 (file)
@@ -130,6 +130,8 @@ static const SSL_METHOD *ssl23_get_server_method(int ver)
                return(TLSv1_server_method());
        else if (ver == TLS1_1_VERSION)
                return(TLSv1_1_server_method());
+       else if (ver == TLS1_2_VERSION)
+               return(TLSv1_2_server_method());
        else
                return(NULL);
        }
@@ -285,10 +287,17 @@ int ssl23_get_client_hello(SSL *s)
                                /* SSLv3/TLSv1 */
                                if (p[4] >= TLS1_VERSION_MINOR)
                                        {
-                                       if (p[4] >= TLS1_1_VERSION_MINOR &&
+                                       if (p[4] >= TLS1_2_VERSION_MINOR &&
+                                          !(s->options & SSL_OP_NO_TLSv1_2))
+                                               {
+                                               s->version=TLS1_2_VERSION;
+                                               s->state=SSL23_ST_SR_CLNT_HELLO_B;
+                                               }
+                                       else if (p[4] >= TLS1_1_VERSION_MINOR &&
                                           !(s->options & SSL_OP_NO_TLSv1_1))
                                                {
                                                s->version=TLS1_1_VERSION;
+                                               /* type=2; */ /* done later to survive restarts */
                                                s->state=SSL23_ST_SR_CLNT_HELLO_B;
                                                }
                                        else if (!(s->options & SSL_OP_NO_TLSv1))
@@ -358,7 +367,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 (v[1] >= TLS1_1_VERSION_MINOR &&
+                               if (v[1] >= TLS1_2_VERSION_MINOR &&
+                                       !(s->options & SSL_OP_NO_TLSv1_2))
+                                       {
+                                       s->version=TLS1_2_VERSION;
+                                       type=3;
+                                       }
+                               else if (v[1] >= TLS1_1_VERSION_MINOR &&
                                        !(s->options & SSL_OP_NO_TLSv1_1))
                                        {
                                        s->version=TLS1_1_VERSION;
@@ -581,8 +596,9 @@ int ssl23_get_client_hello(SSL *s)
                        s->s3->rbuf.left=0;
                        s->s3->rbuf.offset=0;
                        }
-
-               if (s->version == TLS1_1_VERSION)
+               if (s->version == TLS1_2_VERSION)
+                       s->method = TLSv1_2_server_method();
+               else if (s->version == TLS1_1_VERSION)
                        s->method = TLSv1_1_server_method();
                else if (s->version == TLS1_VERSION)
                        s->method = TLSv1_server_method();
index 121ffb2..b8e2b89 100644 (file)
@@ -1185,6 +1185,7 @@ int ssl3_get_key_exchange(SSL *s)
        int al,i,j,param_len,ok;
        long n,alg_k,alg_a;
        EVP_PKEY *pkey=NULL;
+       const EVP_MD *md = NULL;
 #ifndef OPENSSL_NO_RSA
        RSA *rsa=NULL;
 #endif
@@ -1635,6 +1636,38 @@ int ssl3_get_key_exchange(SSL *s)
        /* if it was signed, check the signature */
        if (pkey != NULL)
                {
+               if (s->version >= TLS1_2_VERSION)
+                       {
+                       int sigalg = tls12_get_sigid(pkey);
+                       /* Should never happen */
+                       if (sigalg == -1)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+                               goto err;
+                               }
+                       /* Check key type is consistent with signature */
+                       if (sigalg != (int)p[1])
+                               {
+                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
+                               al=SSL_AD_DECODE_ERROR;
+                               goto f_err;
+                               }
+                       md = tls12_get_hash(p[0]);
+                       if (md == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
+                               al=SSL_AD_DECODE_ERROR;
+                               goto f_err;
+                               }
+#ifdef SSL_DEBUG
+fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
+#endif
+                       p += 2;
+                       n -= 2;
+                       }
+               else
+                       md = EVP_sha1();
+                       
                n2s(p,i);
                n-=2;
                j=EVP_PKEY_size(pkey);
@@ -1648,7 +1681,7 @@ int ssl3_get_key_exchange(SSL *s)
                        }
 
 #ifndef OPENSSL_NO_RSA
-               if (pkey->type == EVP_PKEY_RSA)
+               if (pkey->type == EVP_PKEY_RSA && s->version < TLS1_2_VERSION)
                        {
                        int num;
 
@@ -1683,29 +1716,8 @@ int ssl3_get_key_exchange(SSL *s)
                        }
                else
 #endif
-#ifndef OPENSSL_NO_DSA
-                       if (pkey->type == EVP_PKEY_DSA)
-                       {
-                       /* lets do DSS */
-                       EVP_VerifyInit_ex(&md_ctx,EVP_dss1(), NULL);
-                       EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
-                       EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-                       EVP_VerifyUpdate(&md_ctx,param,param_len);
-                       if (EVP_VerifyFinal(&md_ctx,p,(int)n,pkey) <= 0)
-                               {
-                               /* bad signature */
-                               al=SSL_AD_DECRYPT_ERROR;
-                               SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SIGNATURE);
-                               goto f_err;
-                               }
-                       }
-               else
-#endif
-#ifndef OPENSSL_NO_ECDSA
-                       if (pkey->type == EVP_PKEY_EC)
                        {
-                       /* let's do ECDSA */
-                       EVP_VerifyInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+                       EVP_VerifyInit_ex(&md_ctx, md, NULL);
                        EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                        EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
                        EVP_VerifyUpdate(&md_ctx,param,param_len);
@@ -1717,12 +1729,6 @@ int ssl3_get_key_exchange(SSL *s)
                                goto f_err;
                                }
                        }
-               else
-#endif
-                       {
-                       SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
-                       goto err;
-                       }
                }
        else
                {
@@ -1769,7 +1775,7 @@ int ssl3_get_certificate_request(SSL *s)
        {
        int ok,ret=0;
        unsigned long n,nc,l;
-       unsigned int llen,ctype_num,i;
+       unsigned int llen,sigalglen, ctype_num,i;
        X509_NAME *xn=NULL;
        const unsigned char *p,*q;
        unsigned char *d;
@@ -1825,6 +1831,17 @@ int ssl3_get_certificate_request(SSL *s)
        for (i=0; i<ctype_num; i++)
                s->s3->tmp.ctype[i]= p[i];
        p+=ctype_num;
+       /* HACK! For now just skip over signatature algorithms */
+       if (s->version >= TLS1_2_VERSION)
+               {
+               n2s(p, sigalglen);
+               p += sigalglen;
+               sigalglen += 2;
+               }
+       else
+               sigalglen = 0;
+               
+               
 
        /* get the CA RDNs */
        n2s(p,llen);
@@ -1837,7 +1854,7 @@ fclose(out);
 }
 #endif
 
-       if ((llen+ctype_num+2+1) != n)
+       if ((llen+ctype_num+sigalglen+2+1) != n)
                {
                ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
                SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_LENGTH_MISMATCH);
@@ -3041,7 +3058,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
        if (idx == SSL_PKEY_ECC)
                {
                if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
-                   s->s3->tmp.new_cipher) == 0) 
+                                                               s) == 0) 
                        { /* check failed */
                        SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_BAD_ECC_CERT);
                        goto f_err;
index 58386e1..ac5ae40 100644 (file)
@@ -610,7 +610,7 @@ int ssl3_digest_cached_records(SSL *s)
        /* Loop through bitso of algorithm2 field and create MD_CTX-es */
        for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) 
                {
-               if ((mask & s->s3->tmp.new_cipher->algorithm2) && md) 
+               if ((mask & ssl_get_algorithm2(s)) && md) 
                        {
                        s->s3->handshake_dgst[i]=EVP_MD_CTX_create();
                        EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL);
index 87d19c7..0f4e302 100644 (file)
@@ -1071,6 +1071,103 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
        256,
        },
 
+       /* TLS v1.2 ciphersuites */
+       /* Cipher 3B */
+       {
+       1,
+       TLS1_TXT_RSA_WITH_NULL_SHA256,
+       TLS1_CK_RSA_WITH_NULL_SHA256,
+       SSL_kRSA,
+       SSL_aRSA,
+       SSL_eNULL,
+       SSL_SHA256,
+       SSL_SSLV3,
+       SSL_NOT_EXP|SSL_STRONG_NONE|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       0,
+       0,
+       },
+
+       /* Cipher 3C */
+       {
+       1,
+       TLS1_TXT_RSA_WITH_AES_128_SHA256,
+       TLS1_CK_RSA_WITH_AES_128_SHA256,
+       SSL_kRSA,
+       SSL_aRSA,
+       SSL_AES128,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       128,
+       128,
+       },
+
+       /* Cipher 3D */
+       {
+       1,
+       TLS1_TXT_RSA_WITH_AES_256_SHA256,
+       TLS1_CK_RSA_WITH_AES_256_SHA256,
+       SSL_kRSA,
+       SSL_aRSA,
+       SSL_AES256,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       256,
+       256,
+       },
+
+       /* Cipher 3E */
+       {
+       0, /* not implemented (non-ephemeral DH) */
+       TLS1_TXT_DH_DSS_WITH_AES_128_SHA256,
+       TLS1_CK_DH_DSS_WITH_AES_128_SHA256,
+       SSL_kDHr,
+       SSL_aDH,
+       SSL_AES128,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       128,
+       128,
+       },
+
+       /* Cipher 3F */
+       {
+       0, /* not implemented (non-ephemeral DH) */
+       TLS1_TXT_DH_RSA_WITH_AES_128_SHA256,
+       TLS1_CK_DH_RSA_WITH_AES_128_SHA256,
+       SSL_kDHr,
+       SSL_aDH,
+       SSL_AES128,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       128,
+       128,
+       },
+
+       /* Cipher 40 */
+       {
+       1,
+       TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256,
+       TLS1_CK_DHE_DSS_WITH_AES_128_SHA256,
+       SSL_kEDH,
+       SSL_aDSS,
+       SSL_AES128,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       128,
+       128,
+       },
+
 #ifndef OPENSSL_NO_CAMELLIA
        /* Camellia ciphersuites from RFC4132 (128-bit portion) */
 
@@ -1287,6 +1384,122 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
        128,
        },
 #endif
+
+       /* TLS v1.2 ciphersuites */
+       /* Cipher 67 */
+       {
+       1,
+       TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
+       TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
+       SSL_kEDH,
+       SSL_aRSA,
+       SSL_AES128,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       128,
+       128,
+       },
+
+       /* Cipher 68 */
+       {
+       0, /* not implemented (non-ephemeral DH) */
+       TLS1_TXT_DH_DSS_WITH_AES_256_SHA256,
+       TLS1_CK_DH_DSS_WITH_AES_256_SHA256,
+       SSL_kDHr,
+       SSL_aDH,
+       SSL_AES256,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       256,
+       256,
+       },
+
+       /* Cipher 69 */
+       {
+       0, /* not implemented (non-ephemeral DH) */
+       TLS1_TXT_DH_RSA_WITH_AES_256_SHA256,
+       TLS1_CK_DH_RSA_WITH_AES_256_SHA256,
+       SSL_kDHr,
+       SSL_aDH,
+       SSL_AES256,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       256,
+       256,
+       },
+
+       /* Cipher 6A */
+       {
+       1,
+       TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256,
+       TLS1_CK_DHE_DSS_WITH_AES_256_SHA256,
+       SSL_kEDH,
+       SSL_aDSS,
+       SSL_AES256,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       256,
+       256,
+       },
+
+       /* Cipher 6B */
+       {
+       1,
+       TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256,
+       TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
+       SSL_kEDH,
+       SSL_aRSA,
+       SSL_AES256,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       256,
+       256,
+       },
+
+       /* Cipher 6C */
+       {
+       1,
+       TLS1_TXT_ADH_WITH_AES_128_SHA256,
+       TLS1_CK_ADH_WITH_AES_128_SHA256,
+       SSL_kEDH,
+       SSL_aNULL,
+       SSL_AES128,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       128,
+       128,
+       },
+
+       /* Cipher 6D */
+       {
+       1,
+       TLS1_TXT_ADH_WITH_AES_256_SHA256,
+       TLS1_CK_ADH_WITH_AES_256_SHA256,
+       SSL_kEDH,
+       SSL_aNULL,
+       SSL_AES256,
+       SSL_SHA256,
+       SSL_TLSV1,
+       SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+       SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
+       256,
+       256,
+       },
+
+       /* GOST Ciphersuites */
+
        {
        1,
        "GOST94-GOST89-GOST89",
@@ -3005,6 +3218,9 @@ const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p)
        id=0x03000000L|((unsigned long)p[0]<<8L)|(unsigned long)p[1];
        c.id=id;
        cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS);
+#ifdef DEBUG_PRINT_UNKNOWN_CIPHERSUITES
+if (cp == NULL) fprintf(stderr, "Unknown cipher ID %x\n", (p[0] << 8) | p[1]);
+#endif
        if (cp == NULL || cp->valid == 0)
                return NULL;
        else
@@ -3539,3 +3755,15 @@ need to go to SSL_ST_ACCEPT.
                }
        return(ret);
        }
+/* If we are using TLS v1.2 or later and default SHA1+MD5 algorithms switch
+ * to new SHA256 PRF and handshake macs
+ */
+long ssl_get_algorithm2(SSL *s)
+       {
+       long alg2 = s->s3->tmp.new_cipher->algorithm2;
+       if (s->version >= TLS1_2_VERSION &&
+           alg2 == (SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF))
+               return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
+       return alg2;
+       }
+               
index a1b4a65..e166a51 100644 (file)
@@ -1319,7 +1319,9 @@ start:
                {
        default:
 #ifndef OPENSSL_NO_TLS
-               /* TLS just ignores unknown message types */
+               /* TLS up to v1.1 just ignores unknown message types:
+                * TLS v1.2 give an unexpected message alert.
+                */
                if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION)
                        {
                        rr->length = 0;
index a0d09e0..3107df9 100644 (file)
@@ -1486,6 +1486,7 @@ int ssl3_send_server_key_exchange(SSL *s)
        BN_CTX *bn_ctx = NULL; 
 #endif
        EVP_PKEY *pkey;
+       const EVP_MD *md = NULL;
        unsigned char *p,*d;
        int al,i;
        unsigned long type;
@@ -1766,7 +1767,7 @@ int ssl3_send_server_key_exchange(SSL *s)
                if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
                        && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
                        {
-                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher))
+                       if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
                                == NULL)
                                {
                                al=SSL_AD_DECODE_ERROR;
@@ -1844,7 +1845,8 @@ int ssl3_send_server_key_exchange(SSL *s)
                        /* n is the length of the params, they start at &(d[4])
                         * and p points to the space at the end. */
 #ifndef OPENSSL_NO_RSA
-                       if (pkey->type == EVP_PKEY_RSA)
+                       if (pkey->type == EVP_PKEY_RSA
+                                       && s->version < TLS1_2_VERSION)
                                {
                                q=md_buf;
                                j=0;
@@ -1871,44 +1873,41 @@ int ssl3_send_server_key_exchange(SSL *s)
                                }
                        else
 #endif
-#if !defined(OPENSSL_NO_DSA)
-                               if (pkey->type == EVP_PKEY_DSA)
+                       if (md)
                                {
-                               /* lets do DSS */
-                               EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
-                               EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
-                               EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
-                               EVP_SignUpdate(&md_ctx,&(d[4]),n);
-                               if (!EVP_SignFinal(&md_ctx,&(p[2]),
-                                       (unsigned int *)&i,pkey))
+                               /* For TLS1.2 and later send signature
+                                * algorithm */
+                               if (s->version >= TLS1_2_VERSION)
                                        {
-                                       SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA);
-                                       goto err;
+                                       if (!tls12_get_sigandhash(p, pkey, md))
+                                               {
+                                               /* Should never happen */
+                                               al=SSL_AD_INTERNAL_ERROR;
+                                               SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+                                               goto f_err;
+                                               }
+                                       p+=2;
                                        }
-                               s2n(i,p);
-                               n+=i+2;
-                               }
-                       else
+#ifdef SSL_DEBUG
+                               fprintf(stderr, "Using hash %s\n",
+                                                       EVP_MD_name(md));
 #endif
-#if !defined(OPENSSL_NO_ECDSA)
-                               if (pkey->type == EVP_PKEY_EC)
-                               {
-                               /* let's do ECDSA */
-                               EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL);
+                               EVP_SignInit_ex(&md_ctx, md, NULL);
                                EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                                EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
                                EVP_SignUpdate(&md_ctx,&(d[4]),n);
                                if (!EVP_SignFinal(&md_ctx,&(p[2]),
                                        (unsigned int *)&i,pkey))
                                        {
-                                       SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA);
+                                       SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_EVP);
                                        goto err;
                                        }
                                s2n(i,p);
                                n+=i+2;
+                               if (s->version >= TLS1_2_VERSION)
+                                       n+= 2;
                                }
                        else
-#endif
                                {
                                /* Is this error check actually needed? */
                                al=SSL_AD_HANDSHAKE_FAILURE;
index 104e2ad..26e6077 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -296,11 +296,13 @@ extern "C" {
 #define SSL_TXT_SHA            "SHA" /* same as "SHA1" */
 #define SSL_TXT_GOST94         "GOST94" 
 #define SSL_TXT_GOST89MAC              "GOST89MAC" 
+#define SSL_TXT_SHA256         "SHA256"
 
 #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_TLSV1_2                "TLSv1.2"
 
 #define SSL_TXT_EXP            "EXP"
 #define SSL_TXT_EXPORT         "EXPORT"
@@ -588,11 +590,16 @@ struct ssl_session_st
 #define SSL_OP_NO_SSLv2                                        0x01000000L
 #define SSL_OP_NO_SSLv3                                        0x02000000L
 #define SSL_OP_NO_TLSv1                                        0x04000000L
+#define SSL_OP_NO_TLSv1_2                              0x08000000L
 
+/* These next two were never actually used for anything since SSLeay
+ * zap so we have some more flags.
+ */
 /* The next flag deliberately changes the ciphertest, this is a check
  * for the PKCS#1 attack */
-#define SSL_OP_PKCS1_CHECK_1                           0x08000000L
-#define SSL_OP_PKCS1_CHECK_2                           0x10000000L
+#define SSL_OP_PKCS1_CHECK_1                           0x0
+#define SSL_OP_PKCS1_CHECK_2                           0x0
+
 #define SSL_OP_NETSCAPE_CA_DN_BUG                      0x20000000L
 #define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG         0x40000000L
 /* Make server add server-hello extension from early version of
@@ -1768,6 +1775,11 @@ 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 *TLSv1_2_method(void);                /* TLSv1.2 */
+const SSL_METHOD *TLSv1_2_server_method(void); /* TLSv1.2 */
+const SSL_METHOD *TLSv1_2_client_method(void); /* TLSv1.2 */
+
+
 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 */
@@ -2412,6 +2424,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_UNKNOWN_CERTIFICATE_TYPE                  247
 #define SSL_R_UNKNOWN_CIPHER_RETURNED                   248
 #define SSL_R_UNKNOWN_CIPHER_TYPE                       249
+#define SSL_R_UNKNOWN_DIGEST                            357
 #define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE                         250
 #define SSL_R_UNKNOWN_PKEY_TYPE                                 251
 #define SSL_R_UNKNOWN_PROTOCOL                          252
@@ -2432,6 +2445,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_WRONG_NUMBER_OF_KEY_BITS                  263
 #define SSL_R_WRONG_SIGNATURE_LENGTH                    264
 #define SSL_R_WRONG_SIGNATURE_SIZE                      265
+#define SSL_R_WRONG_SIGNATURE_TYPE                      358
 #define SSL_R_WRONG_SSL_VERSION                                 266
 #define SSL_R_WRONG_VERSION_NUMBER                      267
 #define SSL_R_X509_LIB                                  268
index ae299cf..45fef15 100644 (file)
@@ -470,7 +470,7 @@ typedef struct ssl3_state_st
                int finish_md_len;
                unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2];
                int peer_finish_md_len;
-               
+
                unsigned long message_size;
                int message_type;
 
index 27256ee..917be31 100644 (file)
@@ -160,6 +160,21 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
        return ssl_x509_store_ctx_idx;
        }
 
+static void ssl_cert_set_default_md(CERT *cert)
+       {
+       /* Set digest values to defaults */
+#ifndef OPENSSL_NO_DSA
+       cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_RSA
+       cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+       cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_ECDSA
+       cert->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa();
+#endif
+       }
+
 CERT *ssl_cert_new(void)
        {
        CERT *ret;
@@ -174,7 +189,7 @@ CERT *ssl_cert_new(void)
 
        ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
        ret->references=1;
-
+       ssl_cert_set_default_md(ret);
        return(ret);
        }
 
@@ -307,6 +322,10 @@ CERT *ssl_cert_dup(CERT *cert)
         * chain is held inside SSL_CTX */
 
        ret->references=1;
+       /* Set digests to defaults. NB: we don't copy existing values as they
+        * will be set during handshake.
+        */
+       ssl_cert_set_default_md(ret);
 
        return(ret);
        
index 84829e5..38d5977 100644 (file)
@@ -179,28 +179,29 @@ static STACK_OF(SSL_COMP) *ssl_comp_methods=NULL;
 #define SSL_MD_SHA1_IDX        1
 #define SSL_MD_GOST94_IDX 2
 #define SSL_MD_GOST89MAC_IDX 3
+#define SSL_MD_SHA256_IDX 4
 /*Constant SSL_MAX_DIGEST equal to size of digests array should be 
  * defined in the
  * ssl_locl.h */
 #define SSL_MD_NUM_IDX SSL_MAX_DIGEST 
 static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX]={
-       NULL,NULL,NULL,NULL
+       NULL,NULL,NULL,NULL,NULL
        };
 /* PKEY_TYPE for GOST89MAC is known in advance, but, because
  * implementation is engine-provided, we'll fill it only if
  * corresponding EVP_PKEY_METHOD is found 
  */
 static int  ssl_mac_pkey_id[SSL_MD_NUM_IDX]={
-       EVP_PKEY_HMAC,EVP_PKEY_HMAC,EVP_PKEY_HMAC,NID_undef
+       EVP_PKEY_HMAC,EVP_PKEY_HMAC,EVP_PKEY_HMAC,NID_undef,EVP_PKEY_HMAC
        };
 
 static int ssl_mac_secret_size[SSL_MD_NUM_IDX]={
-       0,0,0,0
+       0,0,0,0,0
        };
 
 static int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={
        SSL_HANDSHAKE_MAC_MD5,SSL_HANDSHAKE_MAC_SHA,
-       SSL_HANDSHAKE_MAC_GOST94,0
+       SSL_HANDSHAKE_MAC_GOST94, 0, SSL_HANDSHAKE_MAC_SHA256
        };
 
 #define CIPHER_ADD     1
@@ -298,6 +299,7 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_SHA,0,     0,0,0,SSL_SHA1,  0,0,0,0,0},
        {0,SSL_TXT_GOST94,0,     0,0,0,SSL_GOST94,  0,0,0,0,0},
        {0,SSL_TXT_GOST89MAC,0,     0,0,0,SSL_GOST89MAC,  0,0,0,0,0},
+       {0,SSL_TXT_SHA256,0,    0,0,0,SSL_SHA256,  0,0,0,0,0},
 
        /* protocol version aliases */
        {0,SSL_TXT_SSLV2,0,   0,0,0,0,SSL_SSLV2, 0,0,0,0},
@@ -406,6 +408,10 @@ void ssl_load_ciphers(void)
                        ssl_mac_secret_size[SSL_MD_GOST89MAC_IDX]=32;
                }               
 
+       ssl_digest_methods[SSL_MD_SHA256_IDX]=
+               EVP_get_digestbyname(SN_sha256);
+       ssl_mac_secret_size[SSL_MD_SHA256_IDX]=
+               EVP_MD_size(ssl_digest_methods[SSL_MD_SHA256_IDX]);
        }
 #ifndef OPENSSL_NO_COMP
 
@@ -550,6 +556,9 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
        case SSL_SHA1:
                i=SSL_MD_SHA1_IDX;
                break;
+       case SSL_SHA256:
+               i=SSL_MD_SHA256_IDX;
+               break;
        case SSL_GOST94:
                i = SSL_MD_GOST94_IDX;
                break;
@@ -586,9 +595,11 @@ int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md)
                {
                return 0;
                }
-       if (ssl_handshake_digest_flag[idx]==0) return 0;
        *mask = ssl_handshake_digest_flag[idx];
-       *md = ssl_digest_methods[idx];
+       if (*mask)
+               *md = ssl_digest_methods[idx];
+       else
+               *md = NULL;
        return 1;
 }
 
@@ -698,6 +709,7 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, un
 
        *mac |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
        *mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
+       *mac |= (ssl_digest_methods[SSL_MD_SHA256_IDX] == NULL) ? SSL_SHA256:0;
        *mac |= (ssl_digest_methods[SSL_MD_GOST94_IDX] == NULL) ? SSL_GOST94:0;
        *mac |= (ssl_digest_methods[SSL_MD_GOST89MAC_IDX] == NULL || ssl_mac_pkey_id[SSL_MD_GOST89MAC_IDX]==NID_undef)? SSL_GOST89MAC:0;
 
@@ -1603,6 +1615,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
        case SSL_SHA1:
                mac="SHA1";
                break;
+       case SSL_SHA256:
+               mac="SHA256";
+               break;
        default:
                mac="unknown";
                break;
index 41b7d1d..46f45ce 100644 (file)
@@ -540,6 +540,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE),"unknown certificate type"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED),"unknown cipher returned"},
 {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE)   ,"unknown cipher type"},
+{ERR_REASON(SSL_R_UNKNOWN_DIGEST)        ,"unknown digest"},
 {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE),"unknown key exchange type"},
 {ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE)     ,"unknown pkey type"},
 {ERR_REASON(SSL_R_UNKNOWN_PROTOCOL)      ,"unknown protocol"},
@@ -560,6 +561,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS),"wrong number of key bits"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH),"wrong signature length"},
 {ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE)  ,"wrong signature size"},
+{ERR_REASON(SSL_R_WRONG_SIGNATURE_TYPE)  ,"wrong signature type"},
 {ERR_REASON(SSL_R_WRONG_SSL_VERSION)     ,"wrong ssl version"},
 {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER)  ,"wrong version number"},
 {ERR_REASON(SSL_R_X509_LIB)              ,"x509 lib"},
index b63beed..1c3e945 100644 (file)
@@ -1702,6 +1702,8 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
         * deployed might change this.
         */
        ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
+       /* Disable TLS v1.2 by default for now */
+       ret->options |= SSL_OP_NO_TLSv1_2;
 
        return(ret);
 err:
@@ -2051,12 +2053,13 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
 
 #ifndef OPENSSL_NO_EC
 
-int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs)
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
        {
        unsigned long alg_k, alg_a;
        EVP_PKEY *pkey = NULL;
        int keysize = 0;
        int signature_nid = 0;
+       const SSL_CIPHER *cs = s->s3->tmp.new_cipher;
 
        alg_k = cs->algorithm_mkey;
        alg_a = cs->algorithm_auth;
@@ -2083,7 +2086,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs)
                        SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG, SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT);
                        return 0;
                        }
-               if (alg_k & SSL_kECDHe)
+               if ((alg_k & SSL_kECDHe) && s->version < TLS1_2_VERSION)
                        {
                        /* signature alg must be ECDSA */
                        if (signature_nid != NID_ecdsa_with_SHA1)
@@ -2092,7 +2095,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs)
                                return 0;
                                }
                        }
-               if (alg_k & SSL_kECDHr)
+               if ((alg_k & SSL_kECDHr) && s->version < TLS1_2_VERSION)
                        {
                        /* signature alg must be RSA */
 
@@ -2188,34 +2191,36 @@ X509 *ssl_get_server_send_cert(SSL *s)
        return(c->pkeys[i].x509);
        }
 
-EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher)
+EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
        {
        unsigned long alg_a;
        CERT *c;
+       int idx = -1;
 
        alg_a = cipher->algorithm_auth;
        c=s->cert;
 
        if ((alg_a & SSL_aDSS) &&
                (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
-               return(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey);
+               idx = SSL_PKEY_DSA_SIGN;
        else if (alg_a & SSL_aRSA)
                {
                if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
-                       return(c->pkeys[SSL_PKEY_RSA_SIGN].privatekey);
+                       idx = SSL_PKEY_RSA_SIGN;
                else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
-                       return(c->pkeys[SSL_PKEY_RSA_ENC].privatekey);
-               else
-                       return(NULL);
+                       idx = SSL_PKEY_RSA_ENC;
                }
        else if ((alg_a & SSL_aECDSA) &&
                 (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
-               return(c->pkeys[SSL_PKEY_ECC].privatekey);
-       else /* if (alg_a & SSL_aNULL) */
+               idx = SSL_PKEY_ECC;
+       if (idx == -1)
                {
                SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
                return(NULL);
                }
+       if (pmd)
+               *pmd = c->pkeys[idx].digest;
+       return c->pkeys[idx].privatekey;
        }
 
 void ssl_update_cache(SSL *s,int mode)
@@ -2440,7 +2445,9 @@ SSL_METHOD *ssl_bad_method(int ver)
 
 const char *SSL_get_version(const SSL *s)
        {
-       if (s->version == TLS1_1_VERSION)
+       if (s->version == TLS1_2_VERSION)
+               return("TLSv1.2");
+       else if (s->version == TLS1_1_VERSION)
                return("TLSv1.1");
        if (s->version == TLS1_VERSION)
                return("TLSv1");
index fb8bd3b..8eb9860 100644 (file)
 # define OPENSSL_EXTERN OPENSSL_EXPORT
 #endif
 
-#define PKCS1_CHECK
+#undef PKCS1_CHECK
 
 #define c2l(c,l)       (l = ((unsigned long)(*((c)++)))     , \
                         l|=(((unsigned long)(*((c)++)))<< 8), \
 #define SSL_SHA1               0x00000002L
 #define SSL_GOST94      0x00000004L
 #define SSL_GOST89MAC   0x00000008L
+#define SSL_SHA256             0x00000010L
 
 /* Bits for algorithm_ssl (protocol version) */
 #define SSL_SSLV2              0x00000001L
 #define SSL_HANDSHAKE_MAC_MD5 0x10
 #define SSL_HANDSHAKE_MAC_SHA 0x20
 #define SSL_HANDSHAKE_MAC_GOST94 0x40
+#define SSL_HANDSHAKE_MAC_SHA256 0x80
 #define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA)
 
 /* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX
  * make sure to update this constant too */
-#define SSL_MAX_DIGEST 4
+#define SSL_MAX_DIGEST 5
 
 #define TLS1_PRF_DGST_MASK     (0xff << TLS1_PRF_DGST_SHIFT)
 
@@ -461,6 +463,8 @@ typedef struct cert_pkey_st
        {
        X509 *x509;
        EVP_PKEY *privatekey;
+       /* Digest to use when signing */
+       const EVP_MD *digest;
        } CERT_PKEY;
 
 typedef struct cert_st
@@ -674,7 +678,7 @@ const SSL_METHOD *func_name(void)  \
 const SSL_METHOD *func_name(void)  \
        { \
        static const SSL_METHOD func_name##_data= { \
-       TLS1_1_VERSION, \
+       TLS1_2_VERSION, \
        tls1_new, \
        tls1_clear, \
        tls1_free, \
@@ -814,7 +818,7 @@ int ssl_undefined_function(SSL *s);
 int ssl_undefined_void_function(void);
 int ssl_undefined_const_function(const SSL *s);
 X509 *ssl_get_server_send_cert(SSL *);
-EVP_PKEY *ssl_get_sign_pkey(SSL *,const SSL_CIPHER *);
+EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd);
 int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
 void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
 STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
@@ -1042,7 +1046,7 @@ int ssl3_alert_code(int code);
 int ssl_ok(SSL *s);
 
 #ifndef OPENSSL_NO_ECDH
-int ssl_check_srvr_ecc_cert_and_alg(X509 *x, const SSL_CIPHER *cs);
+int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
 #endif
 
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
@@ -1069,6 +1073,12 @@ int ssl_check_serverhello_tlsext(SSL *s);
 #endif
 int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
                                const unsigned char *limit, SSL_SESSION **ret);
+
+int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
+                               const EVP_MD *md);
+int tls12_get_sigid(const EVP_PKEY *pk);
+const EVP_MD *tls12_get_hash(unsigned char hash_alg);
+
 #endif
 EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
 void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
@@ -1080,4 +1090,5 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
                                        int maxlen);
 int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
                                          int *al);
+long ssl_get_algorithm2(SSL *s);
 #endif
index 3f0b195..cbb7e70 100644 (file)
@@ -308,6 +308,11 @@ int ssl_get_new_session(SSL *s, int session)
                        ss->ssl_version=TLS1_1_VERSION;
                        ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
                        }
+               else if (s->version == TLS1_2_VERSION)
+                       {
+                       ss->ssl_version=TLS1_2_VERSION;
+                       ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
+                       }
                else if (s->version == DTLS1_BAD_VER)
                        {
                        ss->ssl_version=DTLS1_BAD_VER;
index 552ec2b..6479d52 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_2_VERSION)
+               s="TLSv1.2";
        else if (x->ssl_version == TLS1_1_VERSION)
                s="TLSv1.1";
        else if (x->ssl_version == TLS1_VERSION)
index b06bada..578617e 100644 (file)
@@ -66,6 +66,8 @@
 static const SSL_METHOD *tls1_get_client_method(int ver);
 static const SSL_METHOD *tls1_get_client_method(int ver)
        {
+       if (ver == TLS1_2_VERSION)
+               return TLSv1_2_client_method();
        if (ver == TLS1_1_VERSION)
                return TLSv1_1_client_method();
        if (ver == TLS1_VERSION)
@@ -73,6 +75,11 @@ static const SSL_METHOD *tls1_get_client_method(int ver)
        return NULL;
        }
 
+IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_client_method,
+                       ssl_undefined_function,
+                       ssl3_connect,
+                       tls1_get_client_method)
+
 IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_client_method,
                        ssl_undefined_function,
                        ssl3_connect,
index 8950700..c60bccd 100644 (file)
@@ -291,7 +291,7 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km,
             unsigned char *tmp, int num)
        {
        int ret;
-       ret = tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       ret = tls1_PRF(ssl_get_algorithm2(s),
                 TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
                 s->s3->server_random,SSL3_RANDOM_SIZE,
                 s->s3->client_random,SSL3_RANDOM_SIZE,
@@ -494,7 +494,7 @@ printf("which = %04X\nmac key=",which);
                /* In here I set both the read and write key/iv to the
                 * same value since only the correct one will be used :-).
                 */
-               if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+               if (!tls1_PRF(ssl_get_algorithm2(s),
                                exp_label,exp_label_len,
                                s->s3->client_random,SSL3_RANDOM_SIZE,
                                s->s3->server_random,SSL3_RANDOM_SIZE,
@@ -505,7 +505,7 @@ printf("which = %04X\nmac key=",which);
 
                if (k > 0)
                        {
-                       if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+                       if (!tls1_PRF(ssl_get_algorithm2(s),
                                        TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
                                        s->s3->client_random,SSL3_RANDOM_SIZE,
                                        s->s3->server_random,SSL3_RANDOM_SIZE,
@@ -879,7 +879,7 @@ int tls1_final_finish_mac(SSL *s,
 
        for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
                {
-               if (mask & s->s3->tmp.new_cipher->algorithm2)
+               if (mask & ssl_get_algorithm2(s))
                        {
                        int hashsize = EVP_MD_size(md);
                        if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
@@ -898,7 +898,7 @@ int tls1_final_finish_mac(SSL *s,
                        }
                }
                
-       if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       if (!tls1_PRF(ssl_get_algorithm2(s),
                        str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
                        s->session->master_key,s->session->master_key_length,
                        out,buf2,sizeof buf2))
@@ -1008,6 +1008,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
        const void *co = NULL, *so = NULL;
        int col = 0, sol = 0;
 
+
 #ifdef KSSL_DEBUG
        printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
 #endif /* KSSL_DEBUG */
@@ -1024,7 +1025,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                }
 #endif
 
-       tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       tls1_PRF(ssl_get_algorithm2(s),
                TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
                s->s3->client_random,SSL3_RANDOM_SIZE,
                co, col,
@@ -1032,6 +1033,16 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                so, sol,
                p,len,
                s->session->master_key,buff,sizeof buff);
+#ifdef SSL_DEBUG
+       fprintf(stderr, "Premaster Secret:\n");
+       BIO_dump_fp(stderr, (char *)p, len);
+       fprintf(stderr, "Client Random:\n");
+       BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE);
+       fprintf(stderr, "Server Random:\n");
+       BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE);
+       fprintf(stderr, "Master Secret:\n");
+       BIO_dump_fp(stderr, (char *)s->session->master_key, SSL3_MASTER_SECRET_SIZE);
+#endif
 
 #ifdef KSSL_DEBUG
        printf ("tls1_generate_master_secret() complete\n");
@@ -1096,7 +1107,7 @@ int SSL_tls1_key_exporter(SSL *s, unsigned char *label, int label_len,
        if (!tmp)
                return 0;
        
-       rv = tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
+       rv = tls1_PRF(ssl_get_algorithm2(s),
                         label, label_len,
                         s->s3->client_random,SSL3_RANDOM_SIZE,
                         s->s3->server_random,SSL3_RANDOM_SIZE,
index ed65181..9bed9a3 100644 (file)
@@ -122,6 +122,7 @@ const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
 static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
                                const unsigned char *sess_id, int sesslen,
                                SSL_SESSION **psess);
+static int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
 #endif
 
 SSL3_ENC_METHOD TLSv1_enc_data={
@@ -450,6 +451,62 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
                skip_ext:
 
+       if (s->version >= TLS1_2_VERSION)
+               {
+               /* List of supported signature algorithms and hashes.
+                * Should make this customisable at some point, for
+                * now include everything we support.
+                */
+               static unsigned char sigalgs[] = {
+#ifndef OPENSSL_NO_RSA
+# ifndef OPENSSL_NO_SHA512
+                       TLSEXT_hash_sha512, TLSEXT_signature_rsa,
+                       TLSEXT_hash_sha384, TLSEXT_signature_rsa,
+# endif
+# ifndef OPENSSL_NO_SHA256
+                       TLSEXT_hash_sha256, TLSEXT_signature_rsa,
+                       TLSEXT_hash_sha224, TLSEXT_signature_rsa,
+# endif
+# ifndef OPENSSL_NO_SHA
+                       TLSEXT_hash_sha1, TLSEXT_signature_rsa,
+# endif
+#endif
+#ifndef OPENSSL_NO_ECDSA
+# ifndef OPENSSL_NO_SHA512
+                       TLSEXT_hash_sha512, TLSEXT_signature_ecdsa,
+                       TLSEXT_hash_sha384, TLSEXT_signature_ecdsa,
+# endif
+# ifndef OPENSSL_NO_SHA256
+                       TLSEXT_hash_sha256, TLSEXT_signature_ecdsa,
+                       TLSEXT_hash_sha224, TLSEXT_signature_ecdsa,
+# endif
+# ifndef OPENSSL_NO_SHA
+                       TLSEXT_hash_sha1, TLSEXT_signature_ecdsa,
+# endif
+#endif
+#ifndef OPENSSL_NO_DSA
+# ifndef OPENSSL_NO_SHA512
+                       TLSEXT_hash_sha512, TLSEXT_signature_dsa,
+                       TLSEXT_hash_sha384, TLSEXT_signature_dsa,
+# endif
+# ifndef OPENSSL_NO_SHA256
+                       TLSEXT_hash_sha256, TLSEXT_signature_dsa,
+                       TLSEXT_hash_sha224, TLSEXT_signature_dsa,
+# endif
+# ifndef OPENSSL_NO_SHA
+                       TLSEXT_hash_sha1, TLSEXT_signature_dsa
+# endif
+#endif
+               };
+               if ((size_t)(limit - ret) < sizeof(sigalgs) + 6)
+                       return NULL; 
+               s2n(TLSEXT_TYPE_signature_algorithms,ret);
+               s2n(sizeof(sigalgs) + 2, ret);
+               s2n(sizeof(sigalgs), ret);
+               memcpy(ret, sigalgs, sizeof(sigalgs));
+               ret += sizeof(sigalgs);
+               }
+
 #ifdef TLSEXT_TYPE_opaque_prf_input
        if (s->s3->client_opaque_prf_input != NULL &&
            s->version != DTLS1_VERSION)
@@ -656,6 +713,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
        unsigned short len;
        unsigned char *data = *p;
        int renegotiate_seen = 0;
+       int sigalg_seen = 0;
 
        s->servername_done = 0;
        s->tlsext_status_type = -1;
@@ -919,6 +977,28 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                return 0;
                        renegotiate_seen = 1;
                        }
+               else if (type == TLSEXT_TYPE_signature_algorithms)
+                       {
+                       int dsize;
+                       if (sigalg_seen || size < 2) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       sigalg_seen = 1;
+                       n2s(data,dsize);
+                       size -= 2;
+                       if (dsize != size || dsize & 1) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       if (!tls1_process_sigalgs(s, data, dsize))
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       }
                else if (type == TLSEXT_TYPE_status_request &&
                         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
                        {
@@ -1781,4 +1861,192 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        return 0;
        }
 
+/* Tables to translate from NIDs to TLS v1.2 ids */
+
+typedef struct 
+       {
+       int nid;
+       int id;
+       } tls12_lookup;
+
+static tls12_lookup tls12_md[] = {
+#ifndef OPENSSL_NO_MD5
+       {NID_md5, TLSEXT_hash_md5},
+#endif
+#ifndef OPENSSL_NO_SHA
+       {NID_sha1, TLSEXT_hash_sha1},
+#endif
+#ifndef OPENSSL_NO_SHA256
+       {NID_sha224, TLSEXT_hash_sha224},
+       {NID_sha256, TLSEXT_hash_sha256},
+#endif
+#ifndef OPENSSL_NO_SHA512
+       {NID_sha384, TLSEXT_hash_sha384},
+       {NID_sha512, TLSEXT_hash_sha512}
+#endif
+};
+
+static tls12_lookup tls12_sig[] = {
+#ifndef OPENSSL_NO_RSA
+       {EVP_PKEY_RSA, TLSEXT_signature_rsa},
+#endif
+#ifndef OPENSSL_NO_RSA
+       {EVP_PKEY_DSA, TLSEXT_signature_dsa},
+#endif
+#ifndef OPENSSL_NO_ECDSA
+       {EVP_PKEY_EC, TLSEXT_signature_ecdsa}
+#endif
+};
+
+static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
+       {
+       size_t i;
+       for (i = 0; i < tlen; i++)
+               {
+               if (table[i].nid == nid)
+                       return table[i].id;
+               }
+       return -1;
+       }
+#if 0
+static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
+       {
+       size_t i;
+       for (i = 0; i < tlen; i++)
+               {
+               if (table[i].id == id)
+                       return table[i].nid;
+               }
+       return -1;
+       }
+#endif
+
+int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
+       {
+       int sig_id, md_id;
+       md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
+                               sizeof(tls12_md)/sizeof(tls12_lookup));
+       if (md_id == -1)
+               return 0;
+       sig_id = tls12_get_sigid(pk);
+       if (sig_id == -1)
+               return 0;
+       p[0] = (unsigned char)md_id;
+       p[1] = (unsigned char)sig_id;
+       return 1;
+       }
+
+int tls12_get_sigid(const EVP_PKEY *pk)
+       {
+       return tls12_find_id(pk->type, tls12_sig,
+                               sizeof(tls12_sig)/sizeof(tls12_lookup));
+       }
+
+const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+       {
+       switch(hash_alg)
+               {
+#ifndef OPENSSL_NO_MD5
+               case TLSEXT_hash_md5:
+               return EVP_md5();
+#endif
+#ifndef OPENSSL_NO_SHA
+               case TLSEXT_hash_sha1:
+               return EVP_sha1();
+#endif
+#ifndef OPENSSL_NO_SHA256
+               case TLSEXT_hash_sha224:
+               return EVP_sha224();
+
+               case TLSEXT_hash_sha256:
+               return EVP_sha256();
+#endif
+#ifndef OPENSSL_NO_SHA512
+               case TLSEXT_hash_sha384:
+               return EVP_sha384();
+
+               case TLSEXT_hash_sha512:
+               return EVP_sha512();
+#endif
+               default:
+               return NULL;
+
+               }
+       }
+
+/* Set preferred digest for each key type */
+
+static int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+       {
+       int i, idx;
+       const EVP_MD *md;
+       CERT *c = s->cert;
+       /* Extension ignored for TLS versions below 1.2 */
+       if (s->version < TLS1_2_VERSION)
+               return 1;
+
+       c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
+       c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
+       c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
+       c->pkeys[SSL_PKEY_ECC].digest = NULL;
+
+       for (i = 0; i < dsize; i += 2)
+               {
+               unsigned char hash_alg = data[i], sig_alg = data[i+1];
+
+               switch(sig_alg)
+                       {
+#ifndef OPENSSL_NO_RSA
+                       case TLSEXT_signature_rsa:
+                       idx = SSL_PKEY_RSA_SIGN;
+                       break;
+#endif
+#ifndef OPENSSL_NO_DSA
+                       case TLSEXT_signature_dsa:
+                       idx = SSL_PKEY_DSA_SIGN;
+                       break;
+#endif
+#ifndef OPENSSL_NO_ECDSA
+                       case TLSEXT_signature_ecdsa:
+                       idx = SSL_PKEY_ECC;
+                       break;
+#endif
+                       default:
+                       continue;
+                       }
+
+               if (c->pkeys[idx].digest == NULL)
+                       {
+                       md = tls12_get_hash(hash_alg);
+                       if (md)
+                               {
+                               c->pkeys[idx].digest = md;
+                               if (idx == SSL_PKEY_RSA_SIGN)
+                                       c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+                               }
+                       }
+
+               }
+
+       /* Set any remaining keys to default values. NOTE: if alg is not
+        * supported it stays as NULL.
+        */
+#ifndef OPENSSL_NO_DSA
+       if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
+               c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1();
+#endif
+#ifndef OPENSSL_NO_RSA
+       if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
+               {
+               c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
+               c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
+               }
+#endif
+#ifndef OPENSSL_NO_ECDSA
+       if (!c->pkeys[SSL_PKEY_ECC].digest)
+               c->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa();
+#endif
+       return 1;
+       }
+
 #endif
index 3257636..53c807d 100644 (file)
@@ -62,6 +62,8 @@
 
 static const SSL_METHOD *tls1_get_method(int ver)
        {
+       if (ver == TLS1_2_VERSION)
+               return TLSv1_2_method();
        if (ver == TLS1_1_VERSION)
                return TLSv1_1_method();
        if (ver == TLS1_VERSION)
@@ -69,6 +71,11 @@ static const SSL_METHOD *tls1_get_method(int ver)
        return NULL;
        }
 
+IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_method,
+                       ssl3_accept,
+                       ssl3_connect,
+                       tls1_get_method)
+
 IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method,
                        ssl3_accept,
                        ssl3_connect,
index 274a3d6..f1d1565 100644 (file)
@@ -67,6 +67,8 @@
 static const SSL_METHOD *tls1_get_server_method(int ver);
 static const SSL_METHOD *tls1_get_server_method(int ver)
        {
+       if (ver == TLS1_2_VERSION)
+               return TLSv1_2_server_method();
        if (ver == TLS1_1_VERSION)
                return TLSv1_1_server_method();
        if (ver == TLS1_VERSION)
@@ -74,6 +76,11 @@ static const SSL_METHOD *tls1_get_server_method(int ver)
        return NULL;
        }
 
+IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_server_method,
+                       ssl3_accept,
+                       ssl_undefined_function,
+                       tls1_get_server_method)
+
 IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_server_method,
                        ssl3_accept,
                        ssl_undefined_function,
index c3bb2e5..b517877 100644 (file)
@@ -159,6 +159,10 @@ extern "C" {
 
 #define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES   0
 
+#define TLS1_2_VERSION                 0x0303
+#define TLS1_2_VERSION_MAJOR           0x03
+#define TLS1_2_VERSION_MINOR           0x03
+
 #define TLS1_1_VERSION                 0x0302
 #define TLS1_1_VERSION_MAJOR           0x03
 #define TLS1_1_VERSION_MINOR           0x02
@@ -201,6 +205,7 @@ extern "C" {
 #define TLSEXT_TYPE_ec_point_formats           11
 /* ExtensionType value from RFC5054 */
 #define TLSEXT_TYPE_srp                                12
+#define TLSEXT_TYPE_signature_algorithms       13
 #define TLSEXT_TYPE_session_ticket             35
 /* ExtensionType value from draft-rescorla-tls-opaque-prf-input-00.txt */
 #if 0 /* will have to be provided externally for now ,
@@ -224,6 +229,21 @@ extern "C" {
 #define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2
 #define TLSEXT_ECPOINTFORMAT_last                      2
 
+/* Signature and hash algorithms from RFC 5246 */
+
+#define TLSEXT_signature_anonymous                     0
+#define TLSEXT_signature_rsa                           1
+#define TLSEXT_signature_dsa                           2
+#define TLSEXT_signature_ecdsa                         3
+
+#define TLSEXT_hash_none                               0
+#define TLSEXT_hash_md5                                        1
+#define TLSEXT_hash_sha1                               2
+#define TLSEXT_hash_sha224                             3
+#define TLSEXT_hash_sha256                             4
+#define TLSEXT_hash_sha384                             5
+#define TLSEXT_hash_sha512                             6
+
 #ifndef OPENSSL_NO_TLSEXT
 
 #define TLSEXT_MAXLEN_host_name 255
@@ -330,6 +350,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_CK_DHE_RSA_WITH_AES_256_SHA               0x03000039
 #define TLS1_CK_ADH_WITH_AES_256_SHA                   0x0300003A
 
+/* TLS v1.2 ciphersuites */
+#define TLS1_CK_RSA_WITH_NULL_SHA256                   0x0300003B
+#define TLS1_CK_RSA_WITH_AES_128_SHA256                        0x0300003C
+#define TLS1_CK_RSA_WITH_AES_256_SHA256                        0x0300003D
+#define TLS1_CK_DH_DSS_WITH_AES_128_SHA256             0x0300003E
+#define TLS1_CK_DH_RSA_WITH_AES_128_SHA256             0x0300003F
+#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256            0x03000040
+
 /* Camellia ciphersuites from RFC4132 */
 #define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA          0x03000041
 #define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA       0x03000042
@@ -338,6 +366,16 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA      0x03000045
 #define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA          0x03000046
 
+/* TLS v1.2 ciphersuites */
+#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256            0x03000067
+#define TLS1_CK_DH_DSS_WITH_AES_256_SHA256             0x03000068
+#define TLS1_CK_DH_RSA_WITH_AES_256_SHA256             0x03000069
+#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256            0x0300006A
+#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256            0x0300006B
+#define TLS1_CK_ADH_WITH_AES_128_SHA256                        0x0300006C
+#define TLS1_CK_ADH_WITH_AES_256_SHA256                        0x0300006D
+
+/* Camellia ciphersuites from RFC4132 */
 #define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA          0x03000084
 #define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA       0x03000085
 #define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA       0x03000086
@@ -496,6 +534,20 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_TXT_DHE_RSA_WITH_SEED_SHA                  "DHE-RSA-SEED-SHA"
 #define TLS1_TXT_ADH_WITH_SEED_SHA                      "ADH-SEED-SHA"
 
+/* TLS v1.2 ciphersuites */
+#define TLS1_TXT_RSA_WITH_NULL_SHA256                  "NULL-SHA256"
+#define TLS1_TXT_RSA_WITH_AES_128_SHA256               "AES128-SHA256"
+#define TLS1_TXT_RSA_WITH_AES_256_SHA256               "AES256-SHA256"
+#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256            "DH-DSS-AES128-SHA256"
+#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256            "DH-RSA-AES128-SHA256"
+#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256           "DHE-DSS-AES128-SHA256"
+#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256           "DHE-RSA-AES128-SHA256"
+#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256            "DH-DSS-AES256-SHA256"
+#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256            "DH-RSA-AES256-SHA256"
+#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256           "DHE-DSS-AES256-SHA256"
+#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256           "DHE-RSA-AES256-SHA256"
+#define TLS1_TXT_ADH_WITH_AES_128_SHA256               "ADH-AES128-SHA256"
+#define TLS1_TXT_ADH_WITH_AES_256_SHA256               "ADH-AES256-SHA256"
 
 #define TLS_CT_RSA_SIGN                        1
 #define TLS_CT_DSS_SIGN                        2