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

Split out GOST CKE construction into a separate function



Continuing previous commit to break up the
tls_construct_client_key_exchange() function. This splits out the GOST
code.

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent 67ad5aab
Loading
Loading
Loading
Loading
+144 −129
Original line number Diff line number Diff line
@@ -2283,45 +2283,16 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
#endif
}

int tls_construct_client_key_exchange(SSL *s)
static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
{
    unsigned char *p;
    int n;
    size_t pskhdrlen = 0;
    unsigned long alg_k;
    int al = -1;

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

    p = ssl_handshake_start(s);



    if ((alg_k & SSL_PSK)
            && !tls_construct_cke_psk_preamble(s, &p, &pskhdrlen, &al))
        goto err;

    if (alg_k & SSL_kPSK) {
        n = 0;
    } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
        if (!tls_construct_cke_rsa(s, &p, &n, &al))
            goto err;
    } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
        if (!tls_construct_cke_dhe(s, &p, &n, &al))
            goto err;
    } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
        if (!tls_construct_cke_ecdhe(s, &p, &n, &al))
            goto err;
    }
#ifndef OPENSSL_NO_GOST
    else if (alg_k & SSL_kGOST) {
    /* GOST key exchange message creation */
        EVP_PKEY_CTX *pkey_ctx;
    EVP_PKEY_CTX *pkey_ctx = NULL;
    X509 *peer_cert;
    size_t msglen;
    unsigned int md_len;
    unsigned char shared_ukm[32], tmp[256];
        EVP_MD_CTX *ukm_hash;
    EVP_MD_CTX *ukm_hash = NULL;
    int dgst_nid = NID_id_GostR3411_94;
    unsigned char *pms = NULL;
    size_t pmslen = 0;
@@ -2329,22 +2300,23 @@ int tls_construct_client_key_exchange(SSL *s)
    if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
        dgst_nid = NID_id_GostR3411_2012_256;


    /*
     * Get server sertificate PKEY and create ctx from it
     */
    peer_cert = s->session->peer;
    if (!peer_cert) {
        *al = SSL_AD_HANDSHAKE_FAILURE;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
            goto err;
        return 0;
    }

    pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
    if (pkey_ctx == NULL) {
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               ERR_R_MALLOC_FAILURE);
            goto err;
        return 0;
    }
    /*
     * If we have send a certificate, and certificate key
@@ -2355,15 +2327,17 @@ int tls_construct_client_key_exchange(SSL *s)
    /* Otherwise, generate ephemeral key pair */
    pmslen = 32;
    pms = OPENSSL_malloc(pmslen);
        if (pms == NULL)
            goto memerr;
    if (pms == NULL) {
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               ERR_R_MALLOC_FAILURE);
        return 0;
    }

        if (pkey_ctx == NULL
                || EVP_PKEY_encrypt_init(pkey_ctx) <= 0
    if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
            /* Generate session key */
            || RAND_bytes(pms, pmslen) <= 0) {
            EVP_PKEY_CTX_free(pkey_ctx);
            OPENSSL_clear_free(pms, pmslen);
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               ERR_R_INTERNAL_ERROR);
        goto err;
@@ -2386,24 +2360,23 @@ int tls_construct_client_key_exchange(SSL *s)
     * data
     */
    ukm_hash = EVP_MD_CTX_new();
        if (EVP_DigestInit(ukm_hash,
                           EVP_get_digestbynid(dgst_nid)) <= 0
    if (ukm_hash == NULL
            || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
            || EVP_DigestUpdate(ukm_hash, s->s3->client_random,
                                SSL3_RANDOM_SIZE) <= 0
            || EVP_DigestUpdate(ukm_hash, s->s3->server_random,
                                SSL3_RANDOM_SIZE) <= 0
            || EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
            EVP_MD_CTX_free(ukm_hash);
            OPENSSL_clear_free(pms, pmslen);
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               ERR_R_INTERNAL_ERROR);
        goto err;
    }
    EVP_MD_CTX_free(ukm_hash);
        if (EVP_PKEY_CTX_ctrl
            (pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 8,
             shared_ukm) < 0) {
            OPENSSL_clear_free(pms, pmslen);
    ukm_hash = NULL;
    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
                          EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               SSL_R_LIBRARY_BUG);
        goto err;
@@ -2412,34 +2385,79 @@ int tls_construct_client_key_exchange(SSL *s)
    /*
     * Encapsulate it into sequence
     */
        *(p++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
    *((*p)++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
    msglen = 255;
    if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
            OPENSSL_clear_free(pms, pmslen);
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
               SSL_R_LIBRARY_BUG);
        goto err;
    }
    if (msglen >= 0x80) {
            *(p++) = 0x81;
            *(p++) = msglen & 0xff;
            n = msglen + 3;
        *((*p)++) = 0x81;
        *((*p)++) = msglen & 0xff;
        *len = msglen + 3;
    } else {
            *(p++) = msglen & 0xff;
            n = msglen + 2;
        *((*p)++) = msglen & 0xff;
        *len = msglen + 2;
    }
        memcpy(p, tmp, msglen);
    memcpy(*p, tmp, msglen);
    /* Check if pubkey from client certificate was used */
        if (EVP_PKEY_CTX_ctrl
            (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) {
    if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
                          NULL) > 0) {
        /* Set flag "skip certificate verify" */
        s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
    }
    EVP_PKEY_CTX_free(pkey_ctx);
    s->s3->tmp.pms = pms;
    s->s3->tmp.pmslen = pmslen;
    }

    return 1;
 err:
    EVP_PKEY_CTX_free(pkey_ctx);
    OPENSSL_clear_free(pms, pmslen);
    EVP_MD_CTX_free(ukm_hash);
    return 0;
#else
    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
    *al = SSL_AD_INTERNAL_ERROR;
    return 0;
#endif
}

int tls_construct_client_key_exchange(SSL *s)
{
    unsigned char *p;
    int n;
    size_t pskhdrlen = 0;
    unsigned long alg_k;
    int al = -1;

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

    p = ssl_handshake_start(s);



    if ((alg_k & SSL_PSK)
            && !tls_construct_cke_psk_preamble(s, &p, &pskhdrlen, &al))
        goto err;

    if (alg_k & SSL_kPSK) {
        n = 0;
    } else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
        if (!tls_construct_cke_rsa(s, &p, &n, &al))
            goto err;
    } else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
        if (!tls_construct_cke_dhe(s, &p, &n, &al))
            goto err;
    } else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
        if (!tls_construct_cke_ecdhe(s, &p, &n, &al))
            goto err;
    } else if (alg_k & SSL_kGOST) {
        if (!tls_construct_cke_gost(s, &p, &n, &al))
            goto err;
    }
#ifndef OPENSSL_NO_SRP
    else if (alg_k & SSL_kSRP) {
        if (s->srp_ctx.A != NULL) {
@@ -2477,9 +2495,6 @@ int tls_construct_client_key_exchange(SSL *s)
    }

    return 1;
 memerr:
    SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
    al = SSL_AD_INTERNAL_ERROR;
 err:
    if (al != -1)
        ssl3_send_alert(s, SSL3_AL_FATAL, al);