Fix source where indent will not be able to cope
[openssl.git] / ssl / t1_lib.c
index fb0b736d1c26ce53c661eb9cc8a1c193ed0ff912..8b8c9cd71f3a901ba5b634cdb48c3fb54c471768 100644 (file)
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
+#ifdef OPENSSL_NO_EC2M
+#include <openssl/ec.h>
+#endif
 #include <openssl/ocsp.h>
 #include <openssl/rand.h>
 #include "ssl_locl.h"
@@ -260,31 +263,43 @@ static const unsigned char ecformats_default[] =
 
 static const unsigned char eccurves_default[] =
        {
+#ifndef OPENSSL_NO_EC2M
                0,14, /* sect571r1 (14) */ 
                0,13, /* sect571k1 (13) */ 
+#endif
                0,25, /* secp521r1 (25) */      
                0,28, /* brainpool512r1 (28) */ 
+#ifndef OPENSSL_NO_EC2M
                0,11, /* sect409k1 (11) */ 
                0,12, /* sect409r1 (12) */
+#endif
                0,27, /* brainpoolP384r1 (27) */        
                0,24, /* secp384r1 (24) */
+#ifndef OPENSSL_NO_EC2M
                0,9,  /* sect283k1 (9) */
                0,10, /* sect283r1 (10) */ 
+#endif
                0,26, /* brainpoolP256r1 (26) */        
                0,22, /* secp256k1 (22) */ 
                0,23, /* secp256r1 (23) */ 
+#ifndef OPENSSL_NO_EC2M
                0,8,  /* sect239k1 (8) */ 
                0,6,  /* sect233k1 (6) */
                0,7,  /* sect233r1 (7) */ 
+#endif
                0,20, /* secp224k1 (20) */ 
                0,21, /* secp224r1 (21) */
+#ifndef OPENSSL_NO_EC2M
                0,4,  /* sect193r1 (4) */ 
                0,5,  /* sect193r2 (5) */ 
+#endif
                0,18, /* secp192k1 (18) */
                0,19, /* secp192r1 (19) */ 
+#ifndef OPENSSL_NO_EC2M
                0,1,  /* sect163k1 (1) */
                0,2,  /* sect163r1 (2) */
                0,3,  /* sect163r2 (3) */
+#endif
                0,15, /* secp160k1 (15) */
                0,16, /* secp160r1 (16) */ 
                0,17, /* secp160r2 (17) */ 
@@ -300,37 +315,49 @@ static const unsigned char suiteb_curves[] =
 /* Brainpool not allowed in FIPS mode */
 static const unsigned char fips_curves_default[] =
        {
-               0,14, /* sect571r1 (14) */ 
-               0,13, /* sect571k1 (13) */ 
-               0,25, /* secp521r1 (25) */      
-               0,11, /* sect409k1 (11) */ 
+#ifndef OPENSSL_NO_EC2M
+               0,14, /* sect571r1 (14) */
+               0,13, /* sect571k1 (13) */
+#endif
+               0,25, /* secp521r1 (25) */
+#ifndef OPENSSL_NO_EC2M
+               0,11, /* sect409k1 (11) */
                0,12, /* sect409r1 (12) */
+#endif
                0,24, /* secp384r1 (24) */
+#ifndef OPENSSL_NO_EC2M
                0,9,  /* sect283k1 (9) */
-               0,10, /* sect283r1 (10) */ 
-               0,22, /* secp256k1 (22) */ 
-               0,23, /* secp256r1 (23) */ 
-               0,8,  /* sect239k1 (8) */ 
+               0,10, /* sect283r1 (10) */
+#endif
+               0,22, /* secp256k1 (22) */
+               0,23, /* secp256r1 (23) */
+#ifndef OPENSSL_NO_EC2M
+               0,8,  /* sect239k1 (8) */
                0,6,  /* sect233k1 (6) */
-               0,7,  /* sect233r1 (7) */ 
+               0,7,  /* sect233r1 (7) */
+#endif
                0,20, /* secp224k1 (20) */ 
                0,21, /* secp224r1 (21) */
-               0,4,  /* sect193r1 (4) */ 
-               0,5,  /* sect193r2 (5) */ 
+#ifndef OPENSSL_NO_EC2M
+               0,4,  /* sect193r1 (4) */
+               0,5,  /* sect193r2 (5) */
+#endif
                0,18, /* secp192k1 (18) */
-               0,19, /* secp192r1 (19) */ 
+               0,19, /* secp192r1 (19) */
+#ifndef OPENSSL_NO_EC2M
                0,1,  /* sect163k1 (1) */
                0,2,  /* sect163r1 (2) */
                0,3,  /* sect163r2 (3) */
+#endif
                0,15, /* secp160k1 (15) */
-               0,16, /* secp160r1 (16) */ 
-               0,17, /* secp160r2 (17) */ 
+               0,16, /* secp160r1 (16) */
+               0,17, /* secp160r2 (17) */
        };
 #endif
 
 int tls1_ec_curve_id2nid(int curve_id)
        {
-       /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+       /* ECC curves from RFC 4492 and RFC 7027 */
        if ((curve_id < 1) || ((unsigned int)curve_id >
                                sizeof(nid_list)/sizeof(nid_list[0])))
                return 0;
@@ -339,7 +366,7 @@ int tls1_ec_curve_id2nid(int curve_id)
 
 int tls1_ec_nid2curve_id(int nid)
        {
-       /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+       /* ECC curves from RFC 4492 and RFC 7027 */
        switch (nid)
                {
        case NID_sect163k1: /* sect163k1 (1) */
@@ -402,59 +429,85 @@ int tls1_ec_nid2curve_id(int nid)
                return 0;
                }
        }
-/* Get curves list, if "sess" is set return client curves otherwise
- * preferred list
+/*
+ * Get curves list, if "sess" is set return client curves otherwise
+ * preferred list.
+ * Sets |num_curves| to the number of curves in the list, i.e.,
+ * the length of |pcurves| is 2 * num_curves.
+ * Returns 1 on success and 0 if the client curves list has invalid format.
+ * The latter indicates an internal error: we should not be accepting such
+ * lists in the first place.
+ * TODO(emilia): we should really be storing the curves list in explicitly
+ * parsed form instead. (However, this would affect binary compatibility
+ * so cannot happen in the 1.0.x series.)
  */
-static void tls1_get_curvelist(SSL *s, int sess,
+static int tls1_get_curvelist(SSL *s, int sess,
                                        const unsigned char **pcurves,
-                                       size_t *pcurveslen)
+                                       size_t *num_curves)
        {
+       size_t pcurveslen = 0;
        if (sess)
                {
                *pcurves = s->session->tlsext_ellipticcurvelist;
-               *pcurveslen = s->session->tlsext_ellipticcurvelist_length;
-               return;
+               pcurveslen = s->session->tlsext_ellipticcurvelist_length;
                }
-       /* For Suite B mode only include P-256, P-384 */
-       switch (tls1_suiteb(s))
+       else
                {
-       case SSL_CERT_FLAG_SUITEB_128_LOS:
-               *pcurves = suiteb_curves;
-               *pcurveslen = sizeof(suiteb_curves);
-               break;
+               /* For Suite B mode only include P-256, P-384 */
+               switch (tls1_suiteb(s))
+                       {
+               case SSL_CERT_FLAG_SUITEB_128_LOS:
+                       *pcurves = suiteb_curves;
+                       pcurveslen = sizeof(suiteb_curves);
+                       break;
 
-       case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
-               *pcurves = suiteb_curves;
-               *pcurveslen = 2;
-               break;
+               case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+                       *pcurves = suiteb_curves;
+                       pcurveslen = 2;
+                       break;
 
-       case SSL_CERT_FLAG_SUITEB_192_LOS:
-               *pcurves = suiteb_curves + 2;
-               *pcurveslen = 2;
-               break;
-       default:
-               *pcurves = s->tlsext_ellipticcurvelist;
-               *pcurveslen = s->tlsext_ellipticcurvelist_length;
-               }
-       if (!*pcurves)
-               {
-#ifdef OPENSSL_FIPS
-               if (FIPS_mode())
-                       {
-                       *pcurves = fips_curves_default;
-                       *pcurveslen = sizeof(fips_curves_default);
-                       return;
+               case SSL_CERT_FLAG_SUITEB_192_LOS:
+                       *pcurves = suiteb_curves + 2;
+                       pcurveslen = 2;
+                       break;
+               default:
+                       *pcurves = s->tlsext_ellipticcurvelist;
+                       pcurveslen = s->tlsext_ellipticcurvelist_length;
                        }
+               if (!*pcurves)
+                       {
+#ifdef OPENSSL_FIPS
+                       if (FIPS_mode())
+                               {
+                               *pcurves = fips_curves_default;
+                               *pcurveslen = sizeof(fips_curves_default);
+                               }
+                       else
 #endif
-               *pcurves = eccurves_default;
-               *pcurveslen = sizeof(eccurves_default);
+                               {
+                               *pcurves = eccurves_default;
+                               pcurveslen = sizeof(eccurves_default);
+                               }
+                       }
+               }
+       /* We do not allow odd length arrays to enter the system. */
+       if (pcurveslen & 1)
+               {
+               SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR);
+               *num_curves = 0;
+               return 0;
+               }
+       else
+               {
+               *num_curves = pcurveslen / 2;
+               return 1;
                }
        }
 /* Check a curve is one of our preferences */
 int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
        {
        const unsigned char *curves;
-       size_t curveslen, i;
+       size_t num_curves, i;
        unsigned int suiteb_flags = tls1_suiteb(s);
        if (len != 3 || p[0] != NAMED_CURVE_TYPE)
                return 0;
@@ -477,8 +530,9 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
                else    /* Should never happen */
                        return 0;
                }
-       tls1_get_curvelist(s, 0, &curves, &curveslen);
-       for (i = 0; i < curveslen; i += 2, curves += 2)
+       if (!tls1_get_curvelist(s, 0, &curves, &num_curves))
+               return 0;
+       for (i = 0; i < num_curves; i++, curves += 2)
                {
                if (p[1] == curves[0] && p[2] == curves[1])
                        return 1;
@@ -486,15 +540,16 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
        return 0;
        }
 
-/* Return nth shared curve. If nmatch == -1 return number of
- * matches. For nmatch == -2 return the NID of the curve to use for
- * an EC tmp key.
+/*-
+ * Return |nmatch|th shared curve or NID_undef if there is no match.
+ * For nmatch == -1, return number of  matches
+ * For nmatch == -2, return the NID of the curve to use for
+ * an EC tmp key, or NID_undef if there is no match.
  */
-
 int tls1_shared_curve(SSL *s, int nmatch)
        {
        const unsigned char *pref, *supp;
-       size_t preflen, supplen, i, j;
+       size_t num_pref, num_supp, i, j;
        int k;
        /* Can't do anything on client side */
        if (s->server == 0)
@@ -518,17 +573,22 @@ int tls1_shared_curve(SSL *s, int nmatch)
                /* If not Suite B just return first preference shared curve */
                nmatch = 0;
                }
-       tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
-                               &supp, &supplen);
-       tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
-                               &pref, &preflen);
-       preflen /= 2;
-       supplen /= 2;
+       /*
+        * Avoid truncation. tls1_get_curvelist takes an int
+        * but s->options is a long...
+        */
+       if (!tls1_get_curvelist(s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0,
+                       &supp, &num_supp))
+               /* In practice, NID_undef == 0 but let's be precise. */
+               return nmatch == -1 ? 0 : NID_undef;
+       if(!tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
+                       &pref, &num_pref))
+               return nmatch == -1 ? 0 : NID_undef;
        k = 0;
