[PATCH 1/2] tests/basic: enable IV checks for CBC/CFB/CTR bulk tests

Jussi Kivilinna jussi.kivilinna at iki.fi
Tue Jun 28 11:20:14 CEST 2022


* cipher/cipher.c (_gcry_cipher_ctl): Add handling for
'PRIV_CIPHERCTL_GET_COUNTER'.
* src/gcrypt-testapi.h (PRIV_CIPHERCTL_GET_COUNTER): New.
* tests/basic.c (cipher_cbc_bulk_test, cipher_cfb_bulk_test): Restore
IV checks by reading current IV from CBC/CFB cipher handle using
PRIV_CIPHERCTL_GET_INPUT_VECTOR.
(cipher_ctr_bulk_test): Restore counter checks by reading current
counter from CTR cipher handle using PRIV_CIPHERCTL_GET_COUNTER.
---

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 cipher/cipher.c      |  24 ++++
 src/gcrypt-testapi.h |   1 +
 tests/basic.c        | 263 +++++++++++++++++++++++++++----------------
 3 files changed, 192 insertions(+), 96 deletions(-)

diff --git a/cipher/cipher.c b/cipher/cipher.c
index d1443a62..9e850470 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1651,6 +1651,30 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
         }
       break;
 
+    case PRIV_CIPHERCTL_GET_COUNTER: /* (private)  */
+      /* This is the input block as used in CTR mode which has
+         initially been set as IV.  The returned format is:
+           1 byte  Actual length of the block in bytes.
+           n byte  The block.
+         If the provided buffer is too short, an error is returned. */
+      if (buflen < (1 + h->spec->blocksize))
+        rc = GPG_ERR_TOO_SHORT;
+      else
+        {
+          unsigned char *ctrp;
+          unsigned char *dst = buffer;
+          int n = h->unused;
+
+          if (!n)
+            n = h->spec->blocksize;
+          gcry_assert (n <= h->spec->blocksize);
+          *dst++ = n;
+          ctrp = h->u_ctr.ctr + h->spec->blocksize - n;
+          while (n--)
+            *dst++ = *ctrp++;
+        }
+      break;
+
     case GCRYCTL_SET_SBOX:
       if (h->spec->set_extra_info)
         rc = h->spec->set_extra_info
diff --git a/src/gcrypt-testapi.h b/src/gcrypt-testapi.h
index 0417754f..f5608084 100644
--- a/src/gcrypt-testapi.h
+++ b/src/gcrypt-testapi.h
@@ -41,6 +41,7 @@
 /* For use with gcry_cipher_ctl:  */
 #define PRIV_CIPHERCTL_DISABLE_WEAK_KEY   61
 #define PRIV_CIPHERCTL_GET_INPUT_VECTOR   62
+#define PRIV_CIPHERCTL_GET_COUNTER        63
 
 
 /* Private interfaces for testing of random-drbg.c. */
diff --git a/tests/basic.c b/tests/basic.c
index ab00667e..05934891 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -36,6 +36,7 @@
 #endif
 
 #include "../src/gcrypt-int.h"
+#include "../src/gcrypt-testapi.h"
 
 #define PGM "basic"
 #include "t-common.h"
@@ -11717,6 +11718,7 @@ cipher_cbc_bulk_test (int cipher_algo)
   gcry_cipher_hd_t hd_cbc;
   gcry_error_t err = 0;
   unsigned char *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
+  unsigned char *getivbuf;
   unsigned int memsize;
   unsigned int keylen;
 
@@ -11740,7 +11742,7 @@ cipher_cbc_bulk_test (int cipher_algo)
       return -1;
     }
 
-  memsize = (blocksize * 2) + (blocksize * nblocks * 3) + 16;
+  memsize = (blocksize * 2) + (blocksize * nblocks * 3) + 16 + (blocksize + 1);
 
   mem = xcalloc (1, memsize);
   if (!mem)
@@ -11752,6 +11754,7 @@ cipher_cbc_bulk_test (int cipher_algo)
   plaintext = iv2 + blocksize;
   plaintext2 = plaintext + nblocks * blocksize;
   ciphertext = plaintext2 + nblocks * blocksize;
