/* Provenance: openssl/openssl tls_construct_cke_gost18 (fixed). * repo: openssl/openssl * commit: 373de40f3f76c63e4f2684abd86706f3863347ca * parent: 3be529cd2eb4eb3eaaa7913af619fb9c918d4581 * commit_url: https://github.com/openssl/openssl/commit/373de40f3f76c63e4f2684abd86706f3863347ca * cve: CVE-2022-29242 * license: Apache-2.0 * function: tls_construct_cke_gost18 * relpath: ssl/statem/statem_clnt.c */ static int tls_construct_cke_gost18(SSL *s, WPACKET *pkt) { #ifndef OPENSSL_NO_GOST /* GOST 2018 key exchange message creation */ unsigned char rnd_dgst[32]; unsigned char *encdata = NULL; EVP_PKEY_CTX *pkey_ctx = NULL; X509 *peer_cert; unsigned char *pms = NULL; size_t pmslen = 0; size_t msglen; int cipher_nid = ossl_gost18_cke_cipher_nid(s); if (cipher_nid == NID_undef) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return 0; } if (ossl_gost_ukm(s, rnd_dgst) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); goto err; } /* Pre-master secret - random bytes */ pmslen = 32; pms = OPENSSL_malloc(pmslen); if (pms == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); goto err; } if (RAND_bytes_ex(s->ctx->libctx, pms, pmslen, 0) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); goto err; } /* Get server certificate PKEY and create ctx from it */ peer_cert = s->session->peer; if (peer_cert == NULL) { SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); goto err; } pkey_ctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, X509_get0_pubkey(peer_cert), s->ctx->propq); if (pkey_ctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); goto err; } if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0 ) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); goto err; }; /* Reuse EVP_PKEY_CTRL_SET_IV, make choice in engine code */ if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_SET_IV, 32, rnd_dgst) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG); goto err; } if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, EVP_PKEY_CTRL_CIPHER, cipher_nid, NULL) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_LIBRARY_BUG); goto err; } if (EVP_PKEY_encrypt(pkey_ctx, NULL, &msglen, pms, pmslen) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB); goto err; } if (!WPACKET_allocate_bytes(pkt, msglen, &encdata) || EVP_PKEY_encrypt(pkey_ctx, encdata, &msglen, pms, pmslen) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB); goto err; } EVP_PKEY_CTX_free(pkey_ctx); pkey_ctx = NULL; s->s3.tmp.pms = pms; s->s3.tmp.pmslen = pmslen; return 1; err: EVP_PKEY_CTX_free(pkey_ctx); OPENSSL_clear_free(pms, pmslen); return 0; #else SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return 0; #endif }