From 420cb707b880e4fb649094241371701013eeb15f Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 5 Apr 2019 01:22:14 +0200 Subject: [PATCH] EVP_*Update: ensure that input NULL with length 0 isn't passed Even with custom ciphers, the combination in == NULL && inl == 0 should not be passed down to the backend cipher function. The reason is that these are the values passed by EVP_*Final, and some of the backend cipher functions do check for these to see if a "final" call is made. An exception is made for CCM mode which has special handling for the case where inl == 0: this may mean the total plaintext or ciphertext length is 0. This is based on an original commit by Richard Levitte. Fixes #8675 Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/9057) --- crypto/evp/evp_enc.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 08bd209dd8..b9b6490fe0 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -305,6 +305,17 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx, bl = ctx->cipher->block_size; + /* + * CCM mode needs to know about the case where inl == 0 && in == NULL - it + * means the plaintext/ciphertext length is 0 + */ + if (inl < 0 + || (inl == 0 + && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)) { + *outl = 0; + return inl == 0; + } + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { /* If block size > 1 then the cipher will have to do this check */ if (bl == 1 && is_partially_overlapping(out, in, cmpl)) { @@ -320,10 +331,6 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx, return 1; } - if (inl <= 0) { - *outl = 0; - return inl == 0; - } if (is_partially_overlapping(out + ctx->buf_len, in, cmpl)) { EVPerr(EVP_F_EVP_ENCRYPTDECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); return 0; @@ -457,6 +464,17 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) cmpl = (cmpl + 7) / 8; + /* + * CCM mode needs to know about the case where inl == 0 - it means the + * plaintext/ciphertext length is 0 + */ + if (inl < 0 + || (inl == 0 + && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)) { + *outl = 0; + return inl == 0; + } + if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { if (b == 1 && is_partially_overlapping(out, in, cmpl)) { EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); @@ -472,11 +490,6 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, return 1; } - if (inl <= 0) { - *outl = 0; - return inl == 0; - } - if (ctx->flags & EVP_CIPH_NO_PADDING) return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl); -- 2.25.1