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

Split out DHE from tls_process_key_exchange()



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

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent 25c6c10c
Loading
Loading
Loading
Loading
+99 −86
Original line number Diff line number Diff line
@@ -1393,45 +1393,9 @@ static int tls_process_ske_srp(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_dhe(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;
    }
#ifndef OPENSSL_NO_DH
    else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
    PACKET prime, generator, pub_key;
    EVP_PKEY *peer_tmp = NULL;

@@ -1441,17 +1405,18 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
    if (!PACKET_get_length_prefixed_2(pkt, &prime)
        || !PACKET_get_length_prefixed_2(pkt, &generator)
        || !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
            goto f_err;
        return 0;
    }

    peer_tmp = EVP_PKEY_new();
    dh = DH_new();

    if (peer_tmp == NULL || dh == NULL) {
            al = SSL_AD_INTERNAL_ERROR;
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
            goto dherr;
        goto err;
    }

    p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
@@ -1460,62 +1425,110 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
    bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
                          NULL);
    if (p == NULL || g == NULL || bnpub_key == NULL) {
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
            goto dherr;
        goto err;
    }

    if (BN_is_zero(p) || BN_is_zero(g) || BN_is_zero(bnpub_key)) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_DH_VALUE);
            goto dherr;
        goto err;
    }

    if (!DH_set0_pqg(dh, p, NULL, g)) {
            al = SSL_AD_INTERNAL_ERROR;
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
            goto dherr;
        goto err;
    }
    p = g = NULL;

    if (!DH_set0_key(dh, bnpub_key, NULL)) {
            al = SSL_AD_INTERNAL_ERROR;
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_BN_LIB);
            goto dherr;
        goto err;
    }
    bnpub_key = NULL;

    if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
            al = SSL_AD_HANDSHAKE_FAILURE;
        *al = SSL_AD_HANDSHAKE_FAILURE;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_DH_KEY_TOO_SMALL);
            goto dherr;
        goto err;
    }

    if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
            al = SSL_AD_INTERNAL_ERROR;
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
            goto dherr;
        goto err;
    }

    s->s3->peer_tmp = peer_tmp;

        goto dhend;
 dherr:
    /*
     * FIXME: This makes assumptions about which ciphersuites come with
     * public keys. We should have a less ad-hoc way of doing this
     */
    if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA|SSL_aDSS))
        *pkey = X509_get0_pubkey(s->session->peer);
    /* else anonymous DH, so no certificate or pkey. */

    return 1;

 err:
    BN_free(p);
    BN_free(g);
    BN_free(bnpub_key);
    DH_free(dh);
    EVP_PKEY_free(peer_tmp);

    return 0;
#else
    SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
    *al = SSL_AD_INTERNAL_ERROR;
    return 0;
#endif
}

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;
 dhend:
        /*
         * FIXME: This makes assumptions about which ciphersuites come with
         * public keys. We should have a less ad-hoc way of doing this
         */
        if (alg_a & (SSL_aRSA|SSL_aDSS))
            pkey = X509_get0_pubkey(s->session->peer);
        /* else anonymous DH, so no certificate or pkey. */
    }
#endif                          /* !OPENSSL_NO_DH */

    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;