+  getivbuf = ciphertext + nblocks * blocksize;
 
   err = gcry_cipher_open (&hd_one, cipher_algo, GCRY_CIPHER_MODE_ECB, 0);
   if (err)
@@ -11830,8 +11833,17 @@ cipher_cbc_bulk_test (int cipher_algo)
       return -1;
     }
 
-#if 0 /* missing interface for reading IV */
-  if (memcmp (iv2, iv, blocksize))
+  err = gcry_cipher_ctl (hd_cbc, PRIV_CIPHERCTL_GET_INPUT_VECTOR, getivbuf,
+			 blocksize + 1);
+  if (err || getivbuf[0] != blocksize)
+    {
+      gcry_cipher_close (hd_one);
+      gcry_cipher_close (hd_cbc);
+      xfree(mem);
+      fail ("%s-CBC-%d test failed (CBC getiv fail)", cipher, blocksize * 8);
+      return -1;
+    }
+  if (memcmp (getivbuf + 1, iv, blocksize))
     {
       gcry_cipher_close (hd_one);
       gcry_cipher_close (hd_cbc);
@@ -11839,7 +11851,6 @@ cipher_cbc_bulk_test (int cipher_algo)
       fail ("%s-CBC-%d test failed (IV mismatch)", cipher, blocksize * 8);
       return -1;
     }
-#endif
 
   /* Test parallelized code paths */
   memset (iv, 0x5f, blocksize);
@@ -11895,8 +11906,18 @@ cipher_cbc_bulk_test (int cipher_algo)
             cipher, blocksize * 8);
       return -1;
     }
-#if 0 /* missing interface for reading IV */
-  if (memcmp (iv2, iv, blocksize))
+  err = gcry_cipher_ctl (hd_cbc, PRIV_CIPHERCTL_GET_INPUT_VECTOR, getivbuf,
+			 blocksize + 1);
+  if (err || getivbuf[0] != blocksize)
+    {
+      gcry_cipher_close (hd_one);
+      gcry_cipher_close (hd_cbc);
+      xfree(mem);
+      fail ("%s-CBC-%d test failed (CBC getiv fail, parallel path)",
+	    cipher, blocksize * 8);
+      return -1;
+    }
+  if (memcmp (getivbuf + 1, iv, blocksize))
     {
       gcry_cipher_close (hd_one);
       gcry_cipher_close (hd_cbc);
@@ -11905,7 +11926,6 @@ cipher_cbc_bulk_test (int cipher_algo)
             cipher, blocksize * 8);
       return -1;
     }
-#endif
 
   gcry_cipher_close (hd_one);
   gcry_cipher_close (hd_cbc);
@@ -11938,6 +11958,7 @@ cipher_cfb_bulk_test (int cipher_algo)
   gcry_error_t err = 0;
   int i, offs;
   unsigned char *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
+  unsigned char *getivbuf;
   unsigned int memsize;
   unsigned int keylen;
 
@@ -11961,7 +11982,7 @@ cipher_cfb_bulk_test (int cipher_algo)
       return -1;
     }
 
-  memsize = (blocksize * 2) + (blocksize * nblocks * 3) + 16;
+  memsize = (blocksize * 2) + (blocksize * nblocks * 3) + 16 + (blocksize + 1);
 
   mem = xcalloc (1, memsize);
   if (!mem)
@@ -11973,6 +11994,7 @@ cipher_cfb_bulk_test (int cipher_algo)
   plaintext = iv2 + blocksize;
   plaintext2 = plaintext + nblocks * blocksize;
   ciphertext = plaintext2 + nblocks * blocksize;
+  getivbuf = ciphertext + nblocks * blocksize;
 
   err = gcry_cipher_open (&hd_one, cipher_algo, GCRY_CIPHER_MODE_ECB, 0);
   if (err)
@@ -12049,8 +12071,17 @@ cipher_cfb_bulk_test (int cipher_algo)
       return -1;
     }
 
