Fix CTS cipher decrypt so that the updated IV is returned correctly.
authorShane Lontis <shane.lontis@oracle.com>
Fri, 13 Aug 2021 04:36:21 +0000 (14:36 +1000)
committerPauli <pauli@openssl.org>
Tue, 17 Aug 2021 22:38:40 +0000 (08:38 +1000)
Adding KRB5 test vector 'NextIV' values to evp_test data for AES CTS indicated that the CTS decrypt functions incorrectly returned the wrong IV. The returned IV should match the value returned by the encrypt methods.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16286)

providers/implementations/ciphers/cipher_cts.c
test/recipes/30-test_evp_data/evpciph_aes_cts.txt

index 5732ae199041c9d4465b289371928afbb65633c1..cb3372c646aab28356befa529a26afa13ddbeb69 100644 (file)
@@ -135,7 +135,7 @@ static void do_xor(const unsigned char *in1, const unsigned char *in2,
 static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
                                  unsigned char *out, size_t len)
 {
 static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
                                  unsigned char *out, size_t len)
 {
-    aligned_16bytes mid_iv, ct_mid, pt_last;
+    aligned_16bytes mid_iv, ct_mid, cn, pt_last;
     size_t residue;
 
     residue = len % CTS_BLOCK_SIZE;
     size_t residue;
 
     residue = len % CTS_BLOCK_SIZE;
@@ -155,6 +155,8 @@ static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
     }
     /* Save the iv that will be used by the second last block */
     memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
     }
     /* Save the iv that will be used by the second last block */
     memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
+    /* Save the C(n) block */
+    memcpy(cn.c, in + residue, CTS_BLOCK_SIZE);
 
     /* Decrypt the last block first using an iv of zero */
     memset(ctx->iv, 0, CTS_BLOCK_SIZE);
 
     /* Decrypt the last block first using an iv of zero */
     memset(ctx->iv, 0, CTS_BLOCK_SIZE);
@@ -179,6 +181,7 @@ static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
 
     /* Restore the iv needed by the second last block */
     memcpy(ctx->iv, mid_iv.c, CTS_BLOCK_SIZE);
 
     /* Restore the iv needed by the second last block */
     memcpy(ctx->iv, mid_iv.c, CTS_BLOCK_SIZE);
+
     /*
      * Decrypt the second last plaintext block now that we have rebuilt the
      * ciphertext.
     /*
      * Decrypt the second last plaintext block now that we have rebuilt the
      * ciphertext.
@@ -186,6 +189,8 @@ static size_t cts128_cs1_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
     if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
         return 0;
 
     if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
         return 0;
 
+    /* The returned iv is the C(n) block */
+    memcpy(ctx->iv, cn.c, CTS_BLOCK_SIZE);
     return len + CTS_BLOCK_SIZE + residue;
 }
 
     return len + CTS_BLOCK_SIZE + residue;
 }
 
@@ -232,7 +237,7 @@ static size_t cts128_cs3_encrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
 static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
                                  unsigned char *out, size_t len)
 {
 static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
                                  unsigned char *out, size_t len)
 {
-    aligned_16bytes mid_iv, ct_mid, pt_last;
+    aligned_16bytes mid_iv, ct_mid, cn, pt_last;
     size_t residue;
 
     if (len < CTS_BLOCK_SIZE) /* CS3 requires at least one block */
     size_t residue;
 
     if (len < CTS_BLOCK_SIZE) /* CS3 requires at least one block */
@@ -256,8 +261,10 @@ static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
     }
     /* Save the iv that will be used by the second last block */
     memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
     }
     /* Save the iv that will be used by the second last block */
     memcpy(mid_iv.c, ctx->iv, CTS_BLOCK_SIZE);
+    /* Save the C(n) block : For CS3 it is C(1)||...||C(n-2)||C(n)||C(n-1)* */
+    memcpy(cn.c, in, CTS_BLOCK_SIZE);
 
 
-    /* Decrypt the Cn block first using an iv of zero */
+    /* Decrypt the C(n) block first using an iv of zero */
     memset(ctx->iv, 0, CTS_BLOCK_SIZE);
     if (!ctx->hw->cipher(ctx, pt_last.c, in, CTS_BLOCK_SIZE))
         return 0;
     memset(ctx->iv, 0, CTS_BLOCK_SIZE);
     if (!ctx->hw->cipher(ctx, pt_last.c, in, CTS_BLOCK_SIZE))
         return 0;
