/* Provenance: openssl/openssl ossl_cms_RecipientInfo_pwri_crypt (fixed). * repo: openssl/openssl * commit: 74245170b5a64b234ac4af27c86a25ec251c8b2a * parent: a9af3442290e8a04706a3cd5f284ffd5b486e3f6 * commit_url: https://github.com/openssl/openssl/commit/74245170b5a64b234ac4af27c86a25ec251c8b2a * cve: CVE-2026-42766 * license: Apache-2.0 * function: ossl_cms_RecipientInfo_pwri_crypt * relpath: crypto/cms/cms_pwri.c */ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri, int en_de) { CMS_EncryptedContentInfo *ec; CMS_PasswordRecipientInfo *pwri; int r = 0; X509_ALGOR *algtmp, *kekalg = NULL; EVP_CIPHER_CTX *kekctx = NULL; char name[OSSL_MAX_NAME_SIZE]; EVP_CIPHER *kekcipher; unsigned char *key = NULL; size_t keylen; const CMS_CTX *cms_ctx = ossl_cms_get0_cmsctx(cms); ec = ossl_cms_get0_env_enc_content(cms); pwri = ri->d.pwri; if (pwri->pass == NULL) { ERR_raise(ERR_LIB_CMS, CMS_R_NO_PASSWORD); return 0; } algtmp = pwri->keyEncryptionAlgorithm; if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) { ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM); return 0; } kekalg = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR), algtmp->parameter); if (kekalg == NULL) { ERR_raise(ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER); return 0; } OBJ_obj2txt(name, sizeof(name), kekalg->algorithm, 0); kekcipher = EVP_CIPHER_fetch(ossl_cms_ctx_get0_libctx(cms_ctx), name, ossl_cms_ctx_get0_propq(cms_ctx)); if (kekcipher == NULL) { ERR_raise(ERR_LIB_CMS, CMS_R_UNKNOWN_CIPHER); goto err; } kekctx = EVP_CIPHER_CTX_new(); if (kekctx == NULL) { ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de)) goto err; EVP_CIPHER_CTX_set_padding(kekctx, 0); if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0) { ERR_raise(ERR_LIB_CMS, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR); goto err; } algtmp = pwri->keyDerivationAlgorithm; /* Finish password based key derivation to setup key in "ctx" */ if (algtmp == NULL) { ERR_raise_data(ERR_LIB_CMS, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER, "Missing KeyDerivationAlgorithm"); goto err; } if (!EVP_PBE_CipherInit_ex(algtmp->algorithm, (char *)pwri->pass, (int)pwri->passlen, algtmp->parameter, kekctx, en_de, cms_ctx->libctx, cms_ctx->propq)) { ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } /* Finally wrap/unwrap the key */ if (en_de) { if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx)) goto err; key = OPENSSL_malloc(keylen); if (key == NULL) goto err; if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx)) goto err; pwri->encryptedKey->data = key; pwri->encryptedKey->length = (int)keylen; } else { key = OPENSSL_malloc(pwri->encryptedKey->length); if (key == NULL) goto err; if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data, pwri->encryptedKey->length, kekctx)) { ERR_raise(ERR_LIB_CMS, CMS_R_UNWRAP_FAILURE); goto err; } OPENSSL_clear_free(ec->key, ec->keylen); ec->key = key; ec->keylen = keylen; } r = 1; err: EVP_CIPHER_free(kekcipher); EVP_CIPHER_CTX_free(kekctx); if (!r) OPENSSL_free(key); X509_ALGOR_free(kekalg); return r; }