Protocol version selection and negotiation rewrite
[openssl.git] / ssl / t1_lib.c
index 02ad438a6eac874c6e3c1f8170fc2eb2992bd65b..980f2f5d0bbba6867c747a956cd4b425187d6367 100644 (file)
@@ -208,7 +208,10 @@ void tls1_free(SSL *s)
 void tls1_clear(SSL *s)
 {
     ssl3_clear(s);
-    s->version = s->method->version;
+    if (s->method->version == TLS_ANY_VERSION)
+        s->version = TLS_MAX_VERSION;
+    else
+        s->version = s->method->version;
 }
 
 #ifndef OPENSSL_NO_EC
@@ -259,8 +262,8 @@ static const unsigned char ecformats_default[] = {
     TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
 };
 
-/* The client's default curves / the server's 'auto' curves. */
-static const unsigned char eccurves_auto[] = {
+/* The default curves */
+static const unsigned char eccurves_default[] = {
     /* Prefer P-256 which has the fastest and most secure implementations. */
     0, 23,                      /* secp256r1 (23) */
     /* Other >= 256-bit prime curves. */
@@ -438,13 +441,8 @@ static int tls1_get_curvelist(SSL *s, int sess,
             pcurveslen = s->tlsext_ellipticcurvelist_length;
         }
         if (!*pcurves) {
-            if (!s->server || s->cert->ecdh_tmp_auto) {
-                *pcurves = eccurves_auto;
-                pcurveslen = sizeof(eccurves_auto);
-            } else {
-                *pcurves = eccurves_all;
-                pcurveslen = sizeof(eccurves_all);
-            }
+            *pcurves = eccurves_default;
+            pcurveslen = sizeof(eccurves_default);
         }
     }
 
@@ -507,8 +505,9 @@ int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
 }
 
 /*-
- * Return |nmatch|th shared curve or NID_undef if there is no match.
- * For nmatch == -1, return number of  matches
+ * For nmatch >= 0, return the NID of the |nmatch|th shared curve or NID_undef
+ * if there is no match.
+ * For nmatch == -1, return number of matches
  * For nmatch == -2, return the NID of the curve to use for
  * an EC tmp key, or NID_undef if there is no match.
  */
@@ -790,16 +789,13 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
     unsigned char comp_id, curve_id[2];
     EVP_PKEY *pkey;
     int rv;
-    pkey = X509_get_pubkey(x);
+    pkey = X509_get0_pubkey(x);
     if (!pkey)
         return 0;
     /* If not EC nothing to do */
-    if (pkey->type != EVP_PKEY_EC) {
-        EVP_PKEY_free(pkey);
+    if (pkey->type != EVP_PKEY_EC)
         return 1;
-    }
     rv = tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec);
-    EVP_PKEY_free(pkey);
     if (!rv)
         return 0;
     /*
@@ -842,11 +838,18 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
 }
 
 # ifndef OPENSSL_NO_EC
-/* Check EC temporary key is compatible with client extensions */
+/*
+ * tls1_check_ec_tmp_key - Check EC temporary key compatiblity
+ * @s: SSL connection
+ * @cid: Cipher ID we're considering using
+ *
+ * Checks that the kECDHE cipher suite we're considering using
+ * is compatible with the client extensions.
+ *
+ * Returns 0 when the cipher can't be used or 1 when it can.
+ */
 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)
@@ -857,6 +860,7 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
      * curves permitted.
      */
     if (tls1_suiteb(s)) {
+        unsigned char curve_id[2];
         /* Curve to check determined by ciphersuite */
         if (cid == TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)
             curve_id[1] = TLSEXT_curve_P_256;
@@ -868,43 +872,12 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
         /* Check this curve is acceptable */
         if (!tls1_check_ec_key(s, curve_id, NULL))
             return 0;
-        /* If auto or setting curve from callback assume OK */
-        if (s->cert->ecdh_tmp_auto || s->cert->ecdh_tmp_cb)
-            return 1;
-        /* Otherwise check curve is acceptable */
-        else {
-            unsigned char curve_tmp[2];
-            if (!ec)
-                return 0;
-            if (!tls1_set_ec_id(curve_tmp, NULL, ec))
-                return 0;
-            if (!curve_tmp[0] || curve_tmp[1] == curve_id[1])
-                return 1;
-            return 0;
-        }
-
-    }
-    if (s->cert->ecdh_tmp_auto) {
-        /* Need a shared curve */
-        if (tls1_shared_curve(s, 0))
-            return 1;
-        else
-            return 0;
-    }
-    if (!ec) {
-        if (s->cert->ecdh_tmp_cb)
-            return 1;
-        else
-            return 0;
+        return 1;
     }
-    if (!tls1_set_ec_id(curve_id, NULL, ec))
-        return 0;
-/* Set this to allow use of invalid curves for testing */
-#  if 0
-    return 1;
-#  else
-    return tls1_check_ec_key(s, curve_id, NULL);
-#  endif
+    /* Need a shared curve */
+    if (tls1_shared_curve(s, 0))
+        return 1;
+    return 0;
 }
 # endif                         /* OPENSSL_NO_EC */
 
@@ -1105,9 +1078,7 @@ void ssl_set_client_disabled(SSL *s)
      * algorithms.
      */
     if (s->s3->tmp.mask_a & SSL_aRSA)
-        s->s3->tmp.mask_k |= SSL_kDHr | SSL_kECDHr;
-    if (s->s3->tmp.mask_a & SSL_aDSS)
-        s->s3->tmp.mask_k |= SSL_kDHd;
+        s->s3->tmp.mask_k |= SSL_kECDHr;
     if (s->s3->tmp.mask_a & SSL_aECDSA)
         s->s3->tmp.mask_k |= SSL_kECDHe;
 # ifndef OPENSSL_NO_PSK
@@ -1726,7 +1697,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
         }
     }
 #endif
-    if (!s->hit && s->session->flags & SSL_SESS_FLAG_EXTMS) {
+    if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
         s2n(TLSEXT_TYPE_extended_master_secret, ret);
         s2n(0, ret);
     }
@@ -2296,10 +2267,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
         else if (type == TLSEXT_TYPE_encrypt_then_mac)
             s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
 #endif
-        else if (type == TLSEXT_TYPE_extended_master_secret) {
-            if (!s->hit)
-                s->session->flags |= SSL_SESS_FLAG_EXTMS;
-        }
+        /*
+         * Note: extended master secret extension handled in
+         * tls_check_serverhello_tlsext_early()
+         */
+
         /*
          * If this ClientHello extension was unhandled and this is a
          * nonresumed connection, check whether the extension is a custom
@@ -2393,6 +2365,8 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
     s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
 #endif
 
+    s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+
     if (!PACKET_get_net_2(pkt, &length))
         goto ri_check;
 
@@ -2581,6 +2555,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
         }
 #endif
         else if (type == TLSEXT_TYPE_extended_master_secret) {
+            s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
             if (!s->hit)
                 s->session->flags |= SSL_SESS_FLAG_EXTMS;
         }
@@ -2600,7 +2575,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
     if (!s->hit && tlsext_servername == 1) {
         if (s->tlsext_hostname) {
             if (s->session->tlsext_hostname == NULL) {
-                s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+                s->session->tlsext_hostname = OPENSSL_strdup(s->tlsext_hostname);
                 if (!s->session->tlsext_hostname) {
                     *al = SSL_AD_UNRECOGNIZED_NAME;
                     return 0;
@@ -2630,6 +2605,19 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
         return 0;
     }
 
+    if (s->hit) {
+        /*
+         * Check extended master secret extension is consistent with
+         * original session.
+         */
+        if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+            !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
+            *al = SSL_AD_HANDSHAKE_FAILURE;
+            SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_INCONSISTENT_EXTMS);
+            return 0;
+            }
+    }
+
     return 1;
 }
 
@@ -2860,29 +2848,12 @@ int ssl_check_serverhello_tlsext(SSL *s)
                                                        initial_ctx->tlsext_servername_arg);
 
     /*
-     * If we've requested certificate status and we wont get one tell the
-     * callback
+     * Ensure we get sensible values passed to tlsext_status_cb in the event
+     * that we don't receive a status message
      */
