- /* Otherwise, generate ephemeral key pair */
- pmslen = 32;
- pms = OPENSSL_malloc(pmslen);
- if (pms == NULL)
- goto memerr;
-
- if (pkey_ctx == NULL
- || 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);
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- ERR_R_INTERNAL_ERROR);
- goto err;
- };
- /*
- * If we have client certificate, use its secret as peer key
- */
- if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
- if (EVP_PKEY_derive_set_peer
- (pkey_ctx, s->cert->key->privatekey) <= 0) {
- /*
- * If there was an error - just ignore it. Ephemeral key
- * * would be used
- */
- ERR_clear_error();
- }
- }
- /*
- * Compute shared IV and store it in algorithm-specific context
- * data
- */
- ukm_hash = EVP_MD_CTX_new();
- if (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);
- 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);
- SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE,
- SSL_R_LIBRARY_BUG);
- goto err;
- }
- /* Make GOST keytransport blob message */
- /*
- * Encapsulate it into sequence
- */
- *(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);
- 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;
- } else {
- *(p++) = msglen & 0xff;
- n = msglen + 2;
- }
- 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) {
- /* 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;