Initial support for RFC6689, a.k.a. DANE.
[oweals/openssl.git] / ssl / t1_lib.c
index 8f6ced26184bde4f12a18a3c92cbefdc170421e3..88570201a1b1a2ec0ddc85ab78b2cb9f0c145a23 100644 (file)
@@ -622,6 +622,27 @@ static int tls1_check_ec_key(SSL *s,
        return 1;
        }
 
+static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
+                                       size_t *pformatslen)
+       {
+       /* 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;
+               }
+       else
+               {
+               *pformats = ecformats_default;
+               /* For Suite B we don't support char2 fields */
+               if (tls1_suiteb(s))
+                       *pformatslen = sizeof(ecformats_default) - 1;
+               else
+                       *pformatslen = sizeof(ecformats_default);
+               }
+       }
+
 /* Check cert parameters compatible with extensions: currently just checks
  * EC certificates have compatible curves and compression.
  */
@@ -686,6 +707,11 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
        {
        unsigned char curve_id[2];
        EC_KEY *ec = s->cert->ecdh_tmp;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       /* Allow any curve: not just those peer supports */
+       if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+               return 1;
+#endif
        /* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384,
         * no other curves permitted.
         */
@@ -864,7 +890,10 @@ int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
                if (!tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec))
                        return 0;
                if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id))
+                       {
+                       SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_CURVE);
                        return 0;
