Mailing List Archive

[PATCH 1/2] tests/basic: enable IV checks for CBC/CFB/CTR bulk tests
* 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@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


_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@lists.gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel