Add conditional unit testing interface.
[openssl.git] / ssl / t1_lib.c
index 26fc45c7df020302a9d554fdef638d655711f112..4374d6aadd3d5b0804d13d338b27408d8102e8b5 100644 (file)
@@ -131,7 +131,7 @@ static int ssl_check_clienthello_tlsext_early(SSL *s);
 int ssl_check_serverhello_tlsext(SSL *s);
 #endif
 
-SSL3_ENC_METHOD TLSv1_enc_data={
+SSL3_ENC_METHOD const TLSv1_enc_data={
        tls1_enc,
        tls1_mac,
        tls1_setup_key_block,
@@ -150,7 +150,7 @@ SSL3_ENC_METHOD TLSv1_enc_data={
        ssl3_handshake_write
        };
 
-SSL3_ENC_METHOD TLSv1_1_enc_data={
+SSL3_ENC_METHOD const TLSv1_1_enc_data={
        tls1_enc,
        tls1_mac,
        tls1_setup_key_block,
@@ -169,7 +169,7 @@ SSL3_ENC_METHOD TLSv1_1_enc_data={
        ssl3_handshake_write
        };
 
-SSL3_ENC_METHOD TLSv1_2_enc_data={
+SSL3_ENC_METHOD const TLSv1_2_enc_data={
        tls1_enc,
        tls1_mac,
        tls1_setup_key_block,
@@ -1106,10 +1106,11 @@ static int tls_use_ticket(SSL *s)
        return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
        }
 
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
        {
        int extdatalen=0;
-       unsigned char *ret = p;
+       unsigned char *orig = buf;
+       unsigned char *ret = buf;
 #ifndef OPENSSL_NO_EC
        /* See if we support any ECC ciphersuites */
        int using_ecc = 0;
@@ -1138,7 +1139,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
        /* 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;
 
@@ -1187,7 +1188,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);
@@ -1341,7 +1342,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                etmp = ret;
                /* Skip over lengths for now */
                ret += 4;
-               salglen = tls12_copy_sigalgs(s, etmp, salg, salglen);
+               salglen = tls12_copy_sigalgs(s, ret, salg, salglen);
                /* Fill in lengths */
                s2n(salglen + 2, etmp);
                s2n(salglen, etmp);
@@ -1353,7 +1354,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                {
                size_t col = s->s3->client_opaque_prf_input_len;
                
-               if ((long)(limit - ret - 6 - col < 0))
+               if ((long)(limit - ret - 6 - col) < 0)
                        return NULL;
                if (col > 0xFFFD) /* can't happen */
                        return NULL;
@@ -1416,6 +1417,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:
@@ -1458,7 +1461,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
 
                 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);
@@ -1508,47 +1511,49 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
        s2n(TLSEXT_TYPE_encrypt_then_mac,ret);
        s2n(0,ret);
 #endif
-#ifdef TLSEXT_TYPE_padding
+
        /* Add padding to workaround bugs in F5 terminators.
-        * See https://tools.ietf.org/html/draft-agl-tls-padding-02
+        * 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.
         */
-       {
-       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 (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;
 
-               s2n(TLSEXT_TYPE_padding, ret);
-               s2n(hlen, ret);
-               memset(ret, 0, hlen);
-               ret += hlen;
+                       s2n(TLSEXT_TYPE_padding, ret);
+                       s2n(hlen, ret);
+                       memset(ret, 0, hlen);
+                       ret += hlen;
+                       }
                }
-       }
-#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;
        }
 
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
        {
        int extdatalen=0;
-       unsigned char *ret = p;
+       unsigned char *orig = buf;
+       unsigned char *ret = buf;
        size_t i;
        custom_srv_ext_record *record;
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -1562,7 +1567,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 #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 ... */
@@ -1585,7 +1590,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);
@@ -1665,7 +1670,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 
                 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);
@@ -1697,6 +1702,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
        /* 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:
@@ -1789,10 +1796,10 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                ret += len;
                }
 
-       if ((extdatalen = ret-p-2)== 0) 
-               return p;
+       if ((extdatalen = ret-orig-2)== 0) 
+               return orig;
 
-       s2n(extdatalen,p);
+       s2n(extdatalen, orig);
        return ret;
        }
 
@@ -3450,7 +3457,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;
@@ -3969,16 +3980,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;