chacha20: Properly reinitialize the cipher context with NULL key
authorTomas Mraz <tmraz@fedoraproject.org>
Tue, 12 Jan 2021 15:53:33 +0000 (16:53 +0100)
committerTomas Mraz <tmraz@fedoraproject.org>
Wed, 13 Jan 2021 17:04:28 +0000 (18:04 +0100)
Same for chacha20-poly1305.

The test_cipher_reinit and test_cipher_reinit_partialupdate is modified
to test this case of cipher context reinitialization.

Fixes #13064

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13850)

providers/implementations/ciphers/cipher_chacha20_hw.c
providers/implementations/ciphers/cipher_chacha20_poly1305_hw.c
test/evp_libctx_test.c

index 06cb6b12d3a85d48e90582282d63f4f2c624e70e..4ce4af09066486b5ec431d2a810cf7908c4ce634 100644 (file)
@@ -34,6 +34,7 @@ static int chacha20_initiv(PROV_CIPHER_CTX *bctx)
         for (i = 0; i < CHACHA_CTR_SIZE; i += 4)
             ctx->counter[i / 4] = CHACHA_U8TOU32(bctx->oiv + i);
     }
+    ctx->partial_len = 0;
     return 1;
 }
 
index 65f0fe1ee88016febfac484c1b92a80d1ca9cb7d..55a57de7264f1bde1e00099a69385eb2215308c4 100644 (file)
@@ -79,6 +79,12 @@ static int chacha20_poly1305_initiv(PROV_CIPHER_CTX *bctx)
     unsigned char tempiv[CHACHA_CTR_SIZE] = { 0 };
     int ret = 1;
 
+    ctx->len.aad = 0;
+    ctx->len.text = 0;
+    ctx->aad = 0;
+    ctx->mac_inited = 0;
+    ctx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+
         /* pad on the left */
     if (ctx->nonce_len <= CHACHA_CTR_SIZE) {
             memcpy(tempiv + CHACHA_CTR_SIZE - ctx->nonce_len, bctx->oiv,
index c306bd9a16874813631f3e8fa70823bb2ed21af8..66d2d4cddb792dde84807e10c2f58550626b8859 100644 (file)
@@ -295,11 +295,13 @@ err:
 
 static int test_cipher_reinit(int test_id)
 {
-    int ret = 0, out1_len = 0, out2_len = 0, diff, ccm;
+    int ret = 0, diff, ccm, siv;
+    int out1_len = 0, out2_len = 0, out3_len = 0;
     EVP_CIPHER *cipher = NULL;
     EVP_CIPHER_CTX *ctx = NULL;
     unsigned char out1[256];
     unsigned char out2[256];
+    unsigned char out3[256];
     unsigned char in[16] = {
         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
         0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
@@ -330,6 +332,9 @@ static int test_cipher_reinit(int test_id)
     /* ccm fails on the second update - this matches OpenSSL 1_1_1 behaviour */
     ccm = (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE);
 
+    /* siv cannot be called with NULL key as the iv is irrelevant */
+    siv = (EVP_CIPHER_mode(cipher) == EVP_CIPH_SIV_MODE);
+
     /* DES3-WRAP uses random every update - so it will give a different value */
     diff = EVP_CIPHER_is_a(cipher, "DES3-WRAP");
 
@@ -337,15 +342,21 @@ static int test_cipher_reinit(int test_id)
         || !TEST_true(EVP_EncryptUpdate(ctx, out1, &out1_len, in, sizeof(in)))
         || !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
         || !TEST_int_eq(EVP_EncryptUpdate(ctx, out2, &out2_len, in, sizeof(in)),
-                        ccm ? 0 : 1))
+                        ccm ? 0 : 1)
+        || !TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
+        || !TEST_int_eq(EVP_EncryptUpdate(ctx, out3, &out3_len, in, sizeof(in)),
+                        ccm || siv ? 0 : 1))
         goto err;
 
     if (ccm == 0) {
         if (diff) {
-            if (!TEST_mem_ne(out1, out1_len, out2, out2_len))
+            if (!TEST_mem_ne(out1, out1_len, out2, out2_len)
+                || !TEST_mem_ne(out1, out1_len, out3, out3_len)
+                || !TEST_mem_ne(out2, out2_len, out3, out3_len))
                 goto err;
         } else {
-            if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
+            if (!TEST_mem_eq(out1, out1_len, out2, out2_len)
+                || (!siv && !TEST_mem_eq(out1, out1_len, out3, out3_len)))
                 goto err;
         }
     }
@@ -364,11 +375,13 @@ err:
  */
 static int test_cipher_reinit_partialupdate(int test_id)
 {
-    int ret = 0, out1_len = 0, out2_len = 0, in_len;
+    int ret = 0, in_len;
+    int out1_len = 0, out2_len = 0, out3_len = 0;
     EVP_CIPHER *cipher = NULL;
     EVP_CIPHER_CTX *ctx = NULL;
     unsigned char out1[256];
     unsigned char out2[256];
+    unsigned char out3[256];
     static const unsigned char in[32] = {
         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
         0xba, 0xbe, 0xba, 0xbe, 0x00, 0x00, 0xba, 0xbe,
@@ -416,12 +429,15 @@ static int test_cipher_reinit_partialupdate(int test_id)
         || !TEST_true(EVP_EncryptUpdate(ctx, out2, &out2_len, in, in_len)))
         goto err;
 
-    /* DES3-WRAP uses random every update - so it will give a different value */
-    if (EVP_CIPHER_is_a(cipher, "DES3-WRAP")) {
-        if (!TEST_mem_ne(out1, out1_len, out2, out2_len))
+    if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
+        goto err;
+
+    if (EVP_CIPHER_mode(cipher) != EVP_CIPH_SIV_MODE) {
+        if (!TEST_true(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv))
+            || !TEST_true(EVP_EncryptUpdate(ctx, out3, &out3_len, in, in_len)))
             goto err;
-    } else {
-        if (!TEST_mem_eq(out1, out1_len, out2, out2_len))
+
+        if (!TEST_mem_eq(out1, out1_len, out3, out3_len))
             goto err;
     }
     ret = 1;