-       for (i = 0; i < preflen; i++, pref+=2)
+       for (i = 0; i < num_pref; i++, pref+=2)
                {
                const unsigned char *tsupp = supp;
-               for (j = 0; j < supplen; j++, tsupp+=2)
+               for (j = 0; j < num_supp; j++, tsupp+=2)
                        {
                        if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
                                {
@@ -543,7 +603,8 @@ int tls1_shared_curve(SSL *s, int nmatch)
                }
        if (nmatch == -1)
                return k;
-       return 0;
+       /* Out of range (nmatch > k). */
+       return NID_undef;
        }
 
 int tls1_set_curves(unsigned char **pext, size_t *pextlen,
@@ -555,6 +616,10 @@ int tls1_set_curves(unsigned char **pext, size_t *pextlen,
         * while curve ids < 32 
         */
        unsigned long dup_list = 0;
+#ifdef OPENSSL_NO_EC2M
+       EC_GROUP *curve;
+#endif
+
        clist = OPENSSL_malloc(ncurves * 2);
        if (!clist)
                return 0;
@@ -570,6 +635,19 @@ int tls1_set_curves(unsigned char **pext, size_t *pextlen,
                        OPENSSL_free(clist);
                        return 0;
                        }
+#endif
+#ifdef OPENSSL_NO_EC2M
+               curve = EC_GROUP_new_by_curve_name(curves[i]);
+               if(!curve ||
+                       EC_METHOD_get_field_type(EC_GROUP_method_of(curve))
+                               == NID_X9_62_characteristic_two_field)
+                       {
+                               if(curve) EC_GROUP_free(curve);
+                               OPENSSL_free(clist);
+                               return 0;
+                       }
+               else
+                       EC_GROUP_free(curve);
 #endif
                idmask = 1L << id;
                if (!id || (dup_list & idmask))
@@ -689,22 +767,22 @@ static int tls1_set_ec_id(unsigned char *curve_id, unsigned char *comp_id,
 static int tls1_check_ec_key(SSL *s,
                        unsigned char *curve_id, unsigned char *comp_id)
        {
-       const unsigned char *p;
-       size_t plen, i;
+       const unsigned char *pformats, *pcurves;
+       size_t num_formats, num_curves, i;
        int j;
        /* If point formats extension present check it, otherwise everything
         * is supported (see RFC4492).
         */
        if (comp_id && s->session->tlsext_ecpointformatlist)
                {
-               p = s->session->tlsext_ecpointformatlist;
-               plen = s->session->tlsext_ecpointformatlist_length;
-               for (i = 0; i < plen; i++, p++)
+               pformats = s->session->tlsext_ecpointformatlist;
+               num_formats = s->session->tlsext_ecpointformatlist_length;
+               for (i = 0; i < num_formats; i++, pformats++)
                        {
-                       if (*comp_id == *p)
+                       if (*comp_id == *pformats)
                                break;
                        }
-               if (i == plen)
+               if (i == num_formats)
                        return 0;
                }
        if (!curve_id)
@@ -712,13 +790,15 @@ static int tls1_check_ec_key(SSL *s,
        /* Check curve is consistent with client and server preferences */
        for (j = 0; j <= 1; j++)
                {
-               tls1_get_curvelist(s, j, &p, &plen);
-               for (i = 0; i < plen; i+=2, p+=2)
+               if (!tls1_get_curvelist(s, j, &pcurves, &num_curves))
+                       return 0;
+               for (i = 0; i < num_curves; i++, pcurves += 2)
                        {
-                       if (p[0] == curve_id[0] && p[1] == curve_id[1])
+                       if (pcurves[0] == curve_id[0] &&
+                           pcurves[1] == curve_id[1])
                                break;
                        }
-               if (i == plen)
+               if (i == num_curves)
                        return 0;
                /* For clients can only check sent curve list */
                if (!s->server)
@@ -728,23 +808,23 @@ static int tls1_check_ec_key(SSL *s,
        }
 
 static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
-                                       size_t *pformatslen)
+                                       size_t *num_formats)
        {
        /* If we have a custom point format list use it otherwise
         * use default */
        if (s->tlsext_ecpointformatlist)
                {
                *pformats = s->tlsext_ecpointformatlist;
-               *pformatslen = s->tlsext_ecpointformatlist_length;
+               *num_formats = s->tlsext_ecpointformatlist_length;
                }
        else
                {
                *pformats = ecformats_default;
                /* For Suite B we don't support char2 fields */
                if (tls1_suiteb(s))
-                       *pformatslen = sizeof(ecformats_default) - 1;
+                       *num_formats = sizeof(ecformats_default) - 1;
                else
-                       *pformatslen = sizeof(ecformats_default);
+                       *num_formats = sizeof(ecformats_default);
                }
        }
 
@@ -807,6 +887,7 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
                }
        return rv;
        }
+#ifndef OPENSSL_NO_ECDH
 /* Check EC temporary key is compatible with client extensions */
 int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
        {
@@ -873,6 +954,7 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
        return tls1_check_ec_key(s, curve_id, NULL);
 #endif
        }
+#endif /* OPENSSL_NO_ECDH */
 
 #else
 
@@ -1189,13 +1271,14 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                unsigned long size_str;
                long lenmax; 
 
-               /* check for enough space.
-                  4 for the servername type and entension length
-                  2 for servernamelist length
-                  1 for the hostname type
-                  2 for hostname length
-                  + hostname length 
-               */
+               /*-
+                * check for enough space.
+                * 4 for the servername type and entension length
+                * 2 for servernamelist length
+                * 1 for the hostname type
+                * 2 for hostname length
+                * + hostname length 
+                */
                   
                if ((lenmax = limit - ret - 9) < 0 
                    || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) 
@@ -1252,11 +1335,12 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                        return NULL;
                        } 
 
-               /* check for enough space.
-                  4 for the srp type type and entension length
-                  1 for the srp user identity
-                  + srp user identity length 
-               */
+               /*-
+                * check for enough space.
+                * 4 for the srp type type and entension length
+                * 1 for the srp user identity
+                * + srp user identity length 
+                */
                if ((limit - ret - 5 - login_len) < 0) return NULL; 
 
                /* fill in the extension */
@@ -1273,48 +1357,44 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                {
                /* Add TLS extension ECPointFormats to the ClientHello message */
                long lenmax; 
-               const unsigned char *plist;
-               size_t plistlen;
+               const unsigned char *pcurves, *pformats;
+               size_t num_curves, num_formats, curves_list_len;
 
-               tls1_get_formatlist(s, &plist, &plistlen);
+               tls1_get_formatlist(s, &pformats, &num_formats);
 
                if ((lenmax = limit - ret - 5) < 0) return NULL; 
-               if (plistlen > (size_t)lenmax) return NULL;
-               if (plistlen > 255)
+               if (num_formats > (size_t)lenmax) return NULL;
+               if (num_formats > 255)
                        {
                        SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
                        return NULL;
                        }
                
                s2n(TLSEXT_TYPE_ec_point_formats,ret);
-               s2n(plistlen + 1,ret);
-               *(ret++) = (unsigned char)plistlen ;
-               memcpy(ret, plist, plistlen);
-               ret+=plistlen;
+               /* The point format list has 1-byte length. */
+               s2n(num_formats + 1,ret);
+               *(ret++) = (unsigned char)num_formats ;
+               memcpy(ret, pformats, num_formats);
+               ret+=num_formats;
 
                /* Add TLS extension EllipticCurves to the ClientHello message */
-               plist = s->tlsext_ellipticcurvelist;
-               tls1_get_curvelist(s, 0, &plist, &plistlen);
+               pcurves = s->tlsext_ellipticcurvelist;
+               if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves))
+                       return NULL;
 
                if ((lenmax = limit - ret - 6) < 0) return NULL; 
-               if (plistlen > (size_t)lenmax) return NULL;
-               if (plistlen > 65532)
+               if (num_curves > (size_t)lenmax / 2) return NULL;
+               if (num_curves > 65532 / 2)
                        {
                        SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
                        return NULL;
                        }
-               
+               curves_list_len = 2*num_curves;
                s2n(TLSEXT_TYPE_elliptic_curves,ret);
-               s2n(plistlen + 2, ret);
-
-               /* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for
-                * elliptic_curve_list, but the examples use two bytes.
-                * http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html
-                * resolves this to two bytes.
-                */
-               s2n(plistlen, ret);
-               memcpy(ret, plist, plistlen);
-               ret+=plistlen;
+               s2n(curves_list_len + 2, ret);
+               s2n(curves_list_len, ret);
+               memcpy(ret, pcurves, curves_list_len);
+               ret+=curves_list_len;
                }
 #endif /* OPENSSL_NO_EC */
 
@@ -1440,7 +1520,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                return NULL;
        s2n(TLSEXT_TYPE_heartbeat,ret);
        s2n(1,ret);
-       /* Set mode:
+       /*-
+        * Set mode:
         * 1: peer may send requests
         * 2: peer not allowed to send requests
         */
@@ -1474,6 +1555,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                ret += s->alpn_client_proto_list_len;
                }
 
+#ifndef OPENSSL_NO_SRTP
         if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
                 {
                 int el;
@@ -1492,6 +1574,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                        }
                 ret += el;
                 }
+#endif
        custom_ext_init(&s->cert->cli_ext);
        /* Add custom TLS Extensions to ClientHello */
        if (!custom_ext_add(s, 0, &ret, limit, al))
@@ -1648,6 +1731,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
                }
 #endif
 
+#ifndef OPENSSL_NO_SRTP
         if(SSL_IS_DTLS(s) && s->srtp_profile)
                 {
                 int el;
@@ -1666,6 +1750,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
                        }
                 ret+=el;
                 }
+#endif
 
        if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81) 
                && (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
@@ -1690,7 +1775,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
                        return NULL;
                s2n(TLSEXT_TYPE_heartbeat,ret);
                s2n(1,ret);
-               /* Set mode:
+               /*-
+                * Set mode:
                 * 1: peer may send requests
                 * 2: peer not allowed to send requests
                 */
@@ -1749,7 +1835,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
        }
 
 #ifndef OPENSSL_NO_EC
-/* ssl_check_for_safari attempts to fingerprint Safari using OS X
+/*-
+ * ssl_check_for_safari attempts to fingerprint Safari using OS X
  * SecureTransport using the TLS extension block in |d|, of length |n|.
  * Safari, since 10.6, sends exactly these extensions, in this order:
  *   SNI,
@@ -1908,7 +1995,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 +2024,16 @@ 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++)
+
+#ifndef OPENSSL_NO_SRP
+       if (s->srp_ctx.login != NULL)
                {
-               s->cert->pkeys[i].digest = NULL;
-               s->cert->pkeys[i].valid_flags = 0;
+               OPENSSL_free(s->srp_ctx.login);
+               s->srp_ctx.login = NULL;
                }
+#endif
+
+       s->srtp_profile = NULL;
 
        if (data >= (d+n-2))
                goto ri_check;
@@ -1971,28 +2055,30 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                if (s->tlsext_debug_cb)
                        s->tlsext_debug_cb(s, 0, type, data, size,
                                                s->tlsext_debug_arg);
-/* The servername extension is treated as follows:
-
-   - Only the hostname type is supported with a maximum length of 255.
-   - The servername is rejected if too long or if it contains zeros,
-     in which case an fatal alert is generated.
-   - The servername field is maintained together with the session cache.
-   - When a session is resumed, the servername call back invoked in order
-     to allow the application to position itself to the right context. 
-   - The servername is acknowledged if it is new for a session or when 
-     it is identical to a previously used for the same session. 
-     Applications can control the behaviour.  They can at any time
-     set a 'desirable' servername for a new SSL object. This can be the
-     case for example with HTTPS when a Host: header field is received and
-     a renegotiation is requested. In this case, a possible servername
-     presented in the new client hello is only acknowledged if it matches
-     the value of the Host: field. 
-   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
-     if they provide for changing an explicit servername context for the session,
-     i.e. when the session has been established with a servername extension. 
-   - On session reconnect, the servername extension may be absent. 
-
-*/      
+/*-
+ * The servername extension is treated as follows:
+ *
+ * - Only the hostname type is supported with a maximum length of 255.
+ * - The servername is rejected if too long or if it contains zeros,
+ *   in which case an fatal alert is generated.
+ * - The servername field is maintained together with the session cache.
+ * - When a session is resumed, the servername call back invoked in order
+ *   to allow the application to position itself to the right context. 
+ * - The servername is acknowledged if it is new for a session or when 
+ *   it is identical to a previously used for the same session. 
+ *   Applications can control the behaviour.  They can at any time
+ *   set a 'desirable' servername for a new SSL object. This can be the
+ *   case for example with HTTPS when a Host: header field is received and
+ *   a renegotiation is requested. In this case, a possible servername
+ *   presented in the new client hello is only acknowledged if it matches
+ *   the value of the Host: field. 
+ * - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+ *   if they provide for changing an explicit servername context for the 
+ *   session, i.e. when the session has been established with a servername 
+ *   extension. 
+ * - On session reconnect, the servername extension may be absent. 
+ *
+ */      
 
                if (type == TLSEXT_TYPE_server_name)
                        {
@@ -2146,7 +2232,9 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                        ellipticcurvelist_length += (*(sdata++));
 
                        if (ellipticcurvelist_length != size - 2 ||
-                               ellipticcurvelist_length < 1)
+                               ellipticcurvelist_length < 1 ||
+                               /* Each NamedCurve is 2 bytes. */
+                               ellipticcurvelist_length & 1)
                                {
                                *al = TLS1_AD_DECODE_ERROR;
                                return 0;
@@ -2195,8 +2283,10 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 
                        if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
                                OPENSSL_free(s->s3->client_opaque_prf_input);
+                               
+                       /* dummy byte just to get non-NULL */
                        if (s->s3->client_opaque_prf_input_len == 0)
-                               s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+                               s->s3->client_opaque_prf_input = OPENSSL_malloc(1);
                        else
                                s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
                        if (s->s3->client_opaque_prf_input == NULL)
@@ -2236,21 +2326,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)
                        {
@@ -2385,7 +2465,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                         s->s3->tmp.finish_md_len == 0 &&
                         s->s3->alpn_selected == NULL)
                        {
-                       /* We shouldn't accept this extension on a
+                       /*-
+                        * We shouldn't accept this extension on a
                         * renegotiation.
                         *
                         * s->new_session will be set on renegotiation, but we
@@ -2394,12 +2475,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                         * there's some other reason to disallow resuming an
                         * earlier session -- the current code won't be doing
                         * anything like that, but this might change).
-
+                        *
                         * A valid sign that there's been a previous handshake
                         * in this connection is if s->s3->tmp.finish_md_len >
                         * 0.  (We are talking about a check that will happen
                         * in the Hello protocol round, well before a new
-                        * Finished message could have been computed.) */
+                        * Finished message could have been computed.) 
+                        */
                        s->s3->next_proto_neg_seen = 1;
                        }
 #endif
