Commit de4dc598 authored by Matt Caswell's avatar Matt Caswell
Browse files

Don't negotiate TLSv1.3 if our EC cert isn't TLSv1.3 capable



TLSv1.3 is more restrictive about the curve used. There must be a matching
sig alg defined for that curve. Therefore if we are using some other curve
in our certificate then we should not negotiate TLSv1.3.

Fixes #7435

Reviewed-by: default avatarViktor Dukhovni <viktor@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7442)
parent 42503613
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2564,6 +2564,7 @@ __owur int tls1_process_sigalgs(SSL *s);
__owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey);
__owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd);
__owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs);
__owur int tls_check_sigalg_curve(const SSL *s, int curve);
__owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey);
__owur int ssl_set_client_disabled(SSL *s);
__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int echde);
+16 −2
Original line number Diff line number Diff line
@@ -1506,7 +1506,8 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
 */
static int is_tls13_capable(const SSL *s)
{
    int i;
    int i, curve;
    EC_KEY *eckey;

#ifndef OPENSSL_NO_PSK
    if (s->psk_server_callback != NULL)
@@ -1527,7 +1528,20 @@ static int is_tls13_capable(const SSL *s)
        default:
            break;
        }
        if (ssl_has_cert(s, i))
        if (!ssl_has_cert(s, i))
            continue;
        if (i != SSL_PKEY_ECC)
            return 1;
        /*
         * Prior to TLSv1.3 sig algs allowed any curve to be used. TLSv1.3 is
         * more restrictive so check that our sig algs are consistent with this
         * EC cert. See section 4.2.3 of RFC8446.
         */
        eckey = EVP_PKEY_get0_EC_KEY(s->cert->pkeys[SSL_PKEY_ECC].privatekey);
        if (eckey == NULL)
            continue;
        curve = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
        if (tls_check_sigalg_curve(s, curve))
            return 1;
    }

+31 −0
Original line number Diff line number Diff line
@@ -949,6 +949,37 @@ size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
    }
}

/*
 * Called by servers only. Checks that we have a sig alg that supports the
 * specified EC curve.
 */
int tls_check_sigalg_curve(const SSL *s, int curve)
{
   const uint16_t *sigs;
   size_t siglen, i;

    if (s->cert->conf_sigalgs) {
        sigs = s->cert->conf_sigalgs;
        siglen = s->cert->conf_sigalgslen;
    } else {
        sigs = tls12_sigalgs;
        siglen = OSSL_NELEM(tls12_sigalgs);
    }

    for (i = 0; i < siglen; i++) {
        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(sigs[i]);

        if (lu == NULL)
            continue;
        if (lu->sig == EVP_PKEY_EC
                && lu->curve != NID_undef
                && curve == lu->curve)
            return 1;
    }

    return 0;
}

/*
 * Check signature algorithm is consistent with sent supported signature
 * algorithms and if so set relevant digest and signature scheme in