-#if 0
-  if (memcmp(iv2, iv, blocksize))
+  err = gcry_cipher_ctl (hd_cfb, PRIV_CIPHERCTL_GET_INPUT_VECTOR, getivbuf,
+			 blocksize + 1);
+  if (err || getivbuf[0] != blocksize)
+    {
+      gcry_cipher_close (hd_one);
+      gcry_cipher_close (hd_cfb);
+      xfree(mem);
+      fail ("%s-CFB-%d test failed (CFB getiv fail)", cipher, blocksize * 8);
+      return -1;
+    }
+  if (memcmp(getivbuf + 1, iv, blocksize))
     {
       gcry_cipher_close (hd_one);
       gcry_cipher_close (hd_cfb);
@@ -12059,7 +12090,6 @@ cipher_cfb_bulk_test (int cipher_algo)
             cipher, blocksize * 8);
       return -1;
     }
-#endif
 
   /* Test parallelized code paths */
   memset(iv, 0xe6, blocksize);
@@ -12114,8 +12144,19 @@ cipher_cfb_bulk_test (int cipher_algo)
             cipher, blocksize * 8);
       return -1;
     }
-#if 0
-  if (memcmp(iv2, iv, blocksize))
+
+  err = gcry_cipher_ctl (hd_cfb, PRIV_CIPHERCTL_GET_INPUT_VECTOR, getivbuf,
+			 blocksize + 1);
+  if (err || getivbuf[0] != blocksize)
+    {
+      gcry_cipher_close (hd_one);
+      gcry_cipher_close (hd_cfb);
+      xfree(mem);
+      fail ("%s-CFB-%d test failed (CFB getiv fail, parallel path)",
+	    cipher, blocksize * 8);
+      return -1;
+    }
+  if (memcmp(getivbuf + 1, iv, blocksize))
     {
       gcry_cipher_close (hd_one);
       gcry_cipher_close (hd_cfb);
@@ -12124,7 +12165,6 @@ cipher_cfb_bulk_test (int cipher_algo)
             cipher, blocksize * 8);
       return -1;
     }
-#endif
 
   gcry_cipher_close (hd_one);
   gcry_cipher_close (hd_cfb);
@@ -12147,6 +12187,7 @@ cipher_ctr_bulk_test (int cipher_algo)
   int i, j, offs, diff;
   unsigned char *plaintext, *plaintext2, *ciphertext, *ciphertext2,
                 *iv, *iv2, *mem;
+  unsigned char *getctrbuf;
   unsigned int memsize;
   unsigned int keylen;
 
@@ -12170,7 +12211,7 @@ cipher_ctr_bulk_test (int cipher_algo)
       return -1;
     }
 
-  memsize = (blocksize * 2) + (blocksize * nblocks * 4) + 16;
+  memsize = (blocksize * 2) + (blocksize * nblocks * 4) + 16 + (blocksize + 1);
 
   mem = xcalloc (1, memsize);
   if (!mem)
@@ -12183,6 +12224,7 @@ cipher_ctr_bulk_test (int cipher_algo)
   plaintext2 = plaintext + nblocks * blocksize;
   ciphertext = plaintext2 + nblocks * blocksize;
   ciphertext2 = ciphertext + nblocks * blocksize;
+  getctrbuf = ciphertext2 + nblocks * blocksize;
 
   err = gcry_cipher_open (&hd_one, cipher_algo, GCRY_CIPHER_MODE_ECB, 0);
   if (err)
@@ -12266,8 +12308,17 @@ cipher_ctr_bulk_test (int cipher_algo)
       return -1;
     }
 
-#if 0
-  if (memcmp (iv2, iv, blocksize))
+  err = gcry_cipher_ctl (hd_ctr, PRIV_CIPHERCTL_GET_COUNTER, getctrbuf,
+			 blocksize + 1);
+  if (err || getctrbuf[0] != blocksize)
+    {
+      gcry_cipher_close (hd_one);
+      gcry_cipher_close (hd_ctr);
+      xfree(mem);
+      fail ("%s-CTR-%d test failed (CTR getctr fail)", cipher, blocksize * 8);
+      return -1;
+    }
+  if (memcmp(getctrbuf + 1, iv, blocksize))
     {
       gcry_cipher_close (hd_one);
       gcry_cipher_close (hd_ctr);
@@ -12275,7 +12326,6 @@ cipher_ctr_bulk_test (int cipher_algo)
       fail ("%s-CTR-%d test failed (IV mismatch)", cipher, blocksize * 8);
       return -1;
     }