+                       }
                /* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */
                if (tls1_suiteb(s))
                        {
@@ -936,7 +965,7 @@ void ssl_set_client_disabled(SSL *s)
        c->mask_a = 0;
        c->mask_k = 0;
        /* If less than TLS 1.2 don't allow TLS 1.2 only ciphers */
-       if (TLS1_get_version(s) < TLS1_2_VERSION)
+       if (TLS1_get_client_version(s) < TLS1_2_VERSION)
                c->mask_ssl = SSL_TLSV1_2;
        else
                c->mask_ssl = 0;
@@ -1145,16 +1174,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
                long lenmax; 
                const unsigned char *plist;
                size_t plistlen;
-               /* If we have a custom point format list use it otherwise
-                * use default */
-               plist = s->tlsext_ecpointformatlist;
-               if (plist)
-                       plistlen = s->tlsext_ecpointformatlist_length;
-               else
-                       {
-                       plist = ecformats_default;
-                       plistlen = sizeof(ecformats_default);
-                       }
+
+               tls1_get_formatlist(s, &plist, &plistlen);
 
                if ((lenmax = limit - ret - 5) < 0) return NULL; 
                if (plistlen > (size_t)lenmax) return NULL;
@@ -1366,11 +1387,11 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
        /* 1 byte for the list (we only support audit proofs) */
        if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
                {
-               size_t lenmax;
                 const unsigned short ext_len = 2;
                 const unsigned char list_len = 1;
 
-               if ((lenmax = limit - ret - 6) < 0) return NULL;
+               if (limit < ret + 6)
+                       return NULL;
 
                s2n(TLSEXT_TYPE_server_authz, ret);
                 /* Extension length: 2 bytes */
@@ -1393,6 +1414,10 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
 #ifndef OPENSSL_NO_NEXTPROTONEG
        int next_proto_neg_seen;
 #endif
+       unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+       unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+       int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
+       using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
 
        /* don't add extensions for SSLv3, unless doing secure renegotiation */
        if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
@@ -1434,25 +1459,28 @@ 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 (using_ecc && s->version != DTLS1_VERSION)
                {
+               const unsigned char *plist;
+               size_t plistlen;
                /* Add TLS extension ECPointFormats to the ServerHello message */
                long lenmax; 
 
+               tls1_get_formatlist(s, &plist, &plistlen);
+
                if ((lenmax = limit - ret - 5) < 0) return NULL; 
-               if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
-               if (s->tlsext_ecpointformatlist_length > 255)
+               if (plistlen > (size_t)lenmax) return NULL;
+               if (plistlen > 255)
                        {
                        SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
                        return NULL;
                        }
                
                s2n(TLSEXT_TYPE_ec_point_formats,ret);
-               s2n(s->tlsext_ecpointformatlist_length + 1,ret);
-               *(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
-               memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
-               ret+=s->tlsext_ecpointformatlist_length;
+               s2n(plistlen + 1,ret);
+               *(ret++) = (unsigned char) plistlen;
+               memcpy(ret, plist, plistlen);
+               ret+=plistlen;
 
                }
        /* Currently the server should not respond with a SupportedCurves extension */
@@ -1843,7 +1871,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
                        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;
@@ -2324,8 +2353,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                        unsigned char *sdata = data;
                        int ecpointformatlist_length = *(sdata++);
 
-                       if (ecpointformatlist_length != size - 1 || 
-                               ecpointformatlist_length < 1)
+                       if (ecpointformatlist_length != size - 1)
                                {
                                *al = TLS1_AD_DECODE_ERROR;
                                return 0;
@@ -2419,7 +2447,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
                        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;
@@ -2612,32 +2640,6 @@ int ssl_prepare_clienthello_tlsext(SSL *s)
 
 int ssl_prepare_serverhello_tlsext(SSL *s)
        {
-#ifndef OPENSSL_NO_EC
-       /* If we are server and using an ECC cipher suite, send the point formats we support 
-        * if the client sent us an ECPointsFormat extension.  Note that the server is not
-        * supposed to send an EllipticCurves extension.
-        */
-
-       unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-       unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-       int using_ecc = (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
-       using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
-       
-       if (using_ecc)
-               {
-               if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
-               if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
-                       {
-                       SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
-                       return -1;
-                       }
-               s->tlsext_ecpointformatlist_length = 3;
-               s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
-               s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
-               s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
-               }
-#endif /* OPENSSL_NO_EC */
-
        return 1;
        }
 
@@ -2789,11 +2791,11 @@ int ssl_check_clienthello_tlsext_late(SSL *s)
        switch (ret)
                {
                case SSL_TLSEXT_ERR_ALERT_FATAL:
-                       ssl3_send_alert(s, SSL3_AL_FATAL,al);
+                       ssl3_send_alert(s, SSL3_AL_FATAL, al);
                        return -1;
 
                case SSL_TLSEXT_ERR_ALERT_WARNING:
-                       ssl3_send_alert(s, SSL3_AL_WARNING,al);
+                       ssl3_send_alert(s, SSL3_AL_WARNING, al);
                        return 1; 
 
                default:
@@ -3121,7 +3123,7 @@ 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))
                return 2;
        /* Attempt to decrypt session data */
        /* Move p after IV to start of encrypted ticket, update length */
@@ -3427,6 +3429,32 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 
        tls1_set_shared_sigalgs(s);
 
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+       if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+               {
+               /* Use first set signature preference to force message
+                * digest, ignoring any peer preferences.
+                */
+               const unsigned char *sigs = NULL;
+               if (s->server)
+                       sigs = c->conf_sigalgs;
+               else
+                       sigs = c->client_sigalgs;
+               if (sigs)
+                       {
+                       idx = tls12_get_pkey_idx(sigs[1]);
+                       md = tls12_get_hash(sigs[0]);
+                       c->pkeys[idx].digest = md;
+                       c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+                       if (idx == SSL_PKEY_RSA_SIGN)
+                               {
+                               c->pkeys[SSL_PKEY_RSA_ENC].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+                               c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+                               }
+                       }
+               }
+#endif
+
        for (i = 0, sigptr = c->shared_sigalgs;
                        i < c->shared_sigalgslen; i++, sigptr++)
                {
@@ -3722,6 +3750,8 @@ int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
        sig.sigalgcnt = 0;
        if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
                return 0;
+       if (c == NULL)
+               return 1;
        return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
        }
 
@@ -3840,6 +3870,15 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
                /* If no cert or key, forget it */
                if (!x || !pk)
                        goto end;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+               /* Allow any certificate to pass test */
+               if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+                       {
+                       rv = CERT_PKEY_STRICT_FLAGS|CERT_PKEY_EXPLICIT_SIGN|CERT_PKEY_VALID|CERT_PKEY_SIGN;
+                       cpk->valid_flags = rv;
+                       return rv;
+                       }
+#endif
                }
        else
                {