summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2026-08-27 07:13:34 +0000
committertb <>2026-08-27 07:13:34 +0000
commit448d7a6a510aab5c772d736a43fb5dcec9dfbd73 (patch)
treef67eb62142f9922c5c57ea2a3c58dadbee783beb /src/lib
parent85f442b9807a72de444e8a0c8670310031ffd5e8 (diff)
downloadopenbsd-448d7a6a510aab5c772d736a43fb5dcec9dfbd73.tar.gz
openbsd-448d7a6a510aab5c772d736a43fb5dcec9dfbd73.tar.bz2
openbsd-448d7a6a510aab5c772d736a43fb5dcec9dfbd73.zip
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
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/cms/cms_kari.c11
1 files changed, 8 insertions, 3 deletions
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 @@
1/* $OpenBSD: cms_kari.c,v 1.18 2025/05/10 05:54:38 tb Exp $ */ 1/* $OpenBSD: cms_kari.c,v 1.19 2026/08/27 07:13:34 tb Exp $ */
2/* 2/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4 * project. 4 * project.
@@ -250,6 +250,7 @@ cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in,
250 size_t keklen; 250 size_t keklen;
251 int rv = 0; 251 int rv = 0;
252 unsigned char *out = NULL; 252 unsigned char *out = NULL;
253 size_t outsize = 0;
253 int outlen; 254 int outlen;
254 255
255 keklen = EVP_CIPHER_CTX_key_length(kari->ctx); 256 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,
264 /* obtain output length of ciphered key */ 265 /* obtain output length of ciphered key */
265 if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen)) 266 if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen))
266 goto err; 267 goto err;
267 out = malloc(outlen); 268
269 outsize = outlen;
270 if (outsize < inlen)
271 outsize = inlen;
272 out = malloc(outsize);
268 if (out == NULL) 273 if (out == NULL)
269 goto err; 274 goto err;
270 if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen)) 275 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,
276 err: 281 err:
277 explicit_bzero(kek, keklen); 282 explicit_bzero(kek, keklen);
278 if (!rv) 283 if (!rv)
279 free(out); 284 freezero(out, outsize);
280 (void)EVP_CIPHER_CTX_reset(kari->ctx); 285 (void)EVP_CIPHER_CTX_reset(kari->ctx);
281 /* FIXME: WHY IS kari->pctx freed here? /RL */ 286 /* FIXME: WHY IS kari->pctx freed here? /RL */
282 EVP_PKEY_CTX_free(kari->pctx); 287 EVP_PKEY_CTX_free(kari->pctx);