-#endif
 
   /* Test bulk encryption with typical IV. */
   memset(iv, 0x57, blocksize-4);
@@ -12345,8 +12395,19 @@ cipher_ctr_bulk_test (int cipher_algo)
             cipher, blocksize * 8);
       return -1;
     }
-#if 0
-  if (memcmp (iv2, iv, blocksize))
+
+  err = gcry_cipher_ctl (hd_ctr, PRIV_CIPHERCTL_GET_COUNTER, getctrbuf,
+			 blocksize + 1);
+  if (err || getctrbuf[0] != blocksize)
+    {
+      gcry_cipher_close (hd_one);
+      gcry_cipher_close (hd_ctr);
+      xfree(mem);
+      fail ("%s-CTR-%d test failed (CTR getctr fail, bulk)",
+	    cipher, blocksize * 8);
+      return -1;
+    }
+  if (memcmp(getctrbuf + 1, iv, blocksize))
     {
       gcry_cipher_close (hd_one);
       gcry_cipher_close (hd_ctr);
@@ -12354,89 +12415,99 @@ cipher_ctr_bulk_test (int cipher_algo)
       fail ("%s-CTR-%d test failed (IV mismatch, bulk)", cipher, blocksize * 8);
       return -1;
     }
-#endif
 
   /* Test parallelized code paths (check counter overflow handling) */
