Commit message: Fix NULL dereference in SSL_check_chain() for TLS 1.3

In the tls1_check_sig_alg() helper function, we loop through the list of
"signature_algorithms_cert" values received from the client and attempt
to look up each one in turn in our internal table that maps wire
codepoint to string-form name, digest and/or signature NID, etc., in
order to compare the signature scheme from the peer's list against what
is used to sign the certificates in the certificate chain we're
checking.  Unfortunately, when the peer sends a value that we don't
support, the lookup returns NULL, but we unconditionally dereference the
lookup result for the comparison, leading to an application crash
triggerable by an unauthenticated client.

Since we will not be able to say anything about algorithms we don't
recognize, treat NULL return from lookup as "does not match".

We currently only apply the "signature_algorithm_cert" checks on TLS 1.3
connections, so previous TLS versions are unaffected.  SSL_check_chain()
is not called directly from libssl, but may be used by the application
inside a callback (e.g., client_hello or cert callback) to verify that a
candidate certificate chain will be acceptable to the client.

CVE-2020-1967

Reviewed-by: Matt Caswell <matt@openssl.org>
CVE: CVE-2020-1967
CWE: CWE-476
Vulnerability description: Server or client applications that call the SSL_check_chain() function during or after a TLS 1.3 handshake may crash due to a NULL pointer dereference as a result of incorrect handling of the "signature_algorithms_cert" TLS extension. The crash occurs if an invalid or unrecognised signature algorithm is received from the peer. This could be exploited by a malicious peer in a Denial of Service attack. OpenSSL version 1.1.1d, 1.1.1e, and 1.1.1f are affected by this issue. This issue did not affect OpenSSL versions prior to 1.1.1d. Fixed in OpenSSL 1.1.1g (Affected 1.1.1d-1.1.1f).

Project: openssl

static uint16_t tls1_get_group_id(EVP_PKEY *pkey)
{
    int curve_nid = evp_pkey_get_EC_KEY_curve_nid(pkey);

    if (curve_nid == NID_undef)
        return 0;
    return tls1_nid2group_id(curve_nid);
}

Project: openssl

int tls_choose_sigalg(SSL *s, int fatalerrs)
{
    const SIGALG_LOOKUP *lu = NULL;
    int sig_idx = -1;

    s->s3.tmp.cert = NULL;
    s->s3.tmp.sigalg = NULL;

    if (SSL_IS_TLS13(s)) {
        lu = find_sig_alg(s, NULL, NULL);
        if (lu == NULL) {
            if (!fatalerrs)
                return 1;
            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CHOOSE_SIGALG,
                     SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
            return 0;
        }
    } else {
        /* If ciphersuite doesn't require a cert nothing to do */
        if (!(s->s3.tmp.new_cipher->algorithm_auth & SSL_aCERT))
            return 1;
        if (!s->server && !ssl_has_cert(s, s->cert->key - s->cert->pkeys))
                return 1;

        if (SSL_USE_SIGALGS(s)) {
            size_t i;
            if (s->s3.tmp.peer_sigalgs != NULL) {
#ifndef OPENSSL_NO_EC
                int curve = -1;

                /* For Suite B need to match signature algorithm to curve */
                if (tls1_suiteb(s))
                    curve =
                        evp_pkey_get_EC_KEY_curve_nid(s->cert->pkeys[SSL_PKEY_ECC]
                                                      .privatekey);
#endif

                /*
                 * Find highest preference signature algorithm matching
                 * cert type
                 */
                for (i = 0; i < s->shared_sigalgslen; i++) {
                    lu = s->shared_sigalgs[i];

                    if (s->server) {
                        if ((sig_idx = tls12_get_cert_sigalg_idx(s, lu)) == -1)
                            continue;
                    } else {
                        int cc_idx = s->cert->key - s->cert->pkeys;

                        sig_idx = lu->sig_idx;
                        if (cc_idx != sig_idx)
                            continue;
                    }
                    /* Check that we have a cert, and sig_algs_cert */
                    if (!has_usable_cert(s, lu, sig_idx))
                        continue;
                    if (lu->sig == EVP_PKEY_RSA_PSS) {
                        /* validate that key is large enough for the signature algorithm */
                        EVP_PKEY *pkey = s->cert->pkeys[sig_idx].privatekey;

                        if (!rsa_pss_check_min_key_size(s->ctx, pkey, lu))
                            continue;
                    }
#ifndef OPENSSL_NO_EC
                    if (curve == -1 || lu->curve == curve)
#endif
                        break;
                }
#ifndef OPENSSL_NO_GOST
                /*
                 * Some Windows-based implementations do not send GOST algorithms indication
                 * in supported_algorithms extension, so when we have GOST-based ciphersuite,
                 * we have to assume GOST support.
                 */
                if (i == s->shared_sigalgslen && s->s3.tmp.new_cipher->algorithm_auth & (SSL_aGOST01 | SSL_aGOST12)) {
                  if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
                    if (!fatalerrs)
                      return 1;
                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
                             SSL_F_TLS_CHOOSE_SIGALG,
                             SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
                    return 0;
                  } else {
                    i = 0;
                    sig_idx = lu->sig_idx;
                  }
                }
#endif
                if (i == s->shared_sigalgslen) {
                    if (!fatalerrs)
                        return 1;
                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
                             SSL_F_TLS_CHOOSE_SIGALG,
                             SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
                    return 0;
                }
            } else {
                /*
                 * If we have no sigalg use defaults
                 */
                const uint16_t *sent_sigs;
                size_t sent_sigslen;

                if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
                    if (!fatalerrs)
                        return 1;
                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
                             SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
                    return 0;
                }

                /* Check signature matches a type we sent */
                sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
                for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
                    if (lu->sigalg == *sent_sigs
                            && has_usable_cert(s, lu, lu->sig_idx))
                        break;
                }
                if (i == sent_sigslen) {
                    if (!fatalerrs)
                        return 1;
                    SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
                             SSL_F_TLS_CHOOSE_SIGALG,
                             SSL_R_WRONG_SIGNATURE_TYPE);
                    return 0;
                }
            }
        } else {
            if ((lu = tls1_get_legacy_sigalg(s, -1)) == NULL) {
                if (!fatalerrs)
                    return 1;
                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CHOOSE_SIGALG,
                         SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
                return 0;
            }
        }
    }
    if (sig_idx == -1)
        sig_idx = lu->sig_idx;
    s->s3.tmp.cert = &s->cert->pkeys[sig_idx];
    s->cert->key = s->s3.tmp.cert;
    s->s3.tmp.sigalg = lu;
    return 1;
}

Project: openssl

static int tls1_check_cert_param(SSL *s, X509 *x, int check_ee_md)
{
    uint16_t group_id;
    EVP_PKEY *pkey;
    pkey = X509_get0_pubkey(x);
    if (pkey == NULL)
        return 0;
    /* If not EC nothing to do */
    if (!EVP_PKEY_is_a(pkey, "EC"))
        return 1;
    /* Check compression */
    if (!tls1_check_pkey_comp(s, pkey))
        return 0;
    group_id = tls1_get_group_id(pkey);
    /*
     * For a server we allow the certificate to not be in our list of supported
     * groups.
     */
    if (!tls1_check_group_id(s, group_id, !s->server))
        return 0;
    /*
     * Special case for suite B. We *MUST* sign using SHA256+P-256 or
     * SHA384+P-384.
     */
    if (check_ee_md && tls1_suiteb(s)) {
        int check_md;
        size_t i;

        /* Check to see we have necessary signing algorithm */
        if (group_id == TLSEXT_curve_P_256)
            check_md = NID_ecdsa_with_SHA256;
        else if (group_id == TLSEXT_curve_P_384)
            check_md = NID_ecdsa_with_SHA384;
        else
            return 0;           /* Should never happen */
        for (i = 0; i < s->shared_sigalgslen; i++) {
            if (check_md == s->shared_sigalgs[i]->sigandhash)
                return 1;;
        }
        return 0;
    }
    return 1;
}

Project: openssl

int tls1_lookup_md(SSL_CTX *ctx, const SIGALG_LOOKUP *lu, const EVP_MD **pmd)
{
    const EVP_MD *md;
    if (lu == NULL)
        return 0;
    /* lu->hash == NID_undef means no associated digest */
    if (lu->hash == NID_undef) {
        md = NULL;
    } else {
        md = ssl_md(ctx, lu->hash_idx);
        if (md == NULL)
            return 0;
    }
    if (pmd)
        *pmd = md;
    return 1;
}

Project: openssl

static int rsa_pss_check_min_key_size(SSL_CTX *ctx, const EVP_PKEY *pkey,
                                      const SIGALG_LOOKUP *lu)
{
    const EVP_MD *md;

    if (pkey == NULL)
        return 0;
    if (!tls1_lookup_md(ctx, lu, &md) || md == NULL)
        return 0;
    if (EVP_PKEY_size(pkey) < RSA_PSS_MINIMUM_KEY_SIZE(md))
        return 0;
    return 1;
}

Project: openssl

static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey)
{
    const SIGALG_LOOKUP *lu = NULL;
    size_t i;
#ifndef OPENSSL_NO_EC
    int curve = -1;
#endif
    EVP_PKEY *tmppkey;

    /* Look for a shared sigalgs matching possible certificates */
    for (i = 0; i < s->shared_sigalgslen; i++) {
        lu = s->shared_sigalgs[i];

        /* Skip SHA1, SHA224, DSA and RSA if not PSS */
        if (lu->hash == NID_sha1
            || lu->hash == NID_sha224
            || lu->sig == EVP_PKEY_DSA
            || lu->sig == EVP_PKEY_RSA)
            continue;
        /* Check that we have a cert, and signature_algorithms_cert */
        if (!tls1_lookup_md(s->ctx, lu, NULL))
            continue;
        if ((pkey == NULL && !has_usable_cert(s, lu, -1))
                || (pkey != NULL && !is_cert_usable(s, lu, x, pkey)))
            continue;

        tmppkey = (pkey != NULL) ? pkey
                                 : s->cert->pkeys[lu->sig_idx].privatekey;

        if (lu->sig == EVP_PKEY_EC) {
#ifndef OPENSSL_NO_EC
            if (curve == -1)
                curve = evp_pkey_get_EC_KEY_curve_nid(tmppkey);
            if (lu->curve != NID_undef && curve != lu->curve)
                continue;
#else
            continue;
#endif
        } else if (lu->sig == EVP_PKEY_RSA_PSS) {
            /* validate that key is large enough for the signature algorithm */
            if (!rsa_pss_check_min_key_size(s->ctx, tmppkey, lu))
                continue;
        }
        break;
    }

    if (i == s->shared_sigalgslen)
        return NULL;

    return lu;
}

Project: openssl