-    if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
-        && s->ctx && s->ctx->tlsext_status_cb) {
-        int r;
-        /*
-         * Set resp to NULL, resplen to -1 so callback knows there is no
-         * response.
-         */
-        OPENSSL_free(s->tlsext_ocsp_resp);
-        s->tlsext_ocsp_resp = NULL;
-        s->tlsext_ocsp_resplen = -1;
-        r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
-        if (r == 0) {
-            al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-            ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-        }
-        if (r < 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-        }
-    }
+    OPENSSL_free(s->tlsext_ocsp_resp);
+    s->tlsext_ocsp_resp = NULL;
+    s->tlsext_ocsp_resplen = -1;
 
     switch (ret) {
     case SSL_TLSEXT_ERR_ALERT_FATAL:
@@ -2919,8 +2890,11 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt)
 
 /*-
  * Since the server cache lookup is done early on in the processing of the
- * ClientHello, and other operations depend on the result, we need to handle
- * any TLS session ticket extension at the same time.
+ * ClientHello and other operations depend on the result some extensions
+ * need to be handled at the same time.
+ *
+ * Two extensions are currently handled, session ticket and extended master
+ * secret.
  *
  *   session_id: ClientHello session ID.
  *   ext: ClientHello extensions (including length prefix)
@@ -2947,23 +2921,29 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt)
  *   a session ticket or we couldn't use the one it gave us, or if
  *   s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
  *   Otherwise, s->tlsext_ticket_expected is set to 0.
+ *
+ *   For extended master secret flag is set if the extension is present.
+ *
  */
-int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
-                        SSL_SESSION **ret)
+int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext,
+                                       const PACKET *session_id,
+                                       SSL_SESSION **ret)
 {
     unsigned int i;
     PACKET local_ext = *ext;
     int retv = -1;
 
+    int have_ticket = 0;
+    int use_ticket = tls_use_ticket(s);
+
     *ret = NULL;
     s->tlsext_ticket_expected = 0;
+    s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
 
     /*
      * If tickets disabled behave as if no ticket present to permit stateful
      * resumption.
      */
-    if (!tls_use_ticket(s))
-        return 0;
     if ((s->version <= SSL3_VERSION))
         return 0;
 
@@ -2984,10 +2964,17 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
             retv = 0;
             goto end;
         }
-        if (type == TLSEXT_TYPE_session_ticket) {
+        if (type == TLSEXT_TYPE_session_ticket && use_ticket) {
             int r;
             unsigned char *etick;
 
+            /* Duplicate extension */
+            if (have_ticket != 0) {
+                retv = -1;
+                goto end;
+            }
+            have_ticket = 1;
+
             if (size == 0) {
                 /*
                  * The client will accept a ticket but doesn't currently have
@@ -2995,7 +2982,7 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
                  */
                 s->tlsext_ticket_expected = 1;
                 retv = 1;
-                goto end;
+                continue;
             }
             if (s->tls_session_secret_cb) {
                 /*
@@ -3005,7 +2992,7 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
                  * calculate the master secret later.
                  */
                 retv = 2;
-                goto end;
+                continue;
             }
             if (!PACKET_get_bytes(&local_ext, &etick, size)) {
                 /* Shouldn't ever happen */
@@ -3030,15 +3017,18 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
                 retv = -1;
                 break;
             }
-            goto end;
+            continue;
         } else {
+            if (type == TLSEXT_TYPE_extended_master_secret)
+                s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
             if (!PACKET_forward(&local_ext, size)) {
                 retv = -1;
                 goto end;
             }
         }
     }
-    retv = 0;
+    if (have_ticket == 0)
+        retv = 0;
 end:
     return retv;
 }
@@ -3054,6 +3044,7 @@ end:
  *       point to the resulting session.
  *
  * Returns:
+ *   -2: fatal error, malloc failure.
  *   -1: fatal error, either from parsing or decrypting the ticket.
  *    2: the ticket couldn't be decrypted.
  *    3: a ticket was successfully decrypted and *psess was set.
@@ -3068,19 +3059,21 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
     const unsigned char *p;
     int slen, mlen, renew_ticket = 0;
     unsigned char tick_hmac[EVP_MAX_MD_SIZE];
-    HMAC_CTX hctx;
+    HMAC_CTX *hctx = NULL;
     EVP_CIPHER_CTX ctx;
     SSL_CTX *tctx = s->initial_ctx;
     /* Need at least keyname + iv + some encrypted data */
     if (eticklen < 48)
         return 2;
     /* Initialize session ticket encryption and HMAC contexts */
-    HMAC_CTX_init(&hctx);
+    hctx = HMAC_CTX_new();
+    if (hctx == NULL)
+        return -2;
     EVP_CIPHER_CTX_init(&ctx);
     if (tctx->tlsext_ticket_key_cb) {
         unsigned char *nctick = (unsigned char *)etick;
         int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
-                                            &ctx, &hctx, 0);
+                                            &ctx, hctx, 0);
         if (rv < 0)
             return -1;
         if (rv == 0)
@@ -3091,7 +3084,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
         /* Check key name matches */
         if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
             return 2;
