diff options
author | Matt Caswell <matt@openssl.org> | 2021-02-02 17:17:23 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2021-02-16 11:40:12 +0000 |
commit | c9fb704cf3af5524eb8e79961e31b60eee8c3c47 (patch) | |
tree | b657b2b1a0add855541ba920b8ea861018b3eb7e /crypto/evp/evp_enc.c | |
parent | c1ddd392cf9737c09c1f9bf690adfbe596403c5e (diff) | |
download | openssl-new-c9fb704cf3af5524eb8e79961e31b60eee8c3c47.tar.gz |
Don't overflow the output length in EVP_CipherUpdate calls
CVE-2021-23840
Reviewed-by: Paul Dale <pauli@openssl.org>
Diffstat (limited to 'crypto/evp/evp_enc.c')
-rw-r--r-- | crypto/evp/evp_enc.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index b804d74914..f049cb40bb 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -11,6 +11,7 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include <stdio.h> +#include <limits.h> #include <assert.h> #include "internal/cryptlib.h" #include <openssl/evp.h> @@ -511,6 +512,18 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx, 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) + * We must ensure that this amount of data, plus the one block that + * we process from ctx->buf does not exceed INT_MAX + */ + if (((inl - j) & ~(bl - 1)) > INT_MAX - bl) { + ERR_raise(ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW); + return 0; + } memcpy(&(ctx->buf[i]), in, j); inl -= j; in += j; @@ -771,6 +784,19 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, ERR_raise(ERR_LIB_EVP, EVP_R_PARTIALLY_OVERLAPPING); return 0; } + /* + * final_used is only ever set if buf_len is 0. Therefore the maximum + * length output we will ever see from evp_EncryptDecryptUpdate is + * the maximum multiple of the block length that is <= inl, or just: + * inl & ~(b - 1) + * Since final_used has been set then the final output length is: + * (inl & ~(b - 1)) + b + * This must never exceed INT_MAX + */ + if ((inl & ~(b - 1)) > INT_MAX - b) { + ERR_raise(ERR_LIB_EVP, EVP_R_OUTPUT_WOULD_OVERFLOW); + return 0; + } memcpy(out, ctx->final, b); out += b; fix_len = 1; |