[PR3597] Advance to the next state variant when reusing messages.
[openssl.git] / ssl / t1_lib.c
index f94a4c0b8a35d44c459a16148c1e5c1f2c0a2ead..e0f28d254ba2be11a0b5fae220ff70bee7c2cb31 100644 (file)
@@ -312,7 +312,7 @@ static const unsigned char suiteb_curves[] =
 
 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;
@@ -321,7 +321,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) */
@@ -435,6 +435,10 @@ static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op)
                                sizeof(nid_list)/sizeof(nid_list[0])))
                return 0;
        cinfo = &nid_list[curve[1]-1];
+#ifdef OPENSSL_NO_EC2M
+       if (cinfo->flags & TLS_CURVE_CHAR2)
+               return 0;
+#endif
        return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)curve);
        }
 
@@ -1143,15 +1147,38 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                }
 #endif
 
-       /* don't add extensions for SSLv3 unless doing secure renegotiation */
-       if (s->client_version == SSL3_VERSION
-                                       && !s->s3->send_connection_binding)
-               return orig;
-
        ret+=2;
 
        if (ret>=limit) return NULL; /* this really never occurs, but ... */
 
+        /* Add RI if renegotiating */
+        if (s->renegotiate)
+          {
+          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 - ret - 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;
+        }
+       /* Only add RI for SSLv3 */
+       if (s->client_version == SSL3_VERSION)
+               goto done;
+
        if (s->tlsext_hostname != NULL)
                { 
                /* Add TLS extension servername to the Client Hello message */
@@ -1184,31 +1211,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                ret+=size_str;
                }
 
-        /* Add RI if renegotiating */
-        if (s->renegotiate)
-          {
-          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 - ret - 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_SRP
        /* Add SRP username if there is one */
        if (s->srp_ctx.login != NULL)
@@ -1290,11 +1292,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
 
                plistlen = etmp - ret - 4;
 
-               /* 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 + 2, ret);
                s2n(plistlen, ret);
                ret+=plistlen;
@@ -1462,7 +1459,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                ret += s->alpn_client_proto_list_len;
                }
 
-        if(SSL_get_srtp_profiles(s))
+        if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
                 {
                 int el;
 
@@ -1519,6 +1516,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
                        }
                }
 
+       done:
+
        if ((extdatalen = ret-orig-2)== 0) 
                return orig;
 
@@ -1540,21 +1539,10 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
        int using_ecc = (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
        using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
 #endif
-       /* don't add extensions for SSLv3, unless doing secure renegotiation */
-       if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
-               return orig;
        
        ret+=2;
        if (ret>=limit) return NULL; /* this really never occurs, but ... */
 
-       if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
-               { 
-               if ((long)(limit - ret - 4) < 0) return NULL; 
-
-               s2n(TLSEXT_TYPE_server_name,ret);
-               s2n(0,ret);
-               }
-
        if(s->s3->send_connection_binding)
         {
           int el;
@@ -1579,6 +1567,18 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
           ret += el;
         }
 
+       /* Only add RI for SSLv3 */
+       if (s->version == SSL3_VERSION)
+               goto done;
+
+       if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
+               {
+               if ((long)(limit - ret - 4) < 0) return NULL;
+
+               s2n(TLSEXT_TYPE_server_name,ret);
+               s2n(0,ret);
+               }
+
 #ifndef OPENSSL_NO_EC
        if (using_ecc)
                {
@@ -1639,7 +1639,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
                }
 #endif
 
-        if(s->srtp_profile)
+        if(SSL_IS_DTLS(s) && s->srtp_profile)
                 {
                 int el;
 
@@ -1719,10 +1719,11 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
 #ifdef TLSEXT_TYPE_encrypt_then_mac
        if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC)
                {
-               /* Don't use encrypt_then_mac if AEAD: might want
-                * to disable for other ciphersuites too.
+               /* Don't use encrypt_then_mac if AEAD or RC4
+                * might want to disable for other cases too.
                 */
-               if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD)
+               if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
+                   || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4)
                        s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
                else
                        {
@@ -1747,6 +1748,8 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
                ret += len;
                }
 
+       done:
+
        if ((extdatalen = ret-orig-2)== 0) 
                return orig;
 
@@ -1915,7 +1918,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;
@@ -1945,18 +1947,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                OPENSSL_free(s->cert->peer_sigalgs);
                s->cert->peer_sigalgs = NULL;
                }
