From 448d7a6a510aab5c772d736a43fb5dcec9dfbd73 Mon Sep 17 00:00:00 2001 From: tb <> Date: Thu, 27 Aug 2026 07:13:34 +0000 Subject: libcrypto: harden cms_kek_cipher() a bit When AES key unwrap with padding is in use, the EVP interface breaks its contract and writes more than the outlen it initially reports to the output buffer. This is an old, sneaky trap that the muppet set eons ago and many victims walked right into it, including the muppet himself. If inlen is larger than outlen, allocate inlen bytes to unwrap with padding to avoid a buffer overwrite. This is a variant of OpenSSL's fix. Since we do not support AES keywrap with padding no actual bufer overwrite occurs here at the moment, but if we ever chose to do so (unlikely) this trap would be avoided. There's plenty more traps that the next round of scas will surely find in this absolute trashfire of CMS support code. ok kenjiro --- src/lib/libcrypto/cms/cms_kari.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/lib/libcrypto') diff --git a/src/lib/libcrypto/cms/cms_kari.c b/src/lib/libcrypto/cms/cms_kari.c index c23da18058..a16f51a569 100644 --- a/src/lib/libcrypto/cms/cms_kari.c +++ b/src/lib/libcrypto/cms/cms_kari.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cms_kari.c,v 1.18 2025/05/10 05:54:38 tb Exp $ */ +/* $OpenBSD: cms_kari.c,v 1.19 2026/08/27 07:13:34 tb Exp $ */ /* * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. @@ -250,6 +250,7 @@ cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in, size_t keklen; int rv = 0; unsigned char *out = NULL; + size_t outsize = 0; int outlen; keklen = EVP_CIPHER_CTX_key_length(kari->ctx); @@ -264,7 +265,11 @@ cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in, /* obtain output length of ciphered key */ if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) goto err; - out = malloc(outlen); + + outsize = outlen; + if (outsize < inlen) + outsize = inlen; + out = malloc(outsize); if (out == NULL) goto err; if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) @@ -276,7 +281,7 @@ cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in, err: explicit_bzero(kek, keklen); if (!rv) - free(out); + freezero(out, outsize); (void)EVP_CIPHER_CTX_reset(kari->ctx); /* FIXME: WHY IS kari->pctx freed here? /RL */ EVP_PKEY_CTX_free(kari->pctx); -- cgit v1.2.3-55-g6feb