static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu)
{
    unsigned char sigalgstr[2];
    int secbits;

    /* See if sigalgs is recognised and if hash is enabled */
    if (!tls1_lookup_md(s->ctx, lu, NULL))
        return 0;
    /* DSA is not allowed in TLS 1.3 */
    if (SSL_IS_TLS13(s) && lu->sig == EVP_PKEY_DSA)
        return 0;
    /* TODO(OpenSSL1.2) fully axe DSA/etc. in ClientHello per TLS 1.3 spec */
    if (!s->server && !SSL_IS_DTLS(s) && s->s3.tmp.min_ver >= TLS1_3_VERSION
        && (lu->sig == EVP_PKEY_DSA || lu->hash_idx == SSL_MD_SHA1_IDX
            || lu->hash_idx == SSL_MD_MD5_IDX
            || lu->hash_idx == SSL_MD_SHA224_IDX))
        return 0;

    /* See if public key algorithm allowed */
    if (ssl_cert_is_disabled(lu->sig_idx))
        return 0;

    if (lu->sig == NID_id_GostR3410_2012_256
            || lu->sig == NID_id_GostR3410_2012_512
            || lu->sig == NID_id_GostR3410_2001) {
        /* We never allow GOST sig algs on the server with TLSv1.3 */
        if (s->server && SSL_IS_TLS13(s))
            return 0;
        if (!s->server
                && s->method->version == TLS_ANY_VERSION
                && s->s3.tmp.max_ver >= TLS1_3_VERSION) {
            int i, num;
            STACK_OF(SSL_CIPHER) *sk;

            /*
             * We're a client that could negotiate TLSv1.3. We only allow GOST
             * sig algs if we could negotiate TLSv1.2 or below and we have GOST
             * ciphersuites enabled.
             */

            if (s->s3.tmp.min_ver >= TLS1_3_VERSION)
                return 0;

            sk = SSL_get_ciphers(s);
            num = sk != NULL ? sk_SSL_CIPHER_num(sk) : 0;
            for (i = 0; i < num; i++) {
                const SSL_CIPHER *c;

                c = sk_SSL_CIPHER_value(sk, i);
                /* Skip disabled ciphers */
                if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
                    continue;

                if ((c->algorithm_mkey & SSL_kGOST) != 0)
                    break;
            }
            if (i == num)
                return 0;
        }
    }

    /* Finally see if security callback allows it */
    secbits = sigalg_security_bits(s->ctx, lu);
    sigalgstr[0] = (lu->sigalg >> 8) & 0xff;
    sigalgstr[1] = lu->sigalg & 0xff;
    return ssl_security(s, op, secbits, lu->hash, (void *)sigalgstr);
}

Project: openssl

int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
{
    const uint16_t *sent_sigs;
    const EVP_MD *md = NULL;
    char sigalgstr[2];
    size_t sent_sigslen, i, cidx;
    int pkeyid = -1;
    const SIGALG_LOOKUP *lu;
    int secbits = 0;

    /*
     * TODO(3.0) Remove this when we adapted this function for provider
     * side keys.  We know that EVP_PKEY_get0() downgrades an EVP_PKEY
     * to contain a legacy key.
     *
     * THIS IS TEMPORARY
     */
    EVP_PKEY_get0(pkey);
    if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE)
        return 0;

    pkeyid = EVP_PKEY_id(pkey);
    /* Should never happen */
    if (pkeyid == -1)
        return -1;
    if (SSL_IS_TLS13(s)) {
        /* Disallow DSA for TLS 1.3 */
        if (pkeyid == EVP_PKEY_DSA) {
            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
                     SSL_R_WRONG_SIGNATURE_TYPE);
            return 0;
        }
        /* Only allow PSS for TLS 1.3 */
        if (pkeyid == EVP_PKEY_RSA)
            pkeyid = EVP_PKEY_RSA_PSS;
    }
    lu = tls1_lookup_sigalg(sig);
    /*
     * Check sigalgs is known. Disallow SHA1/SHA224 with TLS 1.3. Check key type
     * is consistent with signature: RSA keys can be used for RSA-PSS
     */
    if (lu == NULL
        || (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
        || (pkeyid != lu->sig
        && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
                 SSL_R_WRONG_SIGNATURE_TYPE);
        return 0;
    }
    /* Check the sigalg is consistent with the key OID */
    if (!ssl_cert_lookup_by_nid(EVP_PKEY_id(pkey), &cidx)
            || lu->sig_idx != (int)cidx) {
        SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
                 SSL_R_WRONG_SIGNATURE_TYPE);
        return 0;
    }

#ifndef OPENSSL_NO_EC
    if (pkeyid == EVP_PKEY_EC) {

        /* Check point compression is permitted */
        if (!tls1_check_pkey_comp(s, pkey)) {
            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
                     SSL_F_TLS12_CHECK_PEER_SIGALG,
                     SSL_R_ILLEGAL_POINT_COMPRESSION);
            return 0;
        }

        /* For TLS 1.3 or Suite B check curve matches signature algorithm */
        if (SSL_IS_TLS13(s) || tls1_suiteb(s)) {
            int curve = evp_pkey_get_EC_KEY_curve_nid(pkey);

            if (lu->curve != NID_undef && curve != lu->curve) {
                SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
                         SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
                return 0;
            }
        }
        if (!SSL_IS_TLS13(s)) {
            /* Check curve matches extensions */
            if (!tls1_check_group_id(s, tls1_get_group_id(pkey), 1)) {
                SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
                         SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_CURVE);
                return 0;
            }
            if (tls1_suiteb(s)) {
                /* Check sigalg matches a permissible Suite B value */
                if (sig != TLSEXT_SIGALG_ecdsa_secp256r1_sha256
                    && sig != TLSEXT_SIGALG_ecdsa_secp384r1_sha384) {
                    SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
                             SSL_F_TLS12_CHECK_PEER_SIGALG,
                             SSL_R_WRONG_SIGNATURE_TYPE);
                    return 0;
                }
            }
        }
    } else if (tls1_suiteb(s)) {
        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
                 SSL_R_WRONG_SIGNATURE_TYPE);
        return 0;
    }
#endif

    /* Check signature matches a type we sent */
    sent_sigslen = tls12_get_psigalgs(s, 1, &sent_sigs);
    for (i = 0; i < sent_sigslen; i++, sent_sigs++) {
        if (sig == *sent_sigs)
            break;
    }
    /* Allow fallback to SHA1 if not strict mode */
    if (i == sent_sigslen && (lu->hash != NID_sha1
        || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
                 SSL_R_WRONG_SIGNATURE_TYPE);
        return 0;
    }
    if (!tls1_lookup_md(s->ctx, lu, &md)) {
        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
                 SSL_R_UNKNOWN_DIGEST);
        return 0;
    }
    /*
     * Make sure security callback allows algorithm. For historical
     * reasons we have to pass the sigalg as a two byte char array.
     */
    sigalgstr[0] = (sig >> 8) & 0xff;
    sigalgstr[1] = sig & 0xff;
    secbits = sigalg_security_bits(s->ctx, lu);
    if (secbits == 0 ||
        !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits,
                      md != NULL ? EVP_MD_type(md) : NID_undef,
                      (void *)sigalgstr)) {
        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS12_CHECK_PEER_SIGALG,
                 SSL_R_WRONG_SIGNATURE_TYPE);
        return 0;
    }
    /* Store the sigalg the peer uses */
    s->s3.tmp.peer_sigalg = lu;
    return 1;
}

Project: openssl

static int tls1_check_pkey_comp(SSL *s, EVP_PKEY *pkey)
{
    const EC_KEY *ec;
    const EC_GROUP *grp;
    unsigned char comp_id;
    size_t i;

    /* If not an EC key nothing to check */
    if (!EVP_PKEY_is_a(pkey, "EC"))
        return 1;
    ec = EVP_PKEY_get0_EC_KEY(pkey);
    grp = EC_KEY_get0_group(ec);

    /* Get required compression id */
    if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_UNCOMPRESSED) {
            comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
    } else if (SSL_IS_TLS13(s)) {
            /*
             * ec_point_formats extension is not used in TLSv1.3 so we ignore
             * this check.
             */
            return 1;
    } else {
        int field_type = EC_METHOD_get_field_type(EC_GROUP_method_of(grp));

        if (field_type == NID_X9_62_prime_field)
            comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
        else if (field_type == NID_X9_62_characteristic_two_field)
            comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
        else
            return 0;
    }
    /*
     * If point formats extension present check it, otherwise everything is
     * supported (see RFC4492).
     */
    if (s->ext.peer_ecpointformats == NULL)
        return 1;

    for (i = 0; i < s->ext.peer_ecpointformats_len; i++) {
        if (s->ext.peer_ecpointformats[i] == comp_id)
            return 1;
    }
    return 0;
}

Project: openssl

EVP_MAC_CTX *ssl_hmac_get0_EVP_MAC_CTX(SSL_HMAC *ctx)
{
    return ctx->ctx;
}

Project: openssl

static int ssl_check_ca_name(STACK_OF(X509_NAME) *names, X509 *x)
{
    const X509_NAME *nm;
    int i;
    nm = X509_get_issuer_name(x);
    for (i = 0; i < sk_X509_NAME_num(names); i++) {
        if (!X509_NAME_cmp(nm, sk_X509_NAME_value(names, i)))
            return 1;
    }
    return 0;
}

Project: openssl

size_t ssl_hmac_size(const SSL_HMAC *ctx)
{
    if (ctx->ctx != NULL)
        return EVP_MAC_size(ctx->ctx);
#ifndef OPENSSL_NO_DEPRECATED_3_0
    if (ctx->old_ctx != NULL)
        return HMAC_size(ctx->old_ctx);
#endif
    return 0;
}

Project: openssl

int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
                     int idx)
{
    int i;
    int rv = 0;
    int check_flags = 0, strict_mode;
    CERT_PKEY *cpk = NULL;
    CERT *c = s->cert;
    uint32_t *pvalid;
    unsigned int suiteb_flags = tls1_suiteb(s);
    /* idx == -1 means checking server chains */
    if (idx != -1) {
        /* idx == -2 means checking client certificate chains */
        if (idx == -2) {
            cpk = c->key;
            idx = (int)(cpk - c->pkeys);
        } else
            cpk = c->pkeys + idx;
        pvalid = s->s3.tmp.valid_flags + idx;
        x = cpk->x509;
        pk = cpk->privatekey;
        chain = cpk->chain;
        strict_mode = c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT;
        /* If no cert or key, forget it */
        if (!x || !pk)
            goto end;
    } else {
        size_t certidx;

        if (!x || !pk)
            return 0;

        if (ssl_cert_lookup_by_pkey(pk, &certidx) == NULL)
            return 0;
        idx = certidx;
        pvalid = s->s3.tmp.valid_flags + idx;

        if (c->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)
            check_flags = CERT_PKEY_STRICT_FLAGS;
        else
            check_flags = CERT_PKEY_VALID_FLAGS;
        strict_mode = 1;
    }

    if (suiteb_flags) {
        int ok;
        if (check_flags)
            check_flags |= CERT_PKEY_SUITEB;
        ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
        if (ok == X509_V_OK)
            rv |= CERT_PKEY_SUITEB;
        else if (!check_flags)
            goto end;
    }

    /*
     * Check all signature algorithms are consistent with signature
     * algorithms extension if TLS 1.2 or later and strict mode.
     */
    if (TLS1_get_version(s) >= TLS1_2_VERSION && strict_mode) {
        int default_nid;
        int rsign = 0;
        if (s->s3.tmp.peer_cert_sigalgs != NULL
                || s->s3.tmp.peer_sigalgs != NULL) {
            default_nid = 0;
        /* If no sigalgs extension use defaults from RFC5246 */
        } else {
            switch (idx) {
            case SSL_PKEY_RSA:
                rsign = EVP_PKEY_RSA;
                default_nid = NID_sha1WithRSAEncryption;
                break;

            case SSL_PKEY_DSA_SIGN:
                rsign = EVP_PKEY_DSA;
                default_nid = NID_dsaWithSHA1;
                break;

            case SSL_PKEY_ECC:
                rsign = EVP_PKEY_EC;
                default_nid = NID_ecdsa_with_SHA1;
                break;

            case SSL_PKEY_GOST01:
                rsign = NID_id_GostR3410_2001;
                default_nid = NID_id_GostR3411_94_with_GostR3410_2001;
                break;

            case SSL_PKEY_GOST12_256:
                rsign = NID_id_GostR3410_2012_256;
                default_nid = NID_id_tc26_signwithdigest_gost3410_2012_256;
                break;

            case SSL_PKEY_GOST12_512:
                rsign = NID_id_GostR3410_2012_512;
                default_nid = NID_id_tc26_signwithdigest_gost3410_2012_512;
                break;

            default:
                default_nid = -1;
                break;
            }
        }
        /*
         * If peer sent no signature algorithms extension and we have set
         * preferred signature algorithms check we support sha1.
         */
        if (default_nid > 0 && c->conf_sigalgs) {
            size_t j;
            const uint16_t *p = c->conf_sigalgs;
            for (j = 0; j < c->conf_sigalgslen; j++, p++) {
                const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(*p);

                if (lu != NULL && lu->hash == NID_sha1 && lu->sig == rsign)
                    break;
            }
            if (j == c->conf_sigalgslen) {
                if (check_flags)
                    goto skip_sigs;
                else
                    goto end;
            }
        }
        /* Check signature algorithm of each cert in chain */
        if (SSL_IS_TLS13(s)) {
            /*
             * We only get here if the application has called SSL_check_chain(),
             * so check_flags is always set.
             */
            if (find_sig_alg(s, x, pk) != NULL)
                rv |= CERT_PKEY_EE_SIGNATURE;
        } else if (!tls1_check_sig_alg(s, x, default_nid)) {
            if (!check_flags)
                goto end;
        } else
            rv |= CERT_PKEY_EE_SIGNATURE;
        rv |= CERT_PKEY_CA_SIGNATURE;
        for (i = 0; i < sk_X509_num(chain); i++) {
            if (!tls1_check_sig_alg(s, sk_X509_value(chain, i), default_nid)) {
                if (check_flags) {
                    rv &= ~CERT_PKEY_CA_SIGNATURE;
                    break;
                } else
                    goto end;
            }
        }
    }
    /* Else not TLS 1.2, so mark EE and CA signing algorithms OK */
    else if (check_flags)
        rv |= CERT_PKEY_EE_SIGNATURE | CERT_PKEY_CA_SIGNATURE;
 skip_sigs:
    /* Check cert parameters are consistent */
    if (tls1_check_cert_param(s, x, 1))
        rv |= CERT_PKEY_EE_PARAM;
    else if (!check_flags)
        goto end;
    if (!s->server)
        rv |= CERT_PKEY_CA_PARAM;
    /* In strict mode check rest of chain too */
    else if (strict_mode) {
        rv |= CERT_PKEY_CA_PARAM;
        for (i = 0; i < sk_X509_num(chain); i++) {
            X509 *ca = sk_X509_value(chain, i);
            if (!tls1_check_cert_param(s, ca, 0)) {
                if (check_flags) {
                    rv &= ~CERT_PKEY_CA_PARAM;
                    break;
                } else
                    goto end;
            }
        }
    }
    if (!s->server && strict_mode) {
        STACK_OF(X509_NAME) *ca_dn;
        int check_type = 0;

        if (EVP_PKEY_is_a(pk, "RSA"))
            check_type = TLS_CT_RSA_SIGN;
        else if (EVP_PKEY_is_a(pk, "DSA"))
            check_type = TLS_CT_DSS_SIGN;
        else if (EVP_PKEY_is_a(pk, "EC"))
            check_type = TLS_CT_ECDSA_SIGN;

        if (check_type) {
            const uint8_t *ctypes = s->s3.tmp.ctype;
            size_t j;

            for (j = 0; j < s->s3.tmp.ctype_len; j++, ctypes++) {
                if (*ctypes == check_type) {
                    rv |= CERT_PKEY_CERT_TYPE;
                    break;
                }
            }
            if (!(rv & CERT_PKEY_CERT_TYPE) && !check_flags)
                goto end;
        } else {
            rv |= CERT_PKEY_CERT_TYPE;
        }

        ca_dn = s->s3.tmp.peer_ca_names;

        if (!sk_X509_NAME_num(ca_dn))
            rv |= CERT_PKEY_ISSUER_NAME;

        if (!(rv & CERT_PKEY_ISSUER_NAME)) {
            if (ssl_check_ca_name(ca_dn, x))
                rv |= CERT_PKEY_ISSUER_NAME;
        }
        if (!(rv & CERT_PKEY_ISSUER_NAME)) {
            for (i = 0; i < sk_X509_num(chain); i++) {
                X509 *xtmp = sk_X509_value(chain, i);
                if (ssl_check_ca_name(ca_dn, xtmp)) {
                    rv |= CERT_PKEY_ISSUER_NAME;
                    break;
                }
            }
        }
        if (!check_flags && !(rv & CERT_PKEY_ISSUER_NAME))
            goto end;
    } else
        rv |= CERT_PKEY_ISSUER_NAME | CERT_PKEY_CERT_TYPE;

    if (!check_flags || (rv & check_flags) == check_flags)
        rv |= CERT_PKEY_VALID;

 end:

    if (TLS1_get_version(s) >= TLS1_2_VERSION)
        rv |= *pvalid & (CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN);
    else
        rv |= CERT_PKEY_SIGN | CERT_PKEY_EXPLICIT_SIGN;

    /*
     * When checking a CERT_PKEY structure all flags are irrelevant if the
     * chain is invalid.
     */
    if (!check_flags) {
        if (rv & CERT_PKEY_VALID) {
            *pvalid = rv;
        } else {
            /* Preserve sign and explicit sign flag, clear rest */
            *pvalid &= CERT_PKEY_EXPLICIT_SIGN | CERT_PKEY_SIGN;
            return 0;
        }
    }
    return rv;
}

Project: openssl

static int sigalg_security_bits(SSL_CTX *ctx, const SIGALG_LOOKUP *lu)
{
    const EVP_MD *md = NULL;
    int secbits = 0;

    if (!tls1_lookup_md(ctx, lu, &md))
        return 0;
    if (md != NULL)
    {
        /* Security bits: half digest bits */
        secbits = EVP_MD_size(md) * 4;
    } else {
        /* Values from https://tools.ietf.org/html/rfc8032#section-8.5 */
        if (lu->sigalg == TLSEXT_SIGALG_ed25519)
            secbits = 128;
        else if (lu->sigalg == TLSEXT_SIGALG_ed448)
            secbits = 224;
    }
    return secbits;
}

Project: openssl

SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
                                     size_t eticklen, const unsigned char *sess_id,
                                     size_t sesslen, SSL_SESSION **psess)
{
    SSL_SESSION *sess = NULL;
    unsigned char *sdec;
    const unsigned char *p;
    int slen, renew_ticket = 0, declen;
    SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER;
    size_t mlen;
    unsigned char tick_hmac[EVP_MAX_MD_SIZE];
    SSL_HMAC *hctx = NULL;
    EVP_CIPHER_CTX *ctx = NULL;
    SSL_CTX *tctx = s->session_ctx;

    if (eticklen == 0) {
        /*
         * The client will accept a ticket but doesn't currently have
         * one (TLSv1.2 and below), or treated as a fatal error in TLSv1.3
         */
        ret = SSL_TICKET_EMPTY;
        goto end;
    }
    if (!SSL_IS_TLS13(s) && s->ext.session_secret_cb) {
        /*
         * Indicate that the ticket couldn't be decrypted rather than
         * generating the session from ticket now, trigger
         * abbreviated handshake based on external mechanism to
         * calculate the master secret later.
         */
        ret = SSL_TICKET_NO_DECRYPT;
        goto end;
    }

    /* Need at least keyname + iv */
    if (eticklen < TLSEXT_KEYNAME_LENGTH + EVP_MAX_IV_LENGTH) {
        ret = SSL_TICKET_NO_DECRYPT;
        goto end;
    }

    /* Initialize session ticket encryption and HMAC contexts */
    hctx = ssl_hmac_new(tctx);
    if (hctx == NULL) {
        ret = SSL_TICKET_FATAL_ERR_MALLOC;
        goto end;
    }
    ctx = EVP_CIPHER_CTX_new();
    if (ctx == NULL) {
        ret = SSL_TICKET_FATAL_ERR_MALLOC;
        goto end;
    }
#ifndef OPENSSL_NO_DEPRECATED_3_0
    if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL)
#else
    if (tctx->ext.ticket_key_evp_cb != NULL)
#endif
    {
        unsigned char *nctick = (unsigned char *)etick;
        int rv = 0;

        if (tctx->ext.ticket_key_evp_cb != NULL)
            rv = tctx->ext.ticket_key_evp_cb(s, nctick,
                                             nctick + TLSEXT_KEYNAME_LENGTH,
                                             ctx,
                                             ssl_hmac_get0_EVP_MAC_CTX(hctx),
                                             0);
#ifndef OPENSSL_NO_DEPRECATED_3_0
        else if (tctx->ext.ticket_key_cb != NULL)
            /* if 0 is returned, write an empty ticket */
            rv = tctx->ext.ticket_key_cb(s, nctick,
                                         nctick + TLSEXT_KEYNAME_LENGTH,
                                         ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0);
#endif
        if (rv < 0) {
            ret = SSL_TICKET_FATAL_ERR_OTHER;
            goto end;
        }
        if (rv == 0) {
            ret = SSL_TICKET_NO_DECRYPT;
            goto end;
        }
        if (rv == 2)
            renew_ticket = 1;
    } else {
        EVP_CIPHER *aes256cbc = NULL;

        /* Check key name matches */
        if (memcmp(etick, tctx->ext.tick_key_name,
                   TLSEXT_KEYNAME_LENGTH) != 0) {
            ret = SSL_TICKET_NO_DECRYPT;
            goto end;
        }

        aes256cbc = EVP_CIPHER_fetch(s->ctx->libctx, "AES-256-CBC",
                                     s->ctx->propq);
        if (aes256cbc == NULL
            || ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key,
                             sizeof(tctx->ext.secure->tick_hmac_key),
                             "SHA256") <= 0
            || EVP_DecryptInit_ex(ctx, aes256cbc, NULL,
                                  tctx->ext.secure->tick_aes_key,
                                  etick + TLSEXT_KEYNAME_LENGTH) <= 0) {
            EVP_CIPHER_free(aes256cbc);
            ret = SSL_TICKET_FATAL_ERR_OTHER;
            goto end;
        }
        EVP_CIPHER_free(aes256cbc);
        if (SSL_IS_TLS13(s))
            renew_ticket = 1;
    }
    /*
     * Attempt to process session ticket, first conduct sanity and integrity
     * checks on ticket.
     */
    mlen = ssl_hmac_size(hctx);
    if (mlen == 0) {
        ret = SSL_TICKET_FATAL_ERR_OTHER;
        goto end;
    }

    /* Sanity check ticket length: must exceed keyname + IV + HMAC */
    if (eticklen <=
        TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx) + mlen) {
        ret = SSL_TICKET_NO_DECRYPT;
        goto end;
    }
    eticklen -= mlen;
    /* Check HMAC of encrypted ticket */
    if (ssl_hmac_update(hctx, etick, eticklen) <= 0
        || ssl_hmac_final(hctx, tick_hmac, NULL, sizeof(tick_hmac)) <= 0) {
        ret = SSL_TICKET_FATAL_ERR_OTHER;
        goto end;
    }

    if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) {
        ret = SSL_TICKET_NO_DECRYPT;
        goto end;
    }
    /* Attempt to decrypt session data */
    /* Move p after IV to start of encrypted ticket, update length */
    p = etick + TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
    eticklen -= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_iv_length(ctx);
    sdec = OPENSSL_malloc(eticklen);
    if (sdec == NULL || EVP_DecryptUpdate(ctx, sdec, &slen, p,
                                          (int)eticklen) <= 0) {
        OPENSSL_free(sdec);
        ret = SSL_TICKET_FATAL_ERR_OTHER;
        goto end;
    }
    if (EVP_DecryptFinal(ctx, sdec + slen, &declen) <= 0) {
        OPENSSL_free(sdec);
        ret = SSL_TICKET_NO_DECRYPT;
        goto end;
    }
    slen += declen;
    p = sdec;

    sess = d2i_SSL_SESSION(NULL, &p, slen);
    slen -= p - sdec;
    OPENSSL_free(sdec);
    if (sess) {
        /* Some additional consistency checks */
        if (slen != 0) {
            SSL_SESSION_free(sess);
            sess = NULL;
            ret = SSL_TICKET_NO_DECRYPT;
            goto end;
        }
        /*
         * The session ID, if non-empty, is used by some clients to detect
         * that the ticket has been accepted. So we copy it to the session
         * structure. If it is empty set length to zero as required by
         * standard.
         */
        if (sesslen) {
            memcpy(sess->session_id, sess_id, sesslen);
            sess->session_id_length = sesslen;
        }
        if (renew_ticket)
            ret = SSL_TICKET_SUCCESS_RENEW;
        else
            ret = SSL_TICKET_SUCCESS;
        goto end;
    }
    ERR_clear_error();
    /*
     * For session parse failure, indicate that we need to send a new ticket.
     */
    ret = SSL_TICKET_NO_DECRYPT;

 end:
    EVP_CIPHER_CTX_free(ctx);
    ssl_hmac_free(hctx);

    /*
     * If set, the decrypt_ticket_cb() is called unless a fatal error was
     * detected above. The callback is responsible for checking |ret| before it
     * performs any action
     */
    if (s->session_ctx->decrypt_ticket_cb != NULL
            && (ret == SSL_TICKET_EMPTY
                || ret == SSL_TICKET_NO_DECRYPT
                || ret == SSL_TICKET_SUCCESS
                || ret == SSL_TICKET_SUCCESS_RENEW)) {
        size_t keyname_len = eticklen;
        int retcb;

        if (keyname_len > TLSEXT_KEYNAME_LENGTH)
            keyname_len = TLSEXT_KEYNAME_LENGTH;
        retcb = s->session_ctx->decrypt_ticket_cb(s, sess, etick, keyname_len,
                                                  ret,
                                                  s->session_ctx->ticket_cb_data);
        switch (retcb) {
        case SSL_TICKET_RETURN_ABORT:
            ret = SSL_TICKET_FATAL_ERR_OTHER;
            break;

        case SSL_TICKET_RETURN_IGNORE:
            ret = SSL_TICKET_NONE;
            SSL_SESSION_free(sess);
            sess = NULL;
            break;

        case SSL_TICKET_RETURN_IGNORE_RENEW:
            if (ret != SSL_TICKET_EMPTY && ret != SSL_TICKET_NO_DECRYPT)
                ret = SSL_TICKET_NO_DECRYPT;
            /* else the value of |ret| will already do the right thing */
            SSL_SESSION_free(sess);
            sess = NULL;
            break;

        case SSL_TICKET_RETURN_USE:
        case SSL_TICKET_RETURN_USE_RENEW:
            if (ret != SSL_TICKET_SUCCESS
                    && ret != SSL_TICKET_SUCCESS_RENEW)
                ret = SSL_TICKET_FATAL_ERR_OTHER;
            else if (retcb == SSL_TICKET_RETURN_USE)
                ret = SSL_TICKET_SUCCESS;
            else
                ret = SSL_TICKET_SUCCESS_RENEW;
            break;

        default:
            ret = SSL_TICKET_FATAL_ERR_OTHER;
        }
    }

    if (s->ext.session_secret_cb == NULL || SSL_IS_TLS13(s)) {
        switch (ret) {
        case SSL_TICKET_NO_DECRYPT:
        case SSL_TICKET_SUCCESS_RENEW:
        case SSL_TICKET_EMPTY:
            s->ext.ticket_expected = 1;
        }
    }

    *psess = sess;

    return ret;
}

