summaryrefslogtreecommitdiff
path: root/cipher/cipher-gcm.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2016-03-27 11:17:39 +0300
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2016-03-27 11:17:39 +0300
commitf2260e3a2e962ac80124ef938e54041bbea08561 (patch)
treecc3443018415bac407e62570e7c47b375a6ec3be /cipher/cipher-gcm.c
parent4a064e2a06fe737f344d1dfd8a45cc4c2abbe4c9 (diff)
downloadlibgcrypt-f2260e3a2e962ac80124ef938e54041bbea08561.tar.gz
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@iki.fi>
Diffstat (limited to 'cipher/cipher-gcm.c')
-rw-r--r--cipher/cipher-gcm.c36
1 files changed, 29 insertions, 7 deletions
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 712641e8..6e0959ad 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;
}