+ if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
+ /* Generate session key */
+ || RAND_bytes(pms, pmslen) <= 0) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, 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 (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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ EVP_MD_CTX_free(ukm_hash);
+ 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_CKE_GOST, 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) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
+ goto err;
+ }
+ if (msglen >= 0x80) {
+ *((*p)++) = 0x81;
+ *((*p)++) = msglen & 0xff;
+ *len = msglen + 3;
+ } else {
+ *((*p)++) = msglen & 0xff;
+ *len = 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;