From bfe6a3c3c55053dabcee6522b0ded0581b06163b Mon Sep 17 00:00:00 2001 From: Theo Buehler Date: Thu, 18 Feb 2021 19:12:30 +0000 Subject: Pull in fix for EVP_CipherUpdate() overflow from OpenSSL. ok inoguchi commit 6a51b9e1d0cf0bf8515f7201b68fb0a3482b3dc1 Author: Matt Caswell Date: Tue Feb 2 17:17:23 2021 +0000 Don't overflow the output length in EVP_CipherUpdate calls CVE-2021-23840 Reviewed-by: Paul Dale --- lib/libcrypto/evp/evp_enc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'lib/libcrypto') diff --git a/lib/libcrypto/evp/evp_enc.c b/lib/libcrypto/evp/evp_enc.c index bb49e28267a..896b9e1a16f 100644 --- a/lib/libcrypto/evp/evp_enc.c +++ b/lib/libcrypto/evp/evp_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: evp_enc.c,v 1.43 2019/04/14 17:16:57 jsing Exp $ */ +/* $OpenBSD: evp_enc.c,v 1.44 2021/02/18 19:12:29 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -56,6 +56,7 @@ * [including the GNU Public Licence.] */ +#include #include #include #include @@ -337,6 +338,17 @@ EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, return 1; } else { j = bl - i; + + /* + * Once we've processed the first j bytes from in, the + * amount of data left that is a multiple of the block + * length is (inl - j) & ~(bl - 1). Ensure this plus + * the block processed from ctx-buf doesn't overflow. + */ + if (((inl - j) & ~(bl - 1)) > INT_MAX - bl) { + EVPerror(EVP_R_TOO_LARGE); + return 0; + } memcpy(&(ctx->buf[i]), in, j); if (!M_do_cipher(ctx, out, ctx->buf, bl)) return 0; @@ -451,6 +463,16 @@ EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, } if (ctx->final_used) { + /* + * final_used is only ever set if buf_len is 0. Therefore the + * maximum length output we will ever see from EVP_EncryptUpdate + * is inl & ~(b - 1). Since final_used is set, the final output + * length is (inl & ~(b - 1)) + b. Ensure it doesn't overflow. + */ + if ((inl & ~(b - 1)) > INT_MAX - b) { + EVPerror(EVP_R_TOO_LARGE); + return 0; + } memcpy(out, ctx->final, b); out += b; fix_len = 1; -- cgit v1.2.3