Project: openssl

void ssl_hmac_free(SSL_HMAC *ctx)
{
    if (ctx != NULL) {
        EVP_MAC_CTX_free(ctx->ctx);
#ifndef OPENSSL_NO_DEPRECATED_3_0
        HMAC_CTX_free(ctx->old_ctx);
#endif
        OPENSSL_free(ctx);
    }
}

Project: openssl

static int tls1_check_sig_alg(SSL *s, X509 *x, int default_nid)
{
    int sig_nid, use_pc_sigalgs = 0;
    size_t i;
    const SIGALG_LOOKUP *sigalg;
    size_t sigalgslen;
    if (default_nid == -1)
        return 1;
    sig_nid = X509_get_signature_nid(x);
    if (default_nid)
        return sig_nid == default_nid ? 1 : 0;

    if (SSL_IS_TLS13(s) && s->s3.tmp.peer_cert_sigalgs != NULL) {
        /*
         * If we're in TLSv1.3 then we only get here if we're checking the
         * chain. If the peer has specified peer_cert_sigalgs then we use them
         * otherwise we default to normal sigalgs.
         */
        sigalgslen = s->s3.tmp.peer_cert_sigalgslen;
        use_pc_sigalgs = 1;
    } else {
        sigalgslen = s->shared_sigalgslen;
    }
    for (i = 0; i < sigalgslen; i++) {
        sigalg = use_pc_sigalgs
                 ? tls1_lookup_sigalg(s->s3.tmp.peer_cert_sigalgs[i])
                 : s->shared_sigalgs[i];
        if (sigalg != NULL && sig_nid == sigalg->sigandhash)
            return 1;
    }
    return 0;
}

Project: openssl

static const SIGALG_LOOKUP *tls1_get_legacy_sigalg(const SSL *s, int idx)
{
    if (idx == -1) {
        if (s->server) {
            size_t i;

            /* Work out index corresponding to ciphersuite */
            for (i = 0; i < SSL_PKEY_NUM; i++) {
                const SSL_CERT_LOOKUP *clu = ssl_cert_lookup_by_idx(i);

                if (clu->amask & s->s3.tmp.new_cipher->algorithm_auth) {
                    idx = i;
                    break;
                }
            }

            /*
             * Some GOST ciphersuites allow more than one signature algorithms
             * */
            if (idx == SSL_PKEY_GOST01 && s->s3.tmp.new_cipher->algorithm_auth != SSL_aGOST01) {
                int real_idx;

                for (real_idx = SSL_PKEY_GOST12_512; real_idx >= SSL_PKEY_GOST01;
                     real_idx--) {
                    if (s->cert->pkeys[real_idx].privatekey != NULL) {
                        idx = real_idx;
                        break;
                    }
                }
            }
        } else {
            idx = s->cert->key - s->cert->pkeys;
        }
    }
    if (idx < 0 || idx >= (int)OSSL_NELEM(tls_default_sigalg))
        return NULL;
    if (SSL_USE_SIGALGS(s) || idx != SSL_PKEY_RSA) {
        const SIGALG_LOOKUP *lu = tls1_lookup_sigalg(tls_default_sigalg[idx]);

        if (!tls1_lookup_md(s->ctx, lu, NULL))
            return NULL;
        if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
            return NULL;
        return lu;
    }
    if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, &legacy_rsa_sigalg))
        return NULL;
    return &legacy_rsa_sigalg;
}

Project: openssl

int ssl_hmac_update(SSL_HMAC *ctx, const unsigned char *data, size_t len)
{
    if (ctx->ctx != NULL)
        return EVP_MAC_update(ctx->ctx, data, len);
#ifndef OPENSSL_NO_DEPRECATED_3_0
    if (ctx->old_ctx != NULL)
        return HMAC_Update(ctx->old_ctx, data, len);
#endif
    return 0;
}

Project: openssl

static int check_cert_usable(SSL *s, const SIGALG_LOOKUP *sig, X509 *x,
                             EVP_PKEY *pkey)
{
    const SIGALG_LOOKUP *lu;
    int mdnid, pknid, supported;
    size_t i;

    /*
     * If the given EVP_PKEY cannot supporting signing with this sigalg,
     * the answer is simply 'no'.
     */
    ERR_set_mark();
    supported = EVP_PKEY_supports_digest_nid(pkey, sig->hash);
    ERR_pop_to_mark();
    if (supported == 0)
        return 0;

    /*
     * The TLS 1.3 signature_algorithms_cert extension places restrictions
     * on the sigalg with which the certificate was signed (by its issuer).
     */
    if (s->s3.tmp.peer_cert_sigalgs != NULL) {
        if (!X509_get_signature_info(x, &mdnid, &pknid, NULL, NULL))
            return 0;
        for (i = 0; i < s->s3.tmp.peer_cert_sigalgslen; i++) {
            lu = tls1_lookup_sigalg(s->s3.tmp.peer_cert_sigalgs[i]);
            if (lu == NULL)
                continue;

            /*
             * TODO this does not differentiate between the
             * rsa_pss_pss_* and rsa_pss_rsae_* schemes since we do not
             * have a chain here that lets us look at the key OID in the
             * signing certificate.
             */
            if (mdnid == lu->hash && pknid == lu->sig)
                return 1;
        }
        return 0;
    }

    /*
     * Without signat_algorithms_cert, any certificate for which we have
     * a viable public key is permitted.
     */
    return 1;
}

Project: openssl

int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len,
                   size_t max_size)
{
    if (ctx->ctx != NULL)
        return EVP_MAC_final(ctx->ctx, md, len, max_size);
#ifndef OPENSSL_NO_DEPRECATED_3_0
    if (ctx->old_ctx != NULL) {
        unsigned int l;

        if (HMAC_Final(ctx->old_ctx, md, &l) > 0) {
            if (len != NULL)
                *len = l;
            return 1;
        }
    }
#endif
    return 0;
}

Project: openssl

int ssl_cipher_disabled(const SSL *s, const SSL_CIPHER *c, int op, int ecdhe)
{
    if (c->algorithm_mkey & s->s3.tmp.mask_k
        || c->algorithm_auth & s->s3.tmp.mask_a)
        return 1;
    if (s->s3.tmp.max_ver == 0)
        return 1;
    if (!SSL_IS_DTLS(s)) {
        int min_tls = c->min_tls;

        /*
         * For historical reasons we will allow ECHDE to be selected by a server
         * in SSLv3 if we are a client
         */
        if (min_tls == TLS1_VERSION && ecdhe
                && (c->algorithm_mkey & (SSL_kECDHE | SSL_kECDHEPSK)) != 0)
            min_tls = SSL3_VERSION;

        if ((min_tls > s->s3.tmp.max_ver) || (c->max_tls < s->s3.tmp.min_ver))
            return 1;
    }
    if (SSL_IS_DTLS(s) && (DTLS_VERSION_GT(c->min_dtls, s->s3.tmp.max_ver)
                           || DTLS_VERSION_LT(c->max_dtls, s->s3.tmp.min_ver)))
        return 1;

    return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
}

Project: openssl

int ssl_hmac_init(SSL_HMAC *ctx, void *key, size_t len, char *md)
{
    OSSL_PARAM params[3], *p = params;

    if (ctx->ctx != NULL) {
        *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, md, 0);
        *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, key, len);
        *p = OSSL_PARAM_construct_end();
        if (EVP_MAC_CTX_set_params(ctx->ctx, params) && EVP_MAC_init(ctx->ctx))
            return 1;
    }
#ifndef OPENSSL_NO_DEPRECATED_3_0
    if (ctx->old_ctx != NULL)
        return HMAC_Init_ex(ctx->old_ctx, key, len,
                            EVP_get_digestbyname(md), NULL);
#endif
    return 0;
}

Project: openssl

SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx)
{
    SSL_HMAC *ret = OPENSSL_zalloc(sizeof(*ret));
    EVP_MAC *mac = NULL;

    if (ret == NULL)
        return NULL;
#ifndef OPENSSL_NO_DEPRECATED_3_0
    if (ctx->ext.ticket_key_evp_cb == NULL
            && ctx->ext.ticket_key_cb != NULL) {
        ret->old_ctx = HMAC_CTX_new();
        if (ret->old_ctx == NULL)
            goto err;
        return ret;
    }
#endif
    mac = EVP_MAC_fetch(ctx->libctx, "HMAC", NULL);
    if (mac == NULL || (ret->ctx = EVP_MAC_CTX_new(mac)) == NULL)
        goto err;
    EVP_MAC_free(mac);
    return ret;
 err:
    EVP_MAC_CTX_free(ret->ctx);
    EVP_MAC_free(mac);
    OPENSSL_free(ret);
    return NULL;
}

Project: openssl

HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx)
{
    return ctx->old_ctx;
}