Process signature algorithms in ClientHello late.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 9 Oct 2014 19:37:27 +0000 (20:37 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 24 Oct 2014 12:57:23 +0000 (13:57 +0100)
Reviewed-by: Tim Hudson <tjh@openssl.org>
(cherry picked from commit c800c27a8c47c8e63254ec594682452c296f1e8e)

Conflicts:

ssl/ssl.h
ssl/ssl_err.c
ssl/ssl_locl.h

ssl/s3_clnt.c
ssl/ssl.h
ssl/ssl_err.c
ssl/ssl_locl.h
ssl/t1_lib.c

index 3e89e5204d7bab86c74724a4e1b0167b468d1007..7d526ddac7ef8c62cec03ee535752fa413599f4c 100644 (file)
@@ -2168,12 +2168,18 @@ int ssl3_get_certificate_request(SSL *s)
                        s->cert->pkeys[i].digest = NULL;
                        s->cert->pkeys[i].valid_flags = 0;
                        }
-               if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
+               if ((llen & 1) || !tls1_save_sigalgs(s, p, llen))
                        {
                        ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
                        SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
                        goto err;
                        }
+               if (!tls1_process_sigalgs(s))
+                       {
+                       ssl3_send_alert(s,SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+                       SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
                p += llen;
                }
 
index 9e3ca9d3f27dcc594eca8953e82fce266c8feda3..bbf31802767a69fa1ff2ca743057f29fbb9150ad 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2582,6 +2582,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_CERT_INST                             222
 #define SSL_F_SSL_CERT_INSTANTIATE                      214
 #define SSL_F_SSL_CERT_NEW                              162
+#define SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE                 335
 #define SSL_F_SSL_CHECK_PRIVATE_KEY                     163
 #define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT              280
 #define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG           279
index 63b5c35beaf25dd72392cf01bd0397ef2312b4a5..bcd124ed6b58ce303397f2ed23ad866d0d664359 100644 (file)
@@ -199,6 +199,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_CERT_INST),        "ssl_cert_inst"},
 {ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE), "SSL_CERT_INSTANTIATE"},
 {ERR_FUNC(SSL_F_SSL_CERT_NEW), "ssl_cert_new"},
+{ERR_FUNC(SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE),    "ssl_check_clienthello_tlsext_late"},
 {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),        "SSL_check_private_key"},
 {ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT), "SSL_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG),      "ssl_check_srvr_ecc_cert_and_alg"},
index ce5856aa8d77b8cc839967d8db73d89a5ebc3a73..6d8047c91cf72b8396c8d645de95d75eae558a5c 100644 (file)
@@ -1353,7 +1353,8 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
                                          int *al);
 long ssl_get_algorithm2(SSL *s);
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
+int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize);
+int tls1_process_sigalgs(SSL *s);
 size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs);
 int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
                                const unsigned char *sig, EVP_PKEY *pkey);
index fb0b736d1c26ce53c661eb9cc8a1c193ed0ff912..23aee0794b6fedd447bd68d83c06b3473bf43222 100644 (file)
@@ -1908,7 +1908,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
        unsigned short len;
        unsigned char *data = *p;
        int renegotiate_seen = 0;
-       size_t i;
 
        s->servername_done = 0;
        s->tlsext_status_type = -1;
@@ -1938,18 +1937,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                OPENSSL_free(s->cert->peer_sigalgs);
                s->cert->peer_sigalgs = NULL;
                }
-       /* Clear any shared sigtnature algorithms */
-       if (s->cert->shared_sigalgs)
-               {
-               OPENSSL_free(s->cert->shared_sigalgs);
-               s->cert->shared_sigalgs = NULL;
-               }
-       /* Clear certificate digests and validity flags */
-       for (i = 0; i < SSL_PKEY_NUM; i++)
-               {
-               s->cert->pkeys[i].digest = NULL;
-               s->cert->pkeys[i].valid_flags = 0;
-               }
 
        if (data >= (d+n-2))
                goto ri_check;
@@ -2236,21 +2223,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                }
-                       if (!tls1_process_sigalgs(s, data, dsize))
+                       if (!tls1_save_sigalgs(s, data, dsize))
                                {
                                *al = SSL_AD_DECODE_ERROR;
                                return 0;
                                }
-                       /* If sigalgs received and no shared algorithms fatal
-                        * error.
-                        */
-                       if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs)
-                               {
-                               SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
-                                       SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
-                               *al = SSL_AD_ILLEGAL_PARAMETER;
-                               return 0;
-                               }
                        }
                else if (type == TLSEXT_TYPE_status_request)
                        {
@@ -2442,9 +2419,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
                return 0;
                }
-       /* If no signature algorithms extension set default values */
-       if (!s->cert->peer_sigalgs)
-               ssl_cert_set_default_md(s->cert);
 
        return 1;
        }
@@ -3000,6 +2974,7 @@ int ssl_check_clienthello_tlsext_late(SSL *s)
        {
        int ret = SSL_TLSEXT_ERR_OK;
        int al;
+       size_t i;
 
        /* If status request then ask callback what to do.
         * Note: this must be called after servername callbacks in case
@@ -3045,6 +3020,43 @@ int ssl_check_clienthello_tlsext_late(SSL *s)
        else
                s->tlsext_status_expected = 0;
 
+       /* Clear any shared sigtnature algorithms */
+       if (s->cert->shared_sigalgs)
+               {
+               OPENSSL_free(s->cert->shared_sigalgs);
+               s->cert->shared_sigalgs = NULL;
+               }
+       /* Clear certificate digests and validity flags */
+       for (i = 0; i < SSL_PKEY_NUM; i++)
+               {
+               s->cert->pkeys[i].digest = NULL;
+               s->cert->pkeys[i].valid_flags = 0;
+               }
+
+       /* If sigalgs received process it. */
+       if (s->cert->peer_sigalgs)
+               {
+               if (!tls1_process_sigalgs(s))
+                       {
+                       SSLerr(SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE,
+                                       ERR_R_MALLOC_FAILURE);
+                       ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                       al = SSL_AD_INTERNAL_ERROR;
+                       goto err;
+                       }
+               /* Fatal error is no shared signature algorithms */
+               if (!s->cert->shared_sigalgs)
+                       {
+                       SSLerr(SSL_F_SSL_CHECK_CLIENTHELLO_TLSEXT_LATE,
+                                       SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+                       ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                       al = SSL_AD_ILLEGAL_PARAMETER;
+                       goto err;
+                       }
+               }
+       else
+               ssl_cert_set_default_md(s->cert);
+
  err:
        switch (ret)
                {
@@ -3677,13 +3689,9 @@ static int tls1_set_shared_sigalgs(SSL *s)
 
 /* Set preferred digest for each key type */
 
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize)
        {
-       int idx;
-       size_t i;
-       const EVP_MD *md;
        CERT *c = s->cert;
-       TLS_SIGALGS *sigptr;
        /* Extension ignored for inappropriate versions */
        if (!SSL_USE_SIGALGS(s))
                return 1;
@@ -3698,8 +3706,18 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
                return 0;
        c->peer_sigalgslen = dsize;
        memcpy(c->peer_sigalgs, data, dsize);
+       return 1;
+       }
 
-       tls1_set_shared_sigalgs(s);
+int tls1_process_sigalgs(SSL *s)
+       {
+       int idx;
+       size_t i;
+       const EVP_MD *md;
+       CERT *c = s->cert;
+       TLS_SIGALGS *sigptr;
+       if (!tls1_set_shared_sigalgs(s))
+               return 0;
 
 #ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
        if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)