[openssl] OpenSSL_1_1_1-stable update

Matt Caswell matt at openssl.org
Fri Nov 29 11:12:21 UTC 2019


The branch OpenSSL_1_1_1-stable has been updated
       via  dbcf53f867146766845f6e64243208d87007f970 (commit)
       via  420cb707b880e4fb649094241371701013eeb15f (commit)
      from  aeb8d94b6bd2bfa4da2681d4609956607aa9ed7a (commit)


- Log -----------------------------------------------------------------
commit dbcf53f867146766845f6e64243208d87007f970
Author: Matt Caswell <matt at openssl.org>
Date:   Fri May 31 14:32:55 2019 +0100

    Add a test for NULL chunks in encrypt/decrypt
    
    Issue #8675 describes a problem where calling EVP_DecryptUpdate() with an
    empty chunk causes the result to be different compared to if you do not
    use an empty chunk. This adds a test for that case.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9057)

commit 420cb707b880e4fb649094241371701013eeb15f
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 5 01:22:14 2019 +0200

    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 <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9057)

-----------------------------------------------------------------------

Summary of changes:
 crypto/evp/evp_enc.c  | 31 ++++++++++++++++-------
 test/evp_extra_test.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 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);
 
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 88aba1a4ac..b9caa30d2e 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -1069,6 +1069,72 @@ done:
 }
 #endif
 
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+static int test_decrypt_null_chunks(void)
+{
+    EVP_CIPHER_CTX* ctx = NULL;
+    const unsigned char key[32] = {
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+        0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1
+    };
+    unsigned char iv[12] = {
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
+    };
+    unsigned char msg[] = "It was the best of times, it was the worst of times";
+    unsigned char ciphertext[80];
+    unsigned char plaintext[80];
+    /* We initialise tmp to a non zero value on purpose */
+    int ctlen, ptlen, tmp = 99;
+    int ret = 0;
+    const int enc_offset = 10, dec_offset = 20;
+
+    if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+            || !TEST_true(EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL,
+                                             key, iv))
+            || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext, &ctlen, msg,
+                                            enc_offset))
+            /* Deliberate add a zero length update */
+            || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext + ctlen, &tmp, NULL,
+                                            0))
+            || !TEST_int_eq(tmp, 0)
+            || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext + ctlen, &tmp,
+                                            msg + enc_offset,
+                                            sizeof(msg) - enc_offset))
+            || !TEST_int_eq(ctlen += tmp, sizeof(msg))
+            || !TEST_true(EVP_EncryptFinal(ctx, ciphertext + ctlen, &tmp))
+            || !TEST_int_eq(tmp, 0))
+        goto err;
+
+    /* Deliberately initialise tmp to a non zero value */
+    tmp = 99;
+    if (!TEST_true(EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, key,
+                                      iv))
+            || !TEST_true(EVP_DecryptUpdate(ctx, plaintext, &ptlen, ciphertext,
+                                            dec_offset))
+            /*
+             * Deliberately add a zero length update. We also deliberately do
+             * this at a different offset than for encryption.
+             */
+            || !TEST_true(EVP_DecryptUpdate(ctx, plaintext + ptlen, &tmp, NULL,
+                                            0))
+            || !TEST_int_eq(tmp, 0)
+            || !TEST_true(EVP_DecryptUpdate(ctx, plaintext + ptlen, &tmp,
+                                            ciphertext + dec_offset,
+                                            ctlen - dec_offset))
+            || !TEST_int_eq(ptlen += tmp, sizeof(msg))
+            || !TEST_true(EVP_DecryptFinal(ctx, plaintext + ptlen, &tmp))
+            || !TEST_int_eq(tmp, 0)
+            || !TEST_mem_eq(msg, sizeof(msg), plaintext, ptlen))
+        goto err;
+
+    ret = 1;
+ err:
+    EVP_CIPHER_CTX_free(ctx);
+    return ret;
+}
+#endif /* !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) */
+
 int setup_tests(void)
 {
     ADD_TEST(test_EVP_DigestSignInit);
@@ -1097,6 +1163,9 @@ int setup_tests(void)
     ADD_TEST(test_X509_PUBKEY_inplace);
     ADD_ALL_TESTS(test_invalide_ec_char2_pub_range_decode,
                   OSSL_NELEM(ec_der_pub_keys));
+#endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+    ADD_TEST(test_decrypt_null_chunks);
 #endif
     return 1;
 }


More information about the openssl-commits mailing list