-  for (diff = 0; diff < nblocks; diff++) {
-    memset(iv, 0xff, blocksize);
-    iv[blocksize-1] -= diff;
-    iv[0] = iv[1] = 0;
-    iv[2] = 0x07;
+  for (diff = 0; diff < nblocks; diff++)
+    {
+      memset(iv, 0xff, blocksize);
+      iv[blocksize-1] -= diff;
+      iv[0] = iv[1] = 0;
+      iv[2] = 0x07;
 
-    for (i = 0; i < blocksize * nblocks; i++)
-      plaintext[i] = i;
+      for (i = 0; i < blocksize * nblocks; i++)
+	plaintext[i] = i;
 
-    /* Create CTR ciphertext manually.  */
-    for (i = 0; i < blocksize * nblocks; i+=blocksize)
-      {
-        err = gcry_cipher_encrypt (hd_one, &ciphertext[i], blocksize,
-                                  iv, blocksize);
-        if (err)
-          {
-            gcry_cipher_close (hd_one);
-            gcry_cipher_close (hd_ctr);
-            xfree(mem);
-            fail ("%s-CTR-%d test failed (ECB encrypt fail)",
-                  cipher, blocksize * 8);
-            return -1;
-          }
-        for (j = 0; j < blocksize; j++)
-          ciphertext[i+j] ^= plaintext[i+j];
-        for (j = blocksize; j > 0; j--)
-          {
-            iv[j-1]++;
-            if (iv[j-1])
-              break;
-          }
-      }
+      /* Create CTR ciphertext manually.  */
+      for (i = 0; i < blocksize * nblocks; i+=blocksize)
+	{
+	  err = gcry_cipher_encrypt (hd_one, &ciphertext[i], blocksize,
+				    iv, blocksize);
+	  if (err)
+	    {
+	      gcry_cipher_close (hd_one);
+	      gcry_cipher_close (hd_ctr);
+	      xfree(mem);
+	      fail ("%s-CTR-%d test failed (ECB encrypt fail)",
+		    cipher, blocksize * 8);
+	      return -1;
+	    }
+	  for (j = 0; j < blocksize; j++)
+	    ciphertext[i+j] ^= plaintext[i+j];
+	  for (j = blocksize; j > 0; j--)
+	    {
+	      iv[j-1]++;
+	      if (iv[j-1])
+		break;
+	    }
+	}
 
-    /* Decrypt using bulk CTR and compare result.  */
-    memset(iv2, 0xff, blocksize);
-    iv2[blocksize-1] -= diff;
-    iv2[0] = iv2[1] = 0;
-    iv2[2] = 0x07;
+      /* Decrypt using bulk CTR and compare result.  */
+      memset(iv2, 0xff, blocksize);
+      iv2[blocksize-1] -= diff;
+      iv2[0] = iv2[1] = 0;
+      iv2[2] = 0x07;
 
-    err = gcry_cipher_setctr (hd_ctr, iv2, blocksize);
-    if (err)
-      {
-        gcry_cipher_close (hd_one);
-        gcry_cipher_close (hd_ctr);
-        xfree(mem);
-        fail ("%s-CTR-%d test failed (setiv fail)", cipher, blocksize * 8);
-        return -1;
-      }
-    err = gcry_cipher_decrypt (hd_ctr, plaintext2, blocksize * nblocks,
-                               ciphertext, blocksize * nblocks);
-    if (err)
-      {
-        gcry_cipher_close (hd_one);
-        gcry_cipher_close (hd_ctr);
-        xfree(mem);
-        fail ("%s-CTR-%d test failed (CTR decrypt fail)", cipher, blocksize * 8);
-        return -1;
-      }
+      err = gcry_cipher_setctr (hd_ctr, iv2, blocksize);
+      if (err)
+	{
+	  gcry_cipher_close (hd_one);
+	  gcry_cipher_close (hd_ctr);
+	  xfree(mem);
+	  fail ("%s-CTR-%d test failed (setiv fail)", cipher, blocksize * 8);
+	  return -1;
+	}
+      err = gcry_cipher_decrypt (hd_ctr, plaintext2, blocksize * nblocks,
+				 ciphertext, blocksize * nblocks);
+      if (err)
+	{
+	  gcry_cipher_close (hd_one);
+	  gcry_cipher_close (hd_ctr);
+	  xfree(mem);
+	  fail ("%s-CTR-%d test failed (CTR decrypt fail)", cipher, blocksize * 8);
+	  return -1;
+	}
 
-    if (memcmp (plaintext2, plaintext, blocksize * nblocks))
-      {
-        gcry_cipher_close (hd_one);
-        gcry_cipher_close (hd_ctr);
-        xfree(mem);
-        fail ("%s-CTR-%d test failed (plaintext mismatch, diff: %d)",
-              cipher, blocksize * 8, diff);
-        return -1;
-      }
-#if 0
-    if (memcmp(iv2, iv, blocksize))
-      {
-        gcry_cipher_close (hd_one);
-        gcry_cipher_close (hd_ctr);
-        xfree(mem);
-        fail ("%s-CTR-%d test failed (IV mismatch, diff: %d)",
-              cipher, blocksize * 8, diff);
-        return -1;
-      }
-#endif
-  }
+      if (memcmp (plaintext2, plaintext, blocksize * nblocks))
+	{
+	  gcry_cipher_close (hd_one);
+	  gcry_cipher_close (hd_ctr);
+	  xfree(mem);
+	  fail ("%s-CTR-%d test failed (plaintext mismatch, diff: %d)",
+		cipher, blocksize * 8, diff);
+	  return -1;
+	}
+
+      err = gcry_cipher_ctl (hd_ctr, PRIV_CIPHERCTL_GET_COUNTER, getctrbuf,
+			     blocksize + 1);
+      if (err || getctrbuf[0] != blocksize)
+        {
+          gcry_cipher_close (hd_one);
+          gcry_cipher_close (hd_ctr);
+          xfree(mem);
+          fail ("%s-CTR-%d test failed (CTR getctr fail, diff: %d)",
+		cipher, blocksize * 8, diff);
+          return -1;
+        }
+      if (memcmp(getctrbuf + 1, iv, blocksize))
+	{
+	  gcry_cipher_close (hd_one);
+	  gcry_cipher_close (hd_ctr);
+	  xfree(mem);
+	  fail ("%s-CTR-%d test failed (IV mismatch, diff: %d)",
+		cipher, blocksize * 8, diff);
+	  return -1;
+	}
+    }
 
   gcry_cipher_close (hd_one);
   gcry_cipher_close (hd_ctr);
-- 
2.34.1




More information about the Gcrypt-devel mailing list