summaryrefslogtreecommitdiff
path: root/cipher/cipher-gcm.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2016-03-23 14:13:18 +0100
committerWerner Koch <wk@gnupg.org>2016-03-23 14:16:12 +0100
commite709d86fe596a4bcf235799468947c13ae657d78 (patch)
treedb7b05053127347c4f750b3733e7dd847321f13a /cipher/cipher-gcm.c
parent7c9c82feecf94a455c66d9c38576f36c9c4b484c (diff)
downloadlibgcrypt-e709d86fe596a4bcf235799468947c13ae657d78.tar.gz
cipher: Avoid NULL-segv in GCM mode if a key has not been set.
* cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt): Check that GHASH_FN has been initialized. (_gcry_cipher_gcm_decrypt): Ditto. (_gcry_cipher_gcm_authenticate): Ditto. (_gcry_cipher_gcm_initiv): Ditto. (_gcry_cipher_gcm_tag): Ditto. -- Avoid a crash if certain functions are used before setkey. Reported-by: Peter Wu <peter@lekensteyn.nl> One crash is not fixed, that is the crash when setkey is not invoked before using the GCM ciphers (introduced in the 1.7.0 cycle). Either these functions should check that the key is present, or they should initialize the ghash table earlier. Affected functions: _gcry_cipher_gcm_encrypt _gcry_cipher_gcm_decrypt _gcry_cipher_gcm_authenticate _gcry_cipher_gcm_initiv (via _gcry_cipher_gcm_setiv) _gcry_cipher_gcm_tag (via _gcry_cipher_gcm_get_tag, _gcry_cipher_gcm_check_tag) Regression-due-to: 4a0795af021305f9240f23626a3796157db46bd7 Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'cipher/cipher-gcm.c')
-rw-r--r--cipher/cipher-gcm.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 5e9dec48..712641e8 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -535,7 +535,9 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
return GPG_ERR_BUFFER_TOO_SHORT;
if (c->u_mode.gcm.datalen_over_limits)
return GPG_ERR_INV_LENGTH;
- if (c->marks.tag || c->u_mode.gcm.ghash_data_finalized)
+ if (c->marks.tag
+ || c->u_mode.gcm.ghash_data_finalized
+ || !c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
@@ -581,7 +583,9 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c,
return GPG_ERR_BUFFER_TOO_SHORT;
if (c->u_mode.gcm.datalen_over_limits)
return GPG_ERR_INV_LENGTH;
- if (c->marks.tag || c->u_mode.gcm.ghash_data_finalized)
+ if (c->marks.tag
+ || c->u_mode.gcm.ghash_data_finalized
+ || !c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
@@ -617,8 +621,10 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c,
return GPG_ERR_CIPHER_ALGO;
if (c->u_mode.gcm.datalen_over_limits)
return GPG_ERR_INV_LENGTH;
- if (c->marks.tag || c->u_mode.gcm.ghash_aad_finalized ||
- c->u_mode.gcm.ghash_data_finalized)
+ if (c->marks.tag
+ || c->u_mode.gcm.ghash_aad_finalized
+ || c->u_mode.gcm.ghash_data_finalized
+ || !c->u_mode.gcm.ghash_fn)
return GPG_ERR_INV_STATE;
if (!c->marks.iv)
@@ -666,6 +672,9 @@ _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
u32 iv_bytes[2] = {0, 0};
u32 bitlengths[2][2];
+ if (!c->u_mode.gcm.ghash_fn)
+ return GPG_ERR_INV_STATE;
+
memset(c->u_ctr.ctr, 0, GCRY_GCM_BLOCK_LEN);
gcm_bytecounter_add(iv_bytes, ivlen);
@@ -773,6 +782,9 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
{
u32 bitlengths[2][2];
+ if (!c->u_mode.gcm.ghash_fn)
+ return GPG_ERR_INV_STATE;
+
/* aad length */
bitlengths[0][1] = be_bswap32(c->u_mode.gcm.aadlen[0] << 3);
bitlengths[0][0] = be_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |