Prepare for 1.0.1j release
[openssl.git] / ssl / t1_lib.c
index 01e8fc9c6802afb7d87bbd01ad412d604aa3a99e..d6aff4b682f234499862819c4a68b15e6a869fe9 100644 (file)
@@ -342,33 +342,26 @@ static unsigned char tls12_sigalgs[] = {
 #ifndef OPENSSL_NO_SHA
        tlsext_sigalg(TLSEXT_hash_sha1)
 #endif
-#ifndef OPENSSL_NO_MD5
-       tlsext_sigalg_rsa(TLSEXT_hash_md5)
-#endif
 };
 
 int tls12_get_req_sig_algs(SSL *s, unsigned char *p)
        {
        size_t slen = sizeof(tls12_sigalgs);
-#ifdef OPENSSL_FIPS
-       /* If FIPS mode don't include MD5 which is last */
-       if (FIPS_mode())
-               slen -= 2;
-#endif
        if (p)
                memcpy(p, tls12_sigalgs, slen);
        return (int)slen;
        }
 
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit)
        {
        int extdatalen=0;
-       unsigned char *ret = p;
+       unsigned char *orig = buf;
+       unsigned char *ret = buf;
 
        /* don't add extensions for SSLv3 unless doing secure renegotiation */
        if (s->client_version == SSL3_VERSION
                                        && !s->s3->send_connection_binding)
-               return p;
+               return orig;
 
        ret+=2;
 
@@ -417,7 +410,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
               return NULL;
               }
 
-          if((limit - p - 4 - el) < 0) return NULL;
+          if((limit - ret - 4 - el) < 0) return NULL;
           
           s2n(TLSEXT_TYPE_renegotiate,ret);
           s2n(el,ret);
@@ -432,32 +425,35 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
         }
 
 #ifndef OPENSSL_NO_SRP
-#define MIN(x,y) (((x)<(y))?(x):(y))
-       /* we add SRP username the first time only if we have one! */
+       /* Add SRP username if there is one */
        if (s->srp_ctx.login != NULL)
-               {/* Add TLS extension SRP username to the Client Hello message */
-               int login_len = MIN(strlen(s->srp_ctx.login) + 1, 255);
-               long lenmax; 
+               { /* Add TLS extension SRP username to the Client Hello message */
 
-               if ((lenmax = limit - ret - 5) < 0) return NULL; 
-               if (login_len > lenmax) return NULL;
-               if (login_len > 255)
+               int login_len = strlen(s->srp_ctx.login);       
+               if (login_len > 255 || login_len == 0)
                        {
                        SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
                        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 
+               */
+               if ((limit - ret - 5 - login_len) < 0) return NULL; 
+
+               /* fill in the extension */
                s2n(TLSEXT_TYPE_srp,ret);
                s2n(login_len+1,ret);
-
-               (*ret++) = (unsigned char) MIN(strlen(s->srp_ctx.login), 254);
-               memcpy(ret, s->srp_ctx.login, MIN(strlen(s->srp_ctx.login), 254));
+               (*ret++) = (unsigned char) login_len;
+               memcpy(ret, s->srp_ctx.login, login_len);
                ret+=login_len;
                }
 #endif
 
 #ifndef OPENSSL_NO_EC
-       if (s->tlsext_ecpointformatlist != NULL &&
-           s->version != DTLS1_VERSION)
+       if (s->tlsext_ecpointformatlist != NULL)
                {
                /* Add TLS extension ECPointFormats to the ClientHello message */
                long lenmax; 
@@ -476,8 +472,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
                ret+=s->tlsext_ecpointformatlist_length;
                }
-       if (s->tlsext_ellipticcurvelist != NULL &&
-           s->version != DTLS1_VERSION)
+       if (s->tlsext_ellipticcurvelist != NULL)
                {
                /* Add TLS extension EllipticCurves to the ClientHello message */
                long lenmax; 
@@ -540,7 +535,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
                skip_ext:
 
-       if (TLS1_get_version(s) >= TLS1_2_VERSION)
+       if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
                {
                if ((size_t)(limit - ret) < sizeof(tls12_sigalgs) + 6)
                        return NULL; 
@@ -621,6 +616,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
 
 #ifndef OPENSSL_NO_HEARTBEATS
        /* Add Heartbeat extension */
+       if ((limit - ret - 4 - 1) < 0)
+               return NULL;
        s2n(TLSEXT_TYPE_heartbeat,ret);
        s2n(1,ret);
        /* Set mode:
@@ -645,13 +642,14 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 #endif
 
-        if(SSL_get_srtp_profiles(s))
+#ifndef OPENSSL_NO_SRTP
+       if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
                 {
                 int el;
 
                 ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0);
                 
-                if((limit - p - 4 - el) < 0) return NULL;
+                if((limit - ret - 4 - el) < 0) return NULL;
 
                 s2n(TLSEXT_TYPE_use_srtp,ret);
                 s2n(el,ret);
@@ -663,25 +661,56 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                        }
                 ret += el;
                 }
+#endif
+       /* Add padding to workaround bugs in F5 terminators.
+        * See https://tools.ietf.org/html/draft-agl-tls-padding-03
+        *
+        * NB: because this code works out the length of all existing
+        * extensions it MUST always appear last.
+        */
+       if (s->options & SSL_OP_TLSEXT_PADDING)
+               {
+               int hlen = ret - (unsigned char *)s->init_buf->data;
+               /* The code in s23_clnt.c to build ClientHello messages
+                * includes the 5-byte record header in the buffer, while
+                * the code in s3_clnt.c does not.
+                */
+               if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
+                       hlen -= 5;
+               if (hlen > 0xff && hlen < 0x200)
+                       {
+                       hlen = 0x200 - hlen;
+                       if (hlen >= 4)
+                               hlen -= 4;
+                       else
+                               hlen = 0;
 
-       if ((extdatalen = ret-p-2)== 0) 
-               return p;
+                       s2n(TLSEXT_TYPE_padding, ret);
+                       s2n(hlen, ret);
+                       memset(ret, 0, hlen);
+                       ret += hlen;
+                       }
+               }
+
+       if ((extdatalen = ret-orig-2)== 0) 
+               return orig;
 
-       s2n(extdatalen,p);
+       s2n(extdatalen, orig);
        return ret;
        }
 
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit)
        {
        int extdatalen=0;
-       unsigned char *ret = p;
+       unsigned char *orig = buf;
+       unsigned char *ret = buf;
 #ifndef OPENSSL_NO_NEXTPROTONEG
        int next_proto_neg_seen;
 #endif
 
        /* don't add extensions for SSLv3, unless doing secure renegotiation */
        if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
-               return p;
+               return orig;
        
        ret+=2;
        if (ret>=limit) return NULL; /* this really never occurs, but ... */
@@ -704,7 +733,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
               return NULL;
               }
 
-          if((limit - p - 4 - el) < 0) return NULL;
+          if((limit - ret - 4 - el) < 0) return NULL;
           
           s2n(TLSEXT_TYPE_renegotiate,ret);
           s2n(el,ret);
@@ -719,8 +748,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
         }
 
 #ifndef OPENSSL_NO_EC
-       if (s->tlsext_ecpointformatlist != NULL &&
-           s->version != DTLS1_VERSION)
+       if (s->tlsext_ecpointformatlist != NULL)
                {
                /* Add TLS extension ECPointFormats to the ServerHello message */
                long lenmax; 
@@ -777,13 +805,14 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 #endif
 
-        if(s->srtp_profile)
+#ifndef OPENSSL_NO_SRTP
+       if(SSL_IS_DTLS(s) && s->srtp_profile)
                 {
                 int el;
 
                 ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0);
                 
-                if((limit - p - 4 - el) < 0) return NULL;
+                if((limit - ret - 4 - el) < 0) return NULL;
 
                 s2n(TLSEXT_TYPE_use_srtp,ret);
                 s2n(el,ret);
@@ -795,6 +824,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                        }
                 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))
@@ -812,17 +842,23 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 
 #ifndef OPENSSL_NO_HEARTBEATS
-       /* Add Heartbeat extension */
-       s2n(TLSEXT_TYPE_heartbeat,ret);
-       s2n(1,ret);
-       /* Set mode:
-        * 1: peer may send requests
-        * 2: peer not allowed to send requests
-        */
-       if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
-               *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
-       else
-               *(ret++) = SSL_TLSEXT_HB_ENABLED;
+       /* Add Heartbeat extension if we've received one */
+       if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
+               {
+               if ((limit - ret - 4 - 1) < 0)
+                       return NULL;
+               s2n(TLSEXT_TYPE_heartbeat,ret);
+               s2n(1,ret);
+               /* Set mode:
+                * 1: peer may send requests
+                * 2: peer not allowed to send requests
+                */
+               if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
+                       *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
+               else
+                       *(ret++) = SSL_TLSEXT_HB_ENABLED;
+
+               }
 #endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -847,13 +883,96 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 #endif
 
-       if ((extdatalen = ret-p-2)== 0) 
-               return p;
+       if ((extdatalen = ret-orig-2)== 0) 
+               return orig;
 
-       s2n(extdatalen,p);
+       s2n(extdatalen, orig);
        return ret;
        }
 
+#ifndef OPENSSL_NO_EC
+/* 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,
+ *   elliptic_curves
+ *   ec_point_formats
+ *
+ * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
+ * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
+ * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
+ * 10.8..10.8.3 (which don't work).
+ */
+static void ssl_check_for_safari(SSL *s, const unsigned char *data, const unsigned char *d, int n) {
+       unsigned short type, size;
+       static const unsigned char kSafariExtensionsBlock[] = {
+               0x00, 0x0a,  /* elliptic_curves extension */
+               0x00, 0x08,  /* 8 bytes */
+               0x00, 0x06,  /* 6 bytes of curve ids */
+               0x00, 0x17,  /* P-256 */
+               0x00, 0x18,  /* P-384 */
+               0x00, 0x19,  /* P-521 */
+
+               0x00, 0x0b,  /* ec_point_formats */
+               0x00, 0x02,  /* 2 bytes */
+               0x01,        /* 1 point format */
+               0x00,        /* uncompressed */
+       };
+
+       /* The following is only present in TLS 1.2 */
+       static const unsigned char kSafariTLS12ExtensionsBlock[] = {
+               0x00, 0x0d,  /* signature_algorithms */
+               0x00, 0x0c,  /* 12 bytes */
+               0x00, 0x0a,  /* 10 bytes */
+               0x05, 0x01,  /* SHA-384/RSA */
+               0x04, 0x01,  /* SHA-256/RSA */
+               0x02, 0x01,  /* SHA-1/RSA */
+               0x04, 0x03,  /* SHA-256/ECDSA */
+               0x02, 0x03,  /* SHA-1/ECDSA */
+       };
+
+       if (data >= (d+n-2))
+               return;
+       data += 2;
+
+       if (data > (d+n-4))
+               return;
+       n2s(data,type);
+       n2s(data,size);
+
+       if (type != TLSEXT_TYPE_server_name)
+               return;
+
+       if (data+size > d+n)
+               return;
+       data += size;
+
+       if (TLS1_get_client_version(s) >= TLS1_2_VERSION)
+               {
+               const size_t len1 = sizeof(kSafariExtensionsBlock);
+               const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
+
+               if (data + len1 + len2 != d+n)
+                       return;
+               if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
+                       return;
+               if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
+                       return;
+               }
+       else
+               {
+               const size_t len = sizeof(kSafariExtensionsBlock);
+
+               if (data + len != d+n)
+                       return;
+               if (memcmp(data, kSafariExtensionsBlock, len) != 0)
+                       return;
+               }
+
+       s->s3->is_probably_safari = 1;
+}
+#endif /* !OPENSSL_NO_EC */
+
 int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
        {
        unsigned short type;
@@ -874,6 +993,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                               SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
 #endif
 
+#ifndef OPENSSL_NO_EC
+       if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
+               ssl_check_for_safari(s, data, d, n);
+#endif /* !OPENSSL_NO_EC */
+
        if (data >= (d+n-2))
                goto ri_check;
        n2s(data,len);
@@ -1003,20 +1127,31 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 #ifndef OPENSSL_NO_SRP
                else if (type == TLSEXT_TYPE_srp)
                        {
-                       if (size > 0)
+                       if (size <= 0 || ((len = data[0])) != (size -1))
                                {
-                               len = data[0];
-                               if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL)
-                                       return -1;
-                               memcpy(s->srp_ctx.login, &data[1], len);
-                               s->srp_ctx.login[len]='\0';  
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       if (s->srp_ctx.login != NULL)
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL)
+                               return -1;
+                       memcpy(s->srp_ctx.login, &data[1], len);
+                       s->srp_ctx.login[len]='\0';
+  
+                       if (strlen(s->srp_ctx.login) != len) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
                                }
                        }
 #endif
 
 #ifndef OPENSSL_NO_EC
-               else if (type == TLSEXT_TYPE_ec_point_formats &&
-                    s->version != DTLS1_VERSION)
+               else if (type == TLSEXT_TYPE_ec_point_formats)
                        {
                        unsigned char *sdata = data;
                        int ecpointformatlist_length = *(sdata++);
@@ -1050,14 +1185,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                        fprintf(stderr,"\n");
 #endif
                        }
-               else if (type == TLSEXT_TYPE_elliptic_curves &&
-                    s->version != DTLS1_VERSION)
+               else if (type == TLSEXT_TYPE_elliptic_curves)
                        {
                        unsigned char *sdata = data;
                        int ellipticcurvelist_length = (*(sdata++) << 8);
                        ellipticcurvelist_length += (*(sdata++));
 
-                       if (ellipticcurvelist_length != size - 2)
+                       if (ellipticcurvelist_length != size - 2 ||
+                               ellipticcurvelist_length < 1)
                                {
                                *al = TLS1_AD_DECODE_ERROR;
                                return 0;
@@ -1156,7 +1291,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                }
                        }
                else if (type == TLSEXT_TYPE_status_request &&
-                        s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
+                        s->version != DTLS1_VERSION)
                        {
                
                        if (size < 5) 
@@ -1244,6 +1379,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                sdata = data;
                                if (dsize > 0)
                                        {
+                                       if (s->tlsext_ocsp_exts)
+                                               {
+                                               sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+                                                                          X509_EXTENSION_free);
+                                               }
+
                                        s->tlsext_ocsp_exts =
                                                d2i_X509_EXTENSIONS(NULL,
                                                        &sdata, dsize);
@@ -1273,6 +1414,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
                                                        break;
+                               default:        *al = SSL_AD_ILLEGAL_PARAMETER;
+                                                       return 0;
                                }
                        }
 #endif
@@ -1300,12 +1443,15 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 #endif
 
                /* session ticket processed earlier */
-               else if (type == TLSEXT_TYPE_use_srtp)
-                        {
+#ifndef OPENSSL_NO_SRTP
+               else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
+                        && type == TLSEXT_TYPE_use_srtp)
+                       {
                        if(ssl_parse_clienthello_use_srtp_ext(s, data, size,
                                                              al))
                                return 0;
-                        }
+                       }
+#endif
 
                data+=size;
                }
@@ -1399,26 +1545,29 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                        }
 
 #ifndef OPENSSL_NO_EC
-               else if (type == TLSEXT_TYPE_ec_point_formats &&
-                    s->version != DTLS1_VERSION)
+               else if (type == TLSEXT_TYPE_ec_point_formats)
                        {
                        unsigned char *sdata = data;
                        int ecpointformatlist_length = *(sdata++);
 
-                       if (ecpointformatlist_length != size - 1)
+                       if (ecpointformatlist_length != size - 1 || 
+                               ecpointformatlist_length < 1)
                                {
                                *al = TLS1_AD_DECODE_ERROR;
                                return 0;
                                }
-                       s->session->tlsext_ecpointformatlist_length = 0;
-                       if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
-                       if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+                       if (!s->hit)
                                {
-                               *al = TLS1_AD_INTERNAL_ERROR;
-                               return 0;
+                               s->session->tlsext_ecpointformatlist_length = 0;
+                               if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+                               if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+                                       {
+                                       *al = TLS1_AD_INTERNAL_ERROR;
+                                       return 0;
+                                       }
+                               s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+                               memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
                                }
-                       s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
-                       memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
 #if 0
                        fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
                        sdata = s->session->tlsext_ecpointformatlist;
@@ -1499,7 +1648,7 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                        unsigned char selected_len;
 
                        /* We must have requested it. */
-                       if ((s->ctx->next_proto_select_cb == NULL))
+                       if (s->ctx->next_proto_select_cb == NULL)
                                {
                                *al = TLS1_AD_UNSUPPORTED_EXTENSION;
                                return 0;
@@ -1544,15 +1693,19 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
                                                        break;
+                               default:        *al = SSL_AD_ILLEGAL_PARAMETER;
+                                                       return 0;
                                }
                        }
 #endif