@@ -288,6 +295,8 @@ static size_t cts128_cs3_decrypt(PROV_CIPHER_CTX *ctx, const unsigned char *in,
     if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
         return 0;
 
     if (!ctx->hw->cipher(ctx, out, ct_mid.c, CTS_BLOCK_SIZE))
         return 0;
 
+    /* The returned iv is the C(n) block */
+    memcpy(ctx->iv, cn.c, CTS_BLOCK_SIZE);
     return len + CTS_BLOCK_SIZE + residue;
 }
 
     return len + CTS_BLOCK_SIZE + residue;
 }
 
index bd0f5ce75152976f13734f95ee7da9bcfd4fe9bb..106eec403f0364db358407dca6b22b6e12329a39 100644 (file)
@@ -48,6 +48,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b652074686520
 Ciphertext = 97c6353568f2bf8cb4d8a580362da7ff7f
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b652074686520
 Ciphertext = 97c6353568f2bf8cb4d8a580362da7ff7f
+NextIV = c6353568f2bf8cb4d8a580362da7ff7f
 
 # 31 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 31 bytes input
 Cipher = AES-128-CBC-CTS
@@ -56,6 +57,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe5fc00783e0efdb2c1d445d4c8eff7ed22
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe5fc00783e0efdb2c1d445d4c8eff7ed22
+NextIV = fc00783e0efdb2c1d445d4c8eff7ed22
 
 # 32 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 32 bytes input
 Cipher = AES-128-CBC-CTS
@@ -64,6 +66,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c2047617527732043
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a8
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c2047617527732043
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a8
+NextIV = 39312523a78662d5be7fcbcc98ebf5a8
 
 # 47 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 47 bytes input
 Cipher = AES-128-CBC-CTS
@@ -71,6 +74,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5b3fffd940c16a18c1b5549d2f838029e
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5b3fffd940c16a18c1b5549d2f838029e
+NextIV = b3fffd940c16a18c1b5549d2f838029e
 
 # 64 bytes input (CS1 is equivalent to CBC when the last block in full)
 Cipher = AES-128-CBC-CTS
 
 # 64 bytes input (CS1 is equivalent to CBC when the last block in full)
 Cipher = AES-128-CBC-CTS
@@ -79,6 +83,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20616e6420776f6e746f6e20736f75702e
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a89dad8bbb96c4cdc03bc103e1a194bbd84807efe836ee89a526730dbc2f7bc840
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20616e6420776f6e746f6e20736f75702e
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a89dad8bbb96c4cdc03bc103e1a194bbd84807efe836ee89a526730dbc2f7bc840
+NextIV = 4807efe836ee89a526730dbc2f7bc840
 
 #-------------------------------------------------------------------------------
 # Generated test values using an IV.
 
 #-------------------------------------------------------------------------------
 # Generated test values using an IV.
@@ -159,6 +164,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b652074686520
 Ciphertext = c6353568f2bf8cb4d8a580362da7ff7f97
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b652074686520
 Ciphertext = c6353568f2bf8cb4d8a580362da7ff7f97
+NextIV = c6353568f2bf8cb4d8a580362da7ff7f
 
 # 31 bytes input (For partial blocks the output should match CS3)
 Cipher = AES-128-CBC-CTS
 
 # 31 bytes input (For partial blocks the output should match CS3)
 Cipher = AES-128-CBC-CTS
@@ -167,6 +173,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320
 Ciphertext = fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320
 Ciphertext = fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5
+NextIV = fc00783e0efdb2c1d445d4c8eff7ed22
 
 # 32 bytes input (Aligned blocks should match normal CBC mode)
 Cipher = AES-128-CBC-CTS
 
 # 32 bytes input (Aligned blocks should match normal CBC mode)
 Cipher = AES-128-CBC-CTS
