[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-365-gf2260e3
by Jussi Kivilinna
cvs at cvs.gnupg.org
Sun Mar 27 10:18:30 CEST 2016
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".
The branch, master has been updated
via f2260e3a2e962ac80124ef938e54041bbea08561 (commit)
from 4a064e2a06fe737f344d1dfd8a45cc4c2abbe4c9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit f2260e3a2e962ac80124ef938e54041bbea08561
Author: Jussi Kivilinna <jussi.kivilinna at iki.fi>
Date: Sun Mar 27 11:17:39 2016 +0300
cipher: GCM: check that length of supplied tag is one of valid lengths
* cipher/cipher-gcm.c (is_tag_length_valid): New.
(_gcry_cipher_gcm_tag): Check that 'outbuflen' has valid tag length.
* tests/basic.c (_check_gcm_cipher): Add test-vectors with different
valid tag lengths and negative test vectors with invalid lengths.
--
NIST SP 800-38D allows following tag lengths:
128, 120, 112, 104, 96, 64 and 32 bits.
[v2: allow larger buffer when outputting tag. 128-bit tag is written
to target buffer in this case]
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 712641e..6e0959a 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -769,12 +769,32 @@ _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c,
#endif
+static int
+is_tag_length_valid(size_t taglen)
+{
+ switch (taglen)
+ {
+ /* Allowed tag lengths from NIST SP 800-38D. */
+ case 128 / 8: /* GCRY_GCM_BLOCK_LEN */
+ case 120 / 8:
+ case 112 / 8:
+ case 104 / 8:
+ case 96 / 8:
+ case 64 / 8:
+ case 32 / 8:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
static gcry_err_code_t
_gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
byte * outbuf, size_t outbuflen, int check)
{
- if (outbuflen < GCRY_GCM_BLOCK_LEN)
- return GPG_ERR_BUFFER_TOO_SHORT;
+ if (!(is_tag_length_valid (outbuflen) || outbuflen >= GCRY_GCM_BLOCK_LEN))
+ return GPG_ERR_INV_LENGTH;
if (c->u_mode.gcm.datalen_over_limits)
return GPG_ERR_INV_LENGTH;
@@ -815,17 +835,19 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
if (!check)
{
+ if (outbuflen > GCRY_GCM_BLOCK_LEN)
+ outbuflen = GCRY_GCM_BLOCK_LEN;
+
/* NB: We already checked that OUTBUF is large enough to hold
- the result. */
- memcpy (outbuf, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN);
+ * the result or has valid truncated length. */
+ memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen);
}
else
{
/* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
* and thus we need to compare its length first. */
- if (outbuflen != GCRY_GCM_BLOCK_LEN
- || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag,
- GCRY_GCM_BLOCK_LEN))
+ if (!is_tag_length_valid (outbuflen)
+ || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen))
return GPG_ERR_CHECKSUM;
}
diff --git a/tests/basic.c b/tests/basic.c
index 36a83d0..25d31ee 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -1304,6 +1304,8 @@ _check_gcm_cipher (unsigned int step)
int inlen;
char out[MAX_DATA_LEN];
char tag[MAX_DATA_LEN];
+ int taglen;
+ int should_fail;
} tv[] =
{
/* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */
@@ -1319,6 +1321,78 @@ _check_gcm_cipher (unsigned int step)
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
"", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45",
+ 15 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7",
+ 14 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4",
+ 13 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57",
+ 12 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d",
+ 11, 1 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce\xfa\x7e\x30\x61",
+ 8 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58\xe2\xfc\xce",
+ 4 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
+ "",
+ 0,
+ "",
+ "\x58",
+ 1, 1 },
+ { GCRY_CIPHER_AES,
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12,
+ "", 0,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
16,
"\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78",
@@ -1570,9 +1644,14 @@ _check_gcm_cipher (unsigned int step)
if (memcmp (tv[i].plaintext, out, tv[i].inlen))
fail ("aes-gcm, decrypt mismatch entry %d (step %d)\n", i, step);
- err = gcry_cipher_gettag (hde, out, GCRY_GCM_BLOCK_LEN);
+ taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN;
+
+ err = gcry_cipher_gettag (hde, out, taglen2);
if (err)
{
+ if (tv[i].should_fail)
+ goto next_tv;
+
fail ("aes-gcm, gcry_cipher_gettag(%d) failed: %s\n",
i, gpg_strerror (err));
gcry_cipher_close (hde);
@@ -1580,11 +1659,10 @@ _check_gcm_cipher (unsigned int step)
return;
}
- if (memcmp (tv[i].tag, out, GCRY_GCM_BLOCK_LEN))
+ if (memcmp (tv[i].tag, out, taglen2))
fail ("aes-gcm, encrypt tag mismatch entry %d\n", i);
-
- err = gcry_cipher_checktag (hdd, out, GCRY_GCM_BLOCK_LEN);
+ err = gcry_cipher_checktag (hdd, out, taglen2);
if (err)
{
fail ("aes-gcm, gcry_cipher_checktag(%d) failed: %s\n",
@@ -1660,17 +1738,25 @@ _check_gcm_cipher (unsigned int step)
if (memcmp (tv[i].out, out, tv[i].inlen))
fail ("aes-gcm, encrypt mismatch entry %d, (byte-buf)\n", i);
- err = gcry_cipher_gettag (hde, tag, GCRY_GCM_BLOCK_LEN);
+ /* Test output to larger than 16-byte buffer. */
+ taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN + 1;
+
+ err = gcry_cipher_gettag (hde, tag, taglen2);
if (err)
{
- fail ("aes-gcm, gcry_cipher_gettag(%d) (byte-buf) failed: %s\n",
- i, gpg_strerror (err));
+ if (tv[i].should_fail)
+ goto next_tv;
+
+ fail ("aes-gcm, gcry_cipher_gettag(%d, %d) (byte-buf) failed: %s\n",
+ i, taglen2, gpg_strerror (err));
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
return;
}
- if (memcmp (tv[i].tag, tag, GCRY_GCM_BLOCK_LEN))
+ taglen2 = tv[i].taglen ? tv[i].taglen : GCRY_GCM_BLOCK_LEN;
+
+ if (memcmp (tv[i].tag, tag, taglen2))
fail ("aes-gcm, encrypt tag mismatch entry %d, (byte-buf)\n", i);
for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum)
@@ -1689,7 +1775,7 @@ _check_gcm_cipher (unsigned int step)
if (memcmp (tv[i].plaintext, out, tv[i].inlen))
fail ("aes-gcm, decrypt mismatch entry %d\n", i);
- err = gcry_cipher_checktag (hdd, tag, GCRY_GCM_BLOCK_LEN);
+ err = gcry_cipher_checktag (hdd, tag, taglen2);
if (err)
{
fail ("aes-gcm, gcry_cipher_checktag(%d) (byte-buf) failed: %s\n",
@@ -1699,6 +1785,34 @@ _check_gcm_cipher (unsigned int step)
return;
}
+ err = gcry_cipher_checktag (hdd, tag, 1);
+ if (!err)
+ {
+ fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid "
+ " tag length of '%d'\n", i, 1);
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+ err = gcry_cipher_checktag (hdd, tag, 17);
+ if (!err)
+ {
+ fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid "
+ " tag length of '%d'\n", i, 17);
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+ if (tv[i].should_fail)
+ {
+ fail ("aes-gcm, negative test succeeded %d\n", i);
+ gcry_cipher_close (hde);
+ gcry_cipher_close (hdd);
+ return;
+ }
+
+next_tv:
gcry_cipher_close (hde);
gcry_cipher_close (hdd);
}
-----------------------------------------------------------------------
Summary of changes:
cipher/cipher-gcm.c | 36 +++++++++++---
tests/basic.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 152 insertions(+), 16 deletions(-)
hooks/post-receive
--
The GNU crypto library
http://git.gnupg.org
_______________________________________________
Gnupg-commits mailing list
Gnupg-commits at gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits
More information about the Gcrypt-devel
mailing list