[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