Commit d29c165122 for openssl.org
commit d29c165122bd480ca736a3eeb21d88a6b433ead3
Author: Pranavjeet-Naidu <pranavjeetnaidu@gmail.com>
Date: Wed Mar 25 05:15:30 2026 +0530
Add negative length validation in EVP_EncryptUpdate and EVP_DecryptUpdate
Added input length validation checks to prevent potential security issues
when negative values are passed to EVP_EncryptUpdate and EVP_DecryptUpdate.
These functions cast inl (int) to size_t without validation, which could lead
to unexpectedly large buffer allocation attempts or unintended behavior with
negative inputs.
Validation is performed early in both functions to ensure only valid,
non-negative lengths are processed. Error is reported via EVP_R_INVALID_LENGTH.
Fixes: https://github.com/openssl/openssl/issues/30486
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
MergeDate: Tue Mar 31 02:10:52 2026
(Merged from https://github.com/openssl/openssl/pull/30560)
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 1be9508ac6..9c27b240bd 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -654,6 +654,11 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
size_t soutl, inl_ = (size_t)inl;
int blocksize;
+ if (inl < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
+ return 0;
+ }
+
if (ossl_likely(outl != NULL)) {
*outl = 0;
} else {
@@ -760,6 +765,11 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
size_t soutl, inl_ = (size_t)inl;
int blocksize;
+ if (inl < 0) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
+ return 0;
+ }
+
if (ossl_likely(outl != NULL)) {
*outl = 0;
} else {
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index b975b68f7e..3dba83c273 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -6131,6 +6131,45 @@ static int test_invalid_ctx_for_digest(void)
return ret;
}
+static int test_evp_cipher_negative_length(void)
+{
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+ unsigned char key[16] = { 0 };
+ unsigned char iv[16] = { 0 };
+ unsigned char buffer[32] = { 0 };
+ int outl = 0;
+ int ret = 0;
+
+ if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()))
+ goto end;
+
+ if (!TEST_ptr(cipher = EVP_CIPHER_fetch(testctx, "AES-128-CBC", testpropq)))
+ goto end;
+
+ /* Initialize encryption context */
+ if (!TEST_int_eq(EVP_EncryptInit_ex2(ctx, cipher, key, iv, NULL), 1))
+ goto end;
+
+ /* Test EVP_EncryptUpdate with negative length - should fail */
+ if (!TEST_int_eq(EVP_EncryptUpdate(ctx, buffer, &outl, (unsigned char *)"test", -1), 0))
+ goto end;
+
+ /* Reinitialize for decryption */
+ if (!TEST_int_eq(EVP_DecryptInit_ex2(ctx, cipher, key, iv, NULL), 1))
+ goto end;
+
+ /* Test EVP_DecryptUpdate with negative length - should fail */
+ if (!TEST_int_eq(EVP_DecryptUpdate(ctx, buffer, &outl, (unsigned char *)"test", -1), 0))
+ goto end;
+
+ ret = 1;
+end:
+ EVP_CIPHER_free(cipher);
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+}
+
static int test_evp_cipher_pipeline(void)
{
OSSL_PROVIDER *fake_pipeline = NULL;
@@ -6869,6 +6908,8 @@ int setup_tests(void)
ADD_TEST(test_invalid_ctx_for_digest);
+ ADD_TEST(test_evp_cipher_negative_length);
+
ADD_TEST(test_evp_cipher_pipeline);
#ifndef OPENSSL_NO_ML_KEM