@@ -175,6 +182,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c2047617527732043
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a8
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c2047617527732043
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a8
+NextIV = 39312523a78662d5be7fcbcc98ebf5a8
 
 # 47 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 47 bytes input
 Cipher = AES-128-CBC-CTS
@@ -183,6 +191,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe584b3fffd940c16a18c1b5549d2f838029e39312523a78662d5be7fcbcc98ebf5
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe584b3fffd940c16a18c1b5549d2f838029e39312523a78662d5be7fcbcc98ebf5
+NextIV = b3fffd940c16a18c1b5549d2f838029e
 
 # 64 bytes input (CS2 is equivalent to CBC when the last block in full)
 Cipher = AES-128-CBC-CTS
 
 # 64 bytes input (CS2 is equivalent to CBC when the last block in full)
 Cipher = AES-128-CBC-CTS
@@ -191,6 +200,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20616e6420776f6e746f6e20736f75702e
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a89dad8bbb96c4cdc03bc103e1a194bbd84807efe836ee89a526730dbc2f7bc840
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20616e6420776f6e746f6e20736f75702e
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a89dad8bbb96c4cdc03bc103e1a194bbd84807efe836ee89a526730dbc2f7bc840
+NextIV = 4807efe836ee89a526730dbc2f7bc840
 
 # Generated test values using an IV.
 
 
 # Generated test values using an IV.
 
@@ -236,6 +246,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b652074686520
 Ciphertext = c6353568f2bf8cb4d8a580362da7ff7f97
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b652074686520
 Ciphertext = c6353568f2bf8cb4d8a580362da7ff7f97
+NextIV = c6353568f2bf8cb4d8a580362da7ff7f
 
 # 31 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 31 bytes input
 Cipher = AES-128-CBC-CTS
@@ -244,6 +255,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320
 Ciphertext = fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320
 Ciphertext = fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5
+NextIV = fc00783e0efdb2c1d445d4c8eff7ed22
 
 # 32 bytes input (CS3 always swaps the last 2 byte blocks - so it is not equivalent to CBC for a full block)
 Cipher = AES-128-CBC-CTS
 
 # 32 bytes input (CS3 always swaps the last 2 byte blocks - so it is not equivalent to CBC for a full block)
 Cipher = AES-128-CBC-CTS
@@ -252,6 +264,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c2047617527732043
 Ciphertext = 39312523a78662d5be7fcbcc98ebf5a897687268d6ecccc0c07b25e25ecfe584
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c2047617527732043
 Ciphertext = 39312523a78662d5be7fcbcc98ebf5a897687268d6ecccc0c07b25e25ecfe584
+NextIV = 39312523a78662d5be7fcbcc98ebf5a8
 
 # 47 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 47 bytes input
 Cipher = AES-128-CBC-CTS
@@ -260,6 +273,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe584b3fffd940c16a18c1b5549d2f838029e39312523a78662d5be7fcbcc98ebf5
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe584b3fffd940c16a18c1b5549d2f838029e39312523a78662d5be7fcbcc98ebf5
+NextIV = b3fffd940c16a18c1b5549d2f838029e
 
 # 48 bytes input
 Cipher = AES-128-CBC-CTS
 
 # 48 bytes input
 Cipher = AES-128-CBC-CTS
@@ -268,6 +282,7 @@ Key = 636869636b656e207465726979616b69
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe5849dad8bbb96c4cdc03bc103e1a194bbd839312523a78662d5be7fcbcc98ebf5a8
 IV = 00000000000000000000000000000000
 Plaintext = 4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20
 Ciphertext = 97687268d6ecccc0c07b25e25ecfe5849dad8bbb96c4cdc03bc103e1a194bbd839312523a78662d5be7fcbcc98ebf5a8
+NextIV = 9dad8bbb96c4cdc03bc103e1a194bbd8
 
 # 64 bytes input (CS3 always swaps the last 2 byte blocks - so it is not equivalent to CBC for a full block)
 Cipher = AES-128-CBC-CTS
 
 # 64 bytes input (CS3 always swaps the last 2 byte blocks - so it is not equivalent to CBC for a full block)
 Cipher = AES-128-CBC-CTS