Initial TLS v1.2 client support. Include a default supported signature
authorDr. Stephen Henson <steve@openssl.org>
Mon, 9 May 2011 15:44:01 +0000 (15:44 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Mon, 9 May 2011 15:44:01 +0000 (15:44 +0000)
algorithms extension (including everything we support). Swicth to new
signature format where needed and relax ECC restrictions.

Not TLS v1.2 client certifcate support yet but client will handle case
where a certificate is requested and we don't have one.

CHANGES
apps/s_client.c
ssl/s3_clnt.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/t1_enc.c
ssl/t1_lib.c

diff --git a/CHANGES b/CHANGES
index a955b3fd983f2f30794be6806e77feef834bb766..1ee3a478d3effda5bc67eefc006da305aef23624 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,12 @@
 
  Changes between 1.0.1 and 1.1.0  [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
index faf7f39c1d96eb354ee18946dfd6229968ecb945..2b8b1455ebcc13ce49913e48502bf833c17a9b05 100644 (file)
@@ -1103,6 +1103,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
@@ -2011,6 +2014,18 @@ static void print_stuff(BIO *bio, SSL *s, int full)
        }
 #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 f96ec4f9848fb34590f439c5a52cc01f3316f3ec..0541de95b9308f30e46b756395c23b7943e8477b 100644 (file)
@@ -1203,6 +1203,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
@@ -1653,6 +1654,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);
@@ -1666,7 +1699,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;
 
@@ -1701,29 +1734,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);
@@ -1735,12 +1747,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
                {
@@ -1787,7 +1793,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;
@@ -1843,6 +1849,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);
@@ -1855,7 +1872,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);
@@ -3059,7 +3076,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 4eec497bef7a4070018075a8cdeb0011948f5ceb..0f203ec6b16ccbcf189cecbca90dcb5192a66fca 100644 (file)
@@ -1932,6 +1932,10 @@ int ssl3_send_server_key_exchange(SSL *s)
                                                }
                                        p+=2;
                                        }
+#ifdef SSL_DEBUG
+                               fprintf(stderr, "Using hash %s\n",
+                                                       EVP_MD_name(md));
+#endif
                                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);
index c48740760779dba15513228227f8d04aade18ed8..755dd853dcf2e2da7ec774dc73c572f744641821 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2500,6 +2500,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
@@ -2520,6 +2521,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 af52856a682772fe90a997db2317b57c2e64acdc..76c8e1e33e2d1990407d7acd83a04ddee2a43946 100644 (file)
@@ -543,6 +543,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"},
@@ -563,6 +564,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 114ad476a8b3ef2544a146c796d2303c919f831f..3f60ab161276d31c1559763ca87ee1b7a3ef1c1d 100644 (file)
@@ -2185,12 +2185,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;
@@ -2217,7 +2218,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)
@@ -2226,7 +2227,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 */
 
index 3225d6517ac0e383d896f26befd6276b91afdf97..78958d4506b0e6dc434db06f8dbaab87d3752a81 100644 (file)
@@ -1050,7 +1050,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);
@@ -1077,6 +1077,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);
@@ -1090,4 +1096,3 @@ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
                                          int *al);
 long ssl_get_algorithm2(SSL *s);
 #endif
-int tls12_get_sigandhash(unsigned char *p, EVP_PKEY *pk, const EVP_MD *md);
index 95a5b35c42e16bb83c37d9906e9166e6a023573a..c60bccd2c00b1af21ad7a306ca1e76679e5dc87f 100644 (file)
@@ -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 */
@@ -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");
index 67a3f86adcc6528a0ae3d3191d25df3dab92646a..ca4b2db493f1899e9c8b67c99ae12a6380941fef 100644 (file)
@@ -451,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)
@@ -1976,15 +2032,15 @@ static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
        return -1;
        }
 #endif
-int tls12_get_sigandhash(unsigned char *p, EVP_PKEY *pk, const EVP_MD *md)
+
+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_find_id(pk->type, tls12_sig,
-                               sizeof(tls12_sig)/sizeof(tls12_lookup));
+       sig_id = tls12_get_sigid(pk);
        if (sig_id == -1)
                return 0;
        p[0] = (unsigned char)md_id;
@@ -1992,9 +2048,47 @@ int tls12_get_sigandhash(unsigned char *p, EVP_PKEY *pk, const EVP_MD *md)
        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 */
 
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+static int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
        {
        int i, idx;
        const EVP_MD *md;
@@ -2033,48 +2127,17 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
                        continue;
                        }
 
-               if (c->pkeys[idx].digest)
-                       continue;
-
-               switch(hash_alg)
+               if (c->pkeys[idx].digest == NULL)
                        {
-#ifndef OPENSSL_NO_MD5
-                       case TLSEXT_hash_md5:
-                       md = EVP_md5();
-                       break;
-#endif
-#ifndef OPENSSL_NO_SHA
-                       case TLSEXT_hash_sha1:
-                       md = EVP_sha1();
-                       break;
-#endif
-#ifndef OPENSSL_NO_SHA256
-                       case TLSEXT_hash_sha224:
-                       md = EVP_sha224();
-                       break;
-
-                       case TLSEXT_hash_sha256:
-                       md = EVP_sha256();
-                       break;
-#endif
-#ifndef OPENSSL_NO_SHA512
-                       case TLSEXT_hash_sha384:
-                       md = EVP_sha384();
-                       break;
-
-                       case TLSEXT_hash_sha512:
-                       md = EVP_sha512();
-                       break;
-#endif
-                       default:
-                       continue;
-
+                       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;
+                               }
                        }
 
-               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