diff options
author | Theo Buehler <tb@cvs.openbsd.org> | 2021-02-18 19:12:30 +0000 |
---|---|---|
committer | Theo Buehler <tb@cvs.openbsd.org> | 2021-02-18 19:12:30 +0000 |
commit | bfe6a3c3c55053dabcee6522b0ded0581b06163b (patch) | |
tree | ef252f6a3eef7ae33dbf0d8e8b0d3424f1481956 /lib/libcrypto | |
parent | c4a53b6d562a630fbd8c8262e40eea04f0aec3c9 (diff) |
Pull in fix for EVP_CipherUpdate() overflow from OpenSSL.
ok inoguchi
commit 6a51b9e1d0cf0bf8515f7201b68fb0a3482b3dc1
Author: Matt Caswell <matt@openssl.org>
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 <pauli@openssl.org>
Diffstat (limited to 'lib/libcrypto')
-rw-r--r-- | lib/libcrypto/evp/evp_enc.c | 24 |
1 files changed, 23 insertions, 1 deletions
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 <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -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; |