-               else if (type == TLSEXT_TYPE_use_srtp)
-                        {
+#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
 
                data+=size;             
                }
@@ -1733,7 +1886,7 @@ int ssl_prepare_serverhello_tlsext(SSL *s)
        return 1;
        }
 
-int ssl_check_clienthello_tlsext(SSL *s)
+int ssl_check_clienthello_tlsext_early(SSL *s)
        {
        int ret=SSL_TLSEXT_ERR_NOACK;
        int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -1752,42 +1905,12 @@ int ssl_check_clienthello_tlsext(SSL *s)
        else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
                ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
 
-       /* If status request then ask callback what to do.
-        * Note: this must be called after servername callbacks in case 
-        * the certificate has changed.
-        */
-       if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
-               {
-               int r;
-               r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
-               switch (r)
-                       {
-                       /* We don't want to send a status request response */
-                       case SSL_TLSEXT_ERR_NOACK:
-                               s->tlsext_status_expected = 0;
-                               break;
-                       /* status request response should be sent */
-                       case SSL_TLSEXT_ERR_OK:
-                               if (s->tlsext_ocsp_resp)
-                                       s->tlsext_status_expected = 1;
-                               else
-                                       s->tlsext_status_expected = 0;
-                               break;
-                       /* something bad happened */
-                       case SSL_TLSEXT_ERR_ALERT_FATAL:
-                               ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-                               al = SSL_AD_INTERNAL_ERROR;
-                               goto err;
-                       }
-               }
-       else
-               s->tlsext_status_expected = 0;
-
 #ifdef TLSEXT_TYPE_opaque_prf_input
        {
                /* This sort of belongs into ssl_prepare_serverhello_tlsext(),
                 * but we might be sending an alert in response to the client hello,
-                * so this has to happen here in ssl_check_clienthello_tlsext(). */
+                * so this has to happen here in
+                * ssl_check_clienthello_tlsext_early(). */
 
                int r = 1;
        
@@ -1839,8 +1962,8 @@ int ssl_check_clienthello_tlsext(SSL *s)
                        }
        }
 
-#endif
  err:
+#endif
        switch (ret)
                {
                case SSL_TLSEXT_ERR_ALERT_FATAL:
@@ -1858,6 +1981,71 @@ int ssl_check_clienthello_tlsext(SSL *s)
                }
        }
 
+int ssl_check_clienthello_tlsext_late(SSL *s)
+       {
+       int ret = SSL_TLSEXT_ERR_OK;
+       int al;
+
+       /* If status request then ask callback what to do.
+        * Note: this must be called after servername callbacks in case 
+        * the certificate has changed, and must be called after the cipher
+        * has been chosen because this may influence which certificate is sent
+        */
+       if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
+               {
+               int r;
+               CERT_PKEY *certpkey;
+               certpkey = ssl_get_server_send_pkey(s);
+               /* If no certificate can't return certificate status */
+               if (certpkey == NULL)
+                       {
+                       s->tlsext_status_expected = 0;
+                       return 1;
+                       }
+               /* Set current certificate to one we will use so
+                * SSL_get_certificate et al can pick it up.
+                */
+               s->cert->key = certpkey;
+               r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+               switch (r)
+                       {
+                       /* We don't want to send a status request response */
+                       case SSL_TLSEXT_ERR_NOACK:
+                               s->tlsext_status_expected = 0;
+                               break;
+                       /* status request response should be sent */
+                       case SSL_TLSEXT_ERR_OK:
+                               if (s->tlsext_ocsp_resp)
+                                       s->tlsext_status_expected = 1;
+                               else
+                                       s->tlsext_status_expected = 0;
+                               break;
+                       /* something bad happened */
+                       case SSL_TLSEXT_ERR_ALERT_FATAL:
+                               ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                               al = SSL_AD_INTERNAL_ERROR;
+                               goto err;
+                       }
+               }
+       else
+               s->tlsext_status_expected = 0;
+
+ err:
+       switch (ret)
+               {
+               case SSL_TLSEXT_ERR_ALERT_FATAL:
+                       ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+                       return -1;
+
+               case SSL_TLSEXT_ERR_ALERT_WARNING:
+                       ssl3_send_alert(s,SSL3_AL_WARNING,al);
+                       return 1; 
+
+               default:
+                       return 1;
+               }
+       }
+
 int ssl_check_serverhello_tlsext(SSL *s)
        {
        int ret=SSL_TLSEXT_ERR_NOACK;
@@ -2159,8 +2347,11 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        HMAC_Update(&hctx, etick, eticklen);
        HMAC_Final(&hctx, tick_hmac, NULL);
        HMAC_CTX_cleanup(&hctx);
-       if (memcmp(tick_hmac, etick + eticklen, mlen))
+       if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen))
+               {
+               EVP_CIPHER_CTX_cleanup(&ctx);
                return 2;
+               }
        /* Attempt to decrypt session data */
        /* Move p after IV to start of encrypted ticket, update length */
        p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