-       /* Clear any shared sigtnature algorithms */
-       if (s->cert->shared_sigalgs)
-               {
-               OPENSSL_free(s->cert->shared_sigalgs);
-               s->cert->shared_sigalgs = NULL;
-               }
-       /* Clear certificate digests and validity flags */
-       for (i = 0; i < SSL_PKEY_NUM; i++)
-               {
-               s->cert->pkeys[i].digest = NULL;
-               s->cert->pkeys[i].valid_flags = 0;
-               }
 
 #ifdef TLSEXT_TYPE_encrypt_then_mac
        s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
@@ -1982,6 +1972,14 @@ 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);
+               if (type == TLSEXT_TYPE_renegotiate)
+                       {
+                       if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+                               return 0;
+                       renegotiate_seen = 1;
+                       }
+               else if (s->version == SSL3_VERSION)
+                       {}
 /* The servername extension is treated as follows:
 
    - Only the hostname type is supported with a maximum length of 255.
@@ -2005,7 +2003,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
 
 */      
 
-               if (type == TLSEXT_TYPE_server_name)
+               else if (type == TLSEXT_TYPE_server_name)
                        {
                        unsigned char *sdata;
                        int servname_type;
@@ -2226,12 +2224,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                                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_signature_algorithms)
                        {
                        int dsize;
@@ -2247,21 +2239,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)
                        {
@@ -2428,12 +2410,17 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                        }
 
                /* session ticket processed earlier */
-               else if (type == TLSEXT_TYPE_use_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;
                         }
+#ifdef TLSEXT_TYPE_encrypt_then_mac
+               else if (type == TLSEXT_TYPE_encrypt_then_mac)
+                       s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
+#endif
                /* If this ClientHello extension was unhandled and this is 
                 * a nonresumed connection, check whether the extension is a 
                 * custom TLS Extension (has a custom_srv_ext_record), and if
@@ -2442,13 +2429,9 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                 */
                else if (!s->hit)
                        {
-                       if (!custom_ext_parse(s, 1, type, data, size, al))
+                       if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
                                return 0;
                        }
-#ifdef TLSEXT_TYPE_encrypt_then_mac
-               else if (type == TLSEXT_TYPE_encrypt_then_mac)
-                       s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
-#endif
 
                data+=size;
                }
@@ -2467,9 +2450,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;
        }
@@ -2524,6 +2504,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)
                {
@@ -2562,7 +2543,16 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                        s->tlsext_debug_cb(s, 1, type, data, size,
                                                s->tlsext_debug_arg);
 
-               if (type == TLSEXT_TYPE_server_name)
+
+               if (type == TLSEXT_TYPE_renegotiate)
+                       {
+                       if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
+                               return 0;
+                       renegotiate_seen = 1;
+                       }
+               else if (s->version == SSL3_VERSION)
+                       {}
+               else if (type == TLSEXT_TYPE_server_name)
                        {
                        if (s->tlsext_hostname == NULL || size > 0)
                                {
@@ -2744,13 +2734,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                        memcpy(s->s3->alpn_selected, data + 3, len);
                        s->s3->alpn_selected_len = len;
                        }
-
-               else if (type == TLSEXT_TYPE_renegotiate)
-                       {
-                       if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
-                               return 0;
-                       renegotiate_seen = 1;
-                       }
 #ifndef OPENSSL_NO_HEARTBEATS
                else if (type == TLSEXT_TYPE_heartbeat)
                        {
@@ -2768,25 +2751,26 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                                }
                        }
 #endif
-               else if (type == TLSEXT_TYPE_use_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;
                         }
-               /* If this extension type was not otherwise handled, but 
-                * matches a custom_cli_ext_record, then send it to the c
-                * callback */
-               else if (!custom_ext_parse(s, 0, type, data, size, al))
-                               return 0;
 #ifdef TLSEXT_TYPE_encrypt_then_mac
                else if (type == TLSEXT_TYPE_encrypt_then_mac)
                        {
                        /* Ignore if inappropriate ciphersuite */
-                       if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD)
+                       if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
+                           && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
                                s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
                        }
 #endif
+               /* If this extension type was not otherwise handled, but 
+                * matches a custom_cli_ext_record, then send it to the c
+                * callback */
+               else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
+                               return 0;
  
                data += size;
                }
@@ -2983,6 +2967,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;
@@ -3369,7 +3397,10 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        HMAC_Final(&hctx, tick_hmac, NULL);
        HMAC_CTX_cleanup(&hctx);
        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);
@@ -3757,13 +3788,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;
@@ -3778,8 +3805,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)
@@ -4257,13 +4294,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