/* Provenance: openssl/openssl cms_kek_cipher (fixed). * repo: openssl/openssl * commit: a0c8ec557d9cac078f032d76cdf684fe743eb382 * parent: d307f61f1b341b6eb7d5d07bd6902a939c709bc6 * commit_url: https://github.com/openssl/openssl/commit/a0c8ec557d9cac078f032d76cdf684fe743eb382 * cve: CVE-2026-63072 * license: Apache-2.0 * function: cms_kek_cipher * relpath: crypto/cms/cms_kari.c */ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in, size_t inlen, CMS_KeyAgreeRecipientInfo *kari, int enc) { /* Key encryption key */ unsigned char kek[EVP_MAX_KEY_LENGTH]; size_t keklen; int rv = 0; unsigned char *out = NULL; size_t out_alloc_len = 0; int outlen; size_t outsize; keklen = EVP_CIPHER_CTX_get_key_length(kari->ctx); if (keklen > EVP_MAX_KEY_LENGTH) return 0; /* Derive KEK */ if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0) goto err; /* Set KEK in context */ if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc)) goto err; /* obtain output length of ciphered key */ if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) goto err; /* * On its integrity-failure paths that primitive writes and cleanses up to * inlen bytes of the output buffer. Size the buffer for that worst case so * a failed unwrap cannot write past the allocation. */ outsize = (size_t)outlen < inlen ? inlen : (size_t)outlen; out = OPENSSL_malloc(outsize); if (out == NULL) goto err; out_alloc_len = (size_t)outlen; if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, (int)inlen)) goto err; *pout = out; *poutlen = (size_t)outlen; rv = 1; err: OPENSSL_cleanse(kek, keklen); if (!rv) OPENSSL_clear_free(out, out_alloc_len); EVP_CIPHER_CTX_reset(kari->ctx); /* FIXME: WHY IS kari->pctx freed here? /RL */ EVP_PKEY_CTX_free(kari->pctx); kari->pctx = NULL; return rv; }