@@ -2173,7 +2364,11 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
                }
        EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
        if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+               {
+               EVP_CIPHER_CTX_cleanup(&ctx);
+               OPENSSL_free(sdec);
                return 2;
+               }
        slen += mlen;
        EVP_CIPHER_CTX_cleanup(&ctx);
        p = sdec;
@@ -2231,7 +2426,7 @@ static tls12_lookup tls12_sig[] = {
 #ifndef OPENSSL_NO_RSA
        {EVP_PKEY_RSA, TLSEXT_signature_rsa},
 #endif
-#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_DSA
        {EVP_PKEY_DSA, TLSEXT_signature_dsa},
 #endif
 #ifndef OPENSSL_NO_ECDSA
@@ -2265,6 +2460,8 @@ static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
 int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
        {
        int sig_id, md_id;
+       if (!md)
+               return 0;
        md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
                                sizeof(tls12_md)/sizeof(tls12_lookup));
        if (md_id == -1)
@@ -2287,14 +2484,6 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
        {
        switch(hash_alg)
                {
-#ifndef OPENSSL_NO_MD5
-               case TLSEXT_hash_md5:
-#ifdef OPENSSL_FIPS
-               if (FIPS_mode())
-                       return NULL;
-#endif
-               return EVP_md5();
-#endif
 #ifndef OPENSSL_NO_SHA
                case TLSEXT_hash_sha1:
                return EVP_sha1();
@@ -2382,7 +2571,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
         */
 #ifndef OPENSSL_NO_DSA
        if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
-               c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_dss1();
+               c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
 #endif
 #ifndef OPENSSL_NO_RSA
        if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
@@ -2393,7 +2582,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 #endif
 #ifndef OPENSSL_NO_ECDSA
        if (!c->pkeys[SSL_PKEY_ECC].digest)
-               c->pkeys[SSL_PKEY_ECC].digest = EVP_ecdsa();
+               c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
 #endif
        return 1;
        }
@@ -2409,16 +2598,20 @@ tls1_process_heartbeat(SSL *s)
        unsigned int payload;
        unsigned int padding = 16; /* Use minimum padding */
 
-       /* Read type and payload length first */
-       hbtype = *p++;
-       n2s(p, payload);
-       pl = p;
-
        if (s->msg_callback)
                s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
                        &s->s3->rrec.data[0], s->s3->rrec.length,
                        s, s->msg_callback_arg);
 
+       /* Read type and payload length first */
+       if (1 + 2 + 16 > s->s3->rrec.length)
+               return 0; /* silently discard */
+       hbtype = *p++;
+       n2s(p, payload);
+       if (1 + 2 + payload + 16 > s->s3->rrec.length)
+               return 0; /* silently discard per RFC 6520 sec. 4 */
+       pl = p;
+
        if (hbtype == TLS1_HB_REQUEST)
                {
                unsigned char *buffer, *bp;
@@ -2435,7 +2628,10 @@ tls1_process_heartbeat(SSL *s)
                *bp++ = TLS1_HB_RESPONSE;
                s2n(payload, bp);
                memcpy(bp, pl, payload);
-               
+               bp += payload;
+               /* Random padding */
+               RAND_pseudo_bytes(bp, padding);
+
                r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
 
                if (r >= 0 && s->msg_callback)