@@ -2417,6 +2499,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                        }
 
                /* session ticket processed earlier */
+#ifndef OPENSSL_NO_SRTP
                else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
                                && type == TLSEXT_TYPE_use_srtp)
                         {
@@ -2424,6 +2507,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                                              al))
                                return 0;
                         }
+#endif
 
                data+=size;
                }
@@ -2442,9 +2526,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;
        }
@@ -2548,6 +2629,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
 #ifndef OPENSSL_NO_NEXTPROTONEG
        s->s3->next_proto_neg_seen = 0;
 #endif
+       s->tlsext_ticket_expected = 0;
 
        if (s->s3->alpn_selected)
                {
@@ -2736,10 +2818,12 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                                *al = TLS1_AD_DECODE_ERROR;
                                return 0;
                                }
-                       /* The extension data consists of:
+                       /*- 
+                        * The extension data consists of:
                         *   uint16 list_length
                         *   uint8 proto_length;
-                        *   uint8 proto[proto_length]; */
+                        *   uint8 proto[proto_length]; 
+                        */
                        len = data[0];
                        len <<= 8;
                        len |= data[1];
@@ -2789,12 +2873,14 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                                }
                        }
 #endif
+#ifndef OPENSSL_NO_SRTP
                else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp)
                         {
                         if(ssl_parse_serverhello_use_srtp_ext(s, data, size,
                                                              al))
                                 return 0;
                         }