-        if (HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
+        if (HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, 16,
                          EVP_sha256(), NULL) <= 0
                 || EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
                                       tctx->tlsext_tick_aes_key,
@@ -3103,17 +3096,17 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
      * Attempt to process session ticket, first conduct sanity and integrity
      * checks on ticket.
      */
-    mlen = HMAC_size(&hctx);
+    mlen = HMAC_size(hctx);
     if (mlen < 0) {
         goto err;
     }
     eticklen -= mlen;
     /* Check HMAC of encrypted ticket */
-    if (HMAC_Update(&hctx, etick, eticklen) <= 0
-            || HMAC_Final(&hctx, tick_hmac, NULL) <= 0) {
+    if (HMAC_Update(hctx, etick, eticklen) <= 0
+            || HMAC_Final(hctx, tick_hmac, NULL) <= 0) {
         goto err;
     }
-    HMAC_CTX_cleanup(&hctx);
+    HMAC_CTX_free(hctx);
     if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
         EVP_CIPHER_CTX_cleanup(&ctx);
         return 2;
@@ -3162,7 +3155,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
     return 2;
 err:
     EVP_CIPHER_CTX_cleanup(&ctx);
-    HMAC_CTX_cleanup(&hctx);
+    HMAC_CTX_free(hctx);
     return -1;
 }
 
@@ -3314,7 +3307,7 @@ static int tls12_get_pkey_idx(unsigned char sig_alg)
 static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
                                int *psignhash_nid, const unsigned char *data)
 {
-    int sign_nid = 0, hash_nid = 0;
+    int sign_nid = NID_undef, hash_nid = NID_undef;
     if (!phash_nid && !psign_nid && !psignhash_nid)
         return;
     if (phash_nid || psignhash_nid) {
@@ -3328,9 +3321,9 @@ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid,
             *psign_nid = sign_nid;
     }
     if (psignhash_nid) {
-        if (sign_nid && hash_nid)
-            OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid);
-        else
+        if (sign_nid == NID_undef || hash_nid == NID_undef
+                || OBJ_find_sigid_by_algs(psignhash_nid, hash_nid,
+                                          sign_nid) <= 0)
             *psignhash_nid = NID_undef;
     }
 }
@@ -4019,13 +4012,11 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
             switch (idx) {
             case SSL_PKEY_RSA_ENC:
             case SSL_PKEY_RSA_SIGN:
-            case SSL_PKEY_DH_RSA:
                 rsign = TLSEXT_signature_rsa;
                 default_nid = NID_sha1WithRSAEncryption;
                 break;
 
             case SSL_PKEY_DSA_SIGN:
-            case SSL_PKEY_DH_DSA:
                 rsign = TLSEXT_signature_dsa;
                 default_nid = NID_dsaWithSHA1;
                 break;
@@ -4128,15 +4119,6 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
         case EVP_PKEY_EC:
             check_type = TLS_CT_ECDSA_SIGN;
             break;
-        case EVP_PKEY_DH:
-        case EVP_PKEY_DHX:
-            {
-                int cert_type = X509_certificate_type(x, pk);
-                if (cert_type & EVP_PKS_RSA)
-                    check_type = TLS_CT_RSA_FIXED_DH;
-                if (cert_type & EVP_PKS_DSA)
-                    check_type = TLS_CT_DSS_FIXED_DH;
-            }
         }
         if (check_type) {
             const unsigned char *ctypes;
@@ -4217,8 +4199,6 @@ void tls1_set_cert_validity(SSL *s)
     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_ENC);
     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_RSA_SIGN);
     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DSA_SIGN);
-    tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_RSA);
-    tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_DH_DSA);
     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_ECC);
     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST01);
     tls1_check_chain(s, NULL, NULL, NULL, SSL_PKEY_GOST12_256);
@@ -4273,13 +4253,17 @@ DH *ssl_get_auto_dh(SSL *s)
 
 static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
 {
-    int secbits;
-    EVP_PKEY *pkey = X509_get_pubkey(x);
+    int secbits = -1;
+    EVP_PKEY *pkey = X509_get0_pubkey(x);
     if (pkey) {
+        /*
+         * If no parameters this will return -1 and fail using the default
+         * security callback for any non-zero security level. This will
+         * reject keys which omit parameters but this only affects DSA and
+         * omission of parameters is never (?) done in practice.
+         */
         secbits = EVP_PKEY_security_bits(pkey);
-        EVP_PKEY_free(pkey);
-    } else
-        secbits = -1;
+    }
     if (s)
         return ssl_security(s, op, secbits, 0, x);
     else