[PATCH] Add gcry_cipher_ctl command to allow weak keys in testing use-cases

Jussi Kivilinna jussi.kivilinna at iki.fi
Sun Jan 26 19:54:46 CET 2020


* cipher/cipher-internal.h (gcry_cipher_handle): Add
'marks.allow_weak_key' flag.
* cipher/cipher.c (cipher_setkey): Do not handle weak key as error when
weak keys are allowed.
(cipher_reset): Preserve 'marks.allow_weak_key' flag on object reset.
(_gcry_cipher_ctl): Add handling for GCRYCTL_SET_ALLOW_WEAK_KEY.
* src/gcrypt.h.in (gcry_ctl_cmds): Add GCRYCTL_SET_ALLOW_WEAK_KEY.
* tests/basic.c (check_ecb_cipher): Add tests for weak key errors and
for GCRYCTL_SET_ALLOW_WEAK_KEY.
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
 0 files changed

diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h
index 47b7b6f9e..262ca9029 100644
--- a/cipher/cipher-internal.h
+++ b/cipher/cipher-internal.h
@@ -207,6 +207,7 @@ struct gcry_cipher_handle
     unsigned int iv:1;  /* Set to 1 if a IV has been set.  */
     unsigned int tag:1; /* Set to 1 if a tag is finalized. */
     unsigned int finalize:1; /* Next encrypt/decrypt has the final data.  */
