add missing parts of reneg port, fix apps patch
[openssl.git] / ssl / t1_lib.c
index 4d6789264d381d7b16774d7014f19841ef2c112c..af196de3519a84b653e82f07647ed13312cb8833 100644 (file)
@@ -315,6 +315,30 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                ret+=size_str;
                }
 
+        /* Add the renegotiation option: TODOEKR switch */
+        {
+          int el;
+          
+          if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
+              {
+              SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          if((limit - p - 4 - el) < 0) return NULL;
+          
+          s2n(TLSEXT_TYPE_renegotiate,ret);
+          s2n(el,ret);
+
+          if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
+              {
+              SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          ret += el;
+        }
+
 #ifndef OPENSSL_NO_EC
        if (s->tlsext_ecpointformatlist != NULL)
                {
@@ -365,7 +389,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
        if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
                {
                int ticklen;
-               if (s->session && s->session->tlsext_tick)
+               if (!s->new_session && s->session && s->session->tlsext_tick)
                        ticklen = s->session->tlsext_ticklen;
                else if (s->session && s->tlsext_session_ticket &&
                         s->tlsext_session_ticket->data)
@@ -490,6 +514,31 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                s2n(TLSEXT_TYPE_server_name,ret);
                s2n(0,ret);
                }
+
+        if(s->s3->send_connection_binding)
+        {
+          int el;
+          
+          if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0))
+              {
+              SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          if((limit - p - 4 - el) < 0) return NULL;
+          
+          s2n(TLSEXT_TYPE_renegotiate,ret);
+          s2n(el,ret);
+
+          if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el))
+              {
+              SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+              return NULL;
+              }
+
+          ret += el;
+        }
+
 #ifndef OPENSSL_NO_EC
        if (s->tlsext_ecpointformatlist != NULL)
                {
@@ -574,11 +623,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
        unsigned short size;
        unsigned short len;
        unsigned char *data = *p;
+       int renegotiate_seen = 0;
+
        s->servername_done = 0;
        s->tlsext_status_type = -1;
+       s->s3->send_connection_binding = 0;
 
        if (data >= (d+n-2))
+               {
+               if (s->new_session
+                       && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+                       {
+                       /* We should always see one extension: the renegotiate extension */
+                       *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
+                       return 0;
+                       }
                return 1;
+               }
        n2s(data,len);
 
        if (data > (d+n-len)) 
@@ -790,6 +851,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                return 0;
                                }
                        }
+               else if (type == TLSEXT_TYPE_renegotiate)
+                       {
+                       if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+                               return 0;
+                       renegotiate_seen = 1;
+                       }
                else if (type == TLSEXT_TYPE_status_request
                                                && s->ctx->tlsext_status_cb)
                        {
@@ -894,6 +961,14 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                /* session ticket processed earlier */
                data+=size;
                }
+  
+       if (s->new_session && !renegotiate_seen
+               && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+               {
+               *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
+               return 0;
+               }
                                
        *p = data;
        return 1;
@@ -905,11 +980,22 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
        unsigned short size;
        unsigned short len;  
        unsigned char *data = *p;
-
        int tlsext_servername = 0;
+       int renegotiate_seen = 0;
 
        if (data >= (d+n-2))
+               {
+               /* Because the client does not see any renegotiation during an
+                  attack, we must enforce this on all server hellos, even the
+                  first */
+               if (!(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+                       {
+                       /* We should always see one extension: the renegotiate extension */
+                       *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
+                       return 0;
+                       }
                return 1;
+               }
 
        n2s(data,len);
 
@@ -1025,7 +1111,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                        /* Set flag to expect CertificateStatus message */
                        s->tlsext_status_expected = 1;
                        }
-
+               else if (type == TLSEXT_TYPE_renegotiate)
+                       {
+                       if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
+                               return 0;
+                       renegotiate_seen = 1;
+                       }
                data+=size;             
                }
 
@@ -1035,6 +1126,13 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                return 0;
                }
 
+       if (!renegotiate_seen
+               && !(s->ctx->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
+               {
+               *al = SSL_AD_ILLEGAL_PARAMETER; /* is this the right alert? */
+               return 0;
+               }
+
        if (!s->hit && tlsext_servername == 1)
                {
                if (s->tlsext_hostname)
@@ -1516,16 +1614,17 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        unsigned char tick_hmac[EVP_MAX_MD_SIZE];
        HMAC_CTX hctx;
        EVP_CIPHER_CTX ctx;
+       SSL_CTX *tctx = s->initial_ctx;
        /* Need at least keyname + iv + some encrypted data */
        if (eticklen < 48)
                goto tickerr;
        /* Initialize session ticket encryption and HMAC contexts */
        HMAC_CTX_init(&hctx);
        EVP_CIPHER_CTX_init(&ctx);
-       if (s->ctx->tlsext_ticket_key_cb)
+       if (tctx->tlsext_ticket_key_cb)
                {
                unsigned char *nctick = (unsigned char *)etick;
-               int rv = s->ctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
+               int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
                                                        &ctx, &hctx, 0);
                if (rv < 0)
                        return -1;
@@ -1537,12 +1636,12 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        else
                {
                /* Check key name matches */
-               if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
+               if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
                        goto tickerr;
-               HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+               HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
                                        tlsext_tick_md(), NULL);
                EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                               s->ctx->tlsext_tick_aes_key, etick + 16);
+                               tctx->tlsext_tick_aes_key, etick + 16);
                }
        /* Attempt to process session ticket, first conduct sanity and
         * integrity checks on ticket.