+#endif
                /* If this extension type was not otherwise handled, but 
                 * matches a custom_cli_ext_record, then send it to the c
                 * callback */
@@ -2996,6 +3082,50 @@ static int ssl_check_clienthello_tlsext_early(SSL *s)
                }
        }
 
+int tls1_set_server_sigalgs(SSL *s)
+       {
+       int al;
+       size_t i;
+       /* 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_TLS1_SET_SERVER_SIGALGS,
+                                       ERR_R_MALLOC_FAILURE);
+                       al = SSL_AD_INTERNAL_ERROR;
+                       goto err;
+                       }
+               /* Fatal error is no shared signature algorithms */
+               if (!s->cert->shared_sigalgs)
+                       {
+                       SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
+                                       SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+                       al = SSL_AD_ILLEGAL_PARAMETER;
+                       goto err;
+                       }
+               }
+       else
+               ssl_cert_set_default_md(s->cert);
+       return 1;
+       err:
+       ssl3_send_alert(s, SSL3_AL_FATAL, al);
+       return 0;
+       }
+
 int ssl_check_clienthello_tlsext_late(SSL *s)
        {
        int ret = SSL_TLSEXT_ERR_OK;
@@ -3192,7 +3322,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
        return 1;
 }
 
-/* Since the server cache lookup is done early on in the processing of the
+/*-
+ * Since the server cache lookup is done early on in the processing of the
  * ClientHello, and other operations depend on the result, we need to handle
  * any TLS session ticket extension at the same time.
  *
@@ -3312,7 +3443,8 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
        return 0;
        }
 
-/* tls_decrypt_ticket attempts to decrypt a session ticket.
+/*-
+ * tls_decrypt_ticket attempts to decrypt a session ticket.
  *
  *   etick: points to the body of the session ticket extension.
  *   eticklen: the length of the session tickets extenion.
@@ -3677,13 +3809,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 +3826,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)
@@ -3925,7 +4063,8 @@ tls1_heartbeat(SSL *s)
         */
        OPENSSL_assert(payload + padding <= 16381);
 
-       /* Create HeartBeat message, we just use a sequence number
+       /*-
+        * Create HeartBeat message, we just use a sequence number
         * as payload to distuingish different messages and add
         * some random stuff.
         *  - Message Type, 1 byte
@@ -4177,13 +4316,10 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
                if (check_flags)
                        check_flags |= CERT_PKEY_SUITEB;
                ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
-               if (ok != X509_V_OK)
-                       {
-                       if (check_flags)
-                               rv |= CERT_PKEY_SUITEB;
-                       else
-                               goto end;
-                       }
+               if (ok == X509_V_OK)
+                       rv |= CERT_PKEY_SUITEB;
+               else if (!check_flags)
+                       goto end;
                }
 
        /* Check all signature algorithms are consistent with