+    unsigned int allow_weak_key:1; /* Set to 1 if weak keys are allowed. */
   } marks;
 
   /* The initialization vector.  For best performance we make sure
diff --git a/cipher/cipher.c b/cipher/cipher.c
index bd571367c..09b8d8299 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -794,7 +794,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
     }
 
   rc = c->spec->setkey (&c->context.c, key, keylen, c);
-  if (!rc)
+  if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY))
     {
       /* Duplicate initial context.  */
       memcpy ((void *) ((char *) &c->context.c + c->spec->contextsize),
@@ -828,7 +828,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
 	  /* Setup tweak cipher with second part of XTS key. */
 	  rc = c->spec->setkey (c->u_mode.xts.tweak_context, key + keylen,
 				keylen, c);
-	  if (!rc)
+	  if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY))
 	    {
 	      /* Duplicate initial tweak context.  */
 	      memcpy (c->u_mode.xts.tweak_context + c->spec->contextsize,
@@ -889,9 +889,10 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
 static void
 cipher_reset (gcry_cipher_hd_t c)
 {
-  unsigned int marks_key;
+  unsigned int marks_key, marks_allow_weak_key;
 
   marks_key = c->marks.key;
+  marks_allow_weak_key = c->marks.allow_weak_key;
 
   memcpy (&c->context.c,
 	  (char *) &c->context.c + c->spec->contextsize,
@@ -903,6 +904,7 @@ cipher_reset (gcry_cipher_hd_t c)
   c->unused = 0;
 
   c->marks.key = marks_key;
+  c->marks.allow_weak_key = marks_allow_weak_key;
 
   switch (c->mode)
     {
@@ -1592,6 +1594,13 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
         rc = GPG_ERR_NOT_SUPPORTED;
       break;
 
+    case GCRYCTL_SET_ALLOW_WEAK_KEY:
+      /* Expecting BUFFER to be NULL and buflen to be on/off flag (0 or 1). */
+      if (!h || buffer || buflen > 1)
+	return GPG_ERR_CIPHER_ALGO;
+      h->marks.allow_weak_key = buflen ? 1 : 0;
+      break;
+
     default:
       rc = GPG_ERR_INV_OP;
     }
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index c008f0a6d..46f92a91f 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -333,7 +333,8 @@ enum gcry_ctl_cmds
     GCRYCTL_SET_TAGLEN = 75,
     GCRYCTL_GET_TAGLEN = 76,
     GCRYCTL_REINIT_SYSCALL_CLAMP = 77,
-    GCRYCTL_AUTO_EXPAND_SECMEM = 78
+    GCRYCTL_AUTO_EXPAND_SECMEM = 78,
+    GCRYCTL_SET_ALLOW_WEAK_KEY = 79
   };
 
 /* Perform various operations defined by CMD. */
diff --git a/tests/basic.c b/tests/basic.c
index 812bd89d6..4e3589eea 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -691,6 +691,7 @@ check_ecb_cipher (void)
   {
     int algo;
     const char *key;
+    int is_weak_key;
     struct
     {
       const char *plaintext;
@@ -704,6 +705,7 @@ check_ecb_cipher (void)
       { GCRY_CIPHER_BLOWFISH,
 	"\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
 	"\x00\x11\x22\x33\x44\x55\x66\x77\x88",
+	0,
 	{ { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
 	    1,
 	    8,
@@ -813,6 +815,7 @@ check_ecb_cipher (void)
 	"\x00\x11\x22\x33\x44\x55\x66\x77\x04\x68\x91\x04\xc2\xfd\x3b\x2f"
 	"\x58\x40\x23\x64\x1a\xba\x61\x76\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e"
 	"\xff\xff\xff\xff\xff\xff\xff\xff",
+	0,
 	{ { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
 	    56,
 	    8,
@@ -820,6 +823,28 @@ check_ecb_cipher (void)
 	  { }
 	}
       },
+      /* Weak-key testing */
+      { GCRY_CIPHER_DES,
+	"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+	1,
+	{ { "\x00\x00\x00\x00\x00\x00\x00\x00",
+	    8,
+	    8,
+	    "\xca\xaa\xaf\x4d\xea\xf1\xdb\xae" },
+	  { }
+	}
+      },
+      /* Weak-key testing */
+      { GCRY_CIPHER_DES,
+	"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+	2,
+	{ { "\x00\x00\x00\x00\x00\x00\x00\x00",
+	    8,
+	    8,
+	    "\xca\xaa\xaf\x4d\xea\xf1\xdb\xae" },
+	  { }
+	}
+      },
     };
   gcry_cipher_hd_t hde, hdd;
   unsigned char out[MAX_DATA_LEN];
@@ -858,6 +883,21 @@ check_ecb_cipher (void)
 	  return;
 	}
 
+      if (tv[i].is_weak_key == 2)
+	{
+	  err = gcry_cipher_ctl(hde, GCRYCTL_SET_ALLOW_WEAK_KEY, NULL, 1);
+	  if (!err)
+	    err = gcry_cipher_ctl(hdd, GCRYCTL_SET_ALLOW_WEAK_KEY, NULL, 1);
+	  if (err)
+	    {
+	      fail ("ecb-algo:%d-tv:%d, gcry_cipher_ctl failed: %s\n",
+		    algo, i, gpg_strerror (err));
+	      gcry_cipher_close (hde);
+	      gcry_cipher_close (hdd);
+	      return;
+	    }
+	}
+
       for (j = 0; tv[i].data[j].inlen; j++)
 	{
 	  keylen = tv[i].data[j].keylen;
@@ -875,9 +915,36 @@ check_ecb_cipher (void)
 	    }
 
 	  err = gcry_cipher_setkey (hde, tv[i].key, keylen);
-	  if (!err)
+	  if (!err || (gcry_err_code(err) == GPG_ERR_WEAK_KEY
+	               && tv[i].is_weak_key == 2))
 	    err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
-	  if (err)
+	  if (tv[i].is_weak_key == 1)
+	    {
+	      if (gcry_err_code(err) != GPG_ERR_WEAK_KEY)
+		{
+		  fail ("ecb-algo:%d-tv:%d-data:%d, expected gcry_cipher_setkey to fail, but got: %s\n",
+			algo, i, j, gpg_strerror (err));
+		  gcry_cipher_close (hde);
+		  gcry_cipher_close (hdd);
+		  return;
+		}
+	      else
+		{
+		  continue;
+		}
+	    }
+	  else if (tv[i].is_weak_key == 2)
+	    {
+	      if (gcry_err_code(err) != GPG_ERR_WEAK_KEY)
+		{
+		  fail ("ecb-algo:%d-tv:%d-data:%d, expected gcry_cipher_setkey to fail, but got: %s\n",
+			algo, i, j, gpg_strerror (err));
+		  gcry_cipher_close (hde);
+		  gcry_cipher_close (hdd);
+		  return;
+		}
+	    }
+	  else if (err)
 	    {
 	      fail ("ecb-algo:%d-tv:%d-data:%d, gcry_cipher_setkey failed: %s\n",
 		    algo, i, j, gpg_strerror (err));




More information about the Gcrypt-devel mailing list