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

Split out ECDHE from tls_process_key_exchange()



Continuing from the previous commit. Refactor tls_process_key_exchange() to
split out into a separate function the ECDHE aspects.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent e01a610d
Loading
Loading
Loading
Loading
+86 −76
Original line number Diff line number Diff line
@@ -1489,48 +1489,9 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
#endif
}

MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
{
    EVP_MD_CTX *md_ctx;
    int al = -1;
    long alg_k, alg_a;
    EVP_PKEY *pkey = NULL;
    PACKET save_param_start, signature;

    md_ctx = EVP_MD_CTX_new();
    if (md_ctx == NULL) {
        al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
        goto f_err;
    }

    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;

    save_param_start = *pkt;

#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
    EVP_PKEY_free(s->s3->peer_tmp);
    s->s3->peer_tmp = NULL;
#endif

    alg_a = s->s3->tmp.new_cipher->algorithm_auth;

    if (alg_k & SSL_PSK) {
        if (!tls_process_ske_psk_preamble(s, pkt, &al))
            goto err;
    }

    /* Nothing else to do for plain PSK or RSAPSK */
    if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
    } else if (alg_k & SSL_kSRP) {
        if (!tls_process_ske_srp(s, pkt, &pkey, &al))
            goto err;
    } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
        if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
            goto err;
    }
#ifndef OPENSSL_NO_EC
    else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
    PACKET encoded_pt;
    const unsigned char *ecparams;
    int curve_nid;
@@ -1542,24 +1503,26 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     * ECParameters in this case is just three bytes.
     */
    if (!PACKET_get_bytes(pkt, &ecparams, 3)) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
            goto f_err;
        return 0;
    }
    /*
     * Check curve is one of our preferences, if not server has sent an
     * invalid curve. ECParameters is 3 bytes.
     */
    if (!tls1_check_curve(s, ecparams, 3)) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_WRONG_CURVE);
            goto f_err;
        return 0;
    }

    curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2));
    if (curve_nid  == 0) {
            al = SSL_AD_INTERNAL_ERROR;
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
               SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
            goto f_err;
        return 0;
    }

    /* Set up EVP_PKEY with named curve as parameters */
@@ -1568,24 +1531,26 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
        || EVP_PKEY_paramgen_init(pctx) <= 0
        || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, curve_nid) <= 0
        || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
            al = SSL_AD_INTERNAL_ERROR;
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
        EVP_PKEY_CTX_free(pctx);
            goto f_err;
        return 0;
    }
    EVP_PKEY_CTX_free(pctx);
    pctx = NULL;

    if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
            goto f_err;
        return 0;
    }

    if (EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(s->s3->peer_tmp),
                       PACKET_data(&encoded_pt),
                       PACKET_remaining(&encoded_pt), NULL) == 0) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_ECPOINT);
            goto f_err;
        return 0;
    }

    /*
@@ -1593,22 +1558,67 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
     * ECParameters in the server key exchange message. We do support RSA
     * and ECDSA.
     */
        if (0) ;
# ifndef OPENSSL_NO_RSA
        else if (alg_a & SSL_aRSA)
            pkey = X509_get0_pubkey(s->session->peer);
    if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA)
        *pkey = X509_get0_pubkey(s->session->peer);
    else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA)
        *pkey = X509_get0_pubkey(s->session->peer);
    /* else anonymous ECDH, so no certificate or pkey. */

    return 1;
#else
    SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
    *al = SSL_AD_INTERNAL_ERROR;
    return 0;
#endif
# ifndef OPENSSL_NO_EC
        else if (alg_a & SSL_aECDSA)
            pkey = X509_get0_pubkey(s->session->peer);
}

MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
{
    EVP_MD_CTX *md_ctx;
    int al = -1;
    long alg_k, alg_a;
    EVP_PKEY *pkey = NULL;
    PACKET save_param_start, signature;

    md_ctx = EVP_MD_CTX_new();
    if (md_ctx == NULL) {
        al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
        goto f_err;
    }

    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;

    save_param_start = *pkt;

#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
    EVP_PKEY_free(s->s3->peer_tmp);
    s->s3->peer_tmp = NULL;
#endif
        /* else anonymous ECDH, so no certificate or pkey. */

    alg_a = s->s3->tmp.new_cipher->algorithm_auth;

    if (alg_k & SSL_PSK) {
        if (!tls_process_ske_psk_preamble(s, pkt, &al))
            goto err;
    }

    /* Nothing else to do for plain PSK or RSAPSK */
    if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
    } else if (alg_k & SSL_kSRP) {
        if (!tls_process_ske_srp(s, pkt, &pkey, &al))
            goto err;
    } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
        if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
            goto err;
    } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
        if (!tls_process_ske_ecdhe(s, pkt, &pkey, &al))
            goto err;
    } else if (alg_k) {
        al = SSL_AD_UNEXPECTED_MESSAGE;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
        goto f_err;
    }
#endif                          /* !OPENSSL_NO_EC */

    /* if it was signed, check the signature */
    if (pkey != NULL) {