summaryrefslogtreecommitdiff
path: root/cipher/cipher-gcm.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-19 23:26:27 +0200
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-20 18:39:02 +0200
commit56d352d6bdcf7abaa33c3399741f5063e2ddc32a (patch)
treef0ff0624e5e0bdec3f2054a3fc0e36d1e47fb7c9 /cipher/cipher-gcm.c
parent32a2da9abc91394b23cf565c1c833fa964394083 (diff)
downloadlibgcrypt-56d352d6bdcf7abaa33c3399741f5063e2ddc32a.tar.gz
GCM: add FIPS mode restrictions
* cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt) (_gcry_cipher_gcm_get_tag): Do not allow using in FIPS mode is setiv was invocated directly. (_gcry_cipher_gcm_setiv): Rename to... (_gcry_cipher_gcm_initiv): ...this. (_gcry_cipher_gcm_setiv): New setiv function with check for FIPS mode. [TODO] (_gcry_cipher_gcm_getiv): New. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode'. -- Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/cipher-gcm.c')
-rw-r--r--cipher/cipher-gcm.c61
1 files changed, 59 insertions, 2 deletions
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index 124fe3e8..0e97c678 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -850,6 +850,9 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
if (!c->marks.iv)
_gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
+ if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode)
+ return GPG_ERR_INV_STATE;
+
gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen);
if (!gcm_check_datalen(c->u_mode.gcm.datalen))
{
@@ -928,8 +931,8 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c,
}
-gcry_err_code_t
-_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
+static gcry_err_code_t
+_gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
{
memset (c->u_mode.gcm.aadlen, 0, sizeof(c->u_mode.gcm.aadlen));
memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen));
@@ -992,6 +995,56 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
}
+gcry_err_code_t
+_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
+{
+ c->marks.iv = 0;
+ c->marks.tag = 0;
+ c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0;
+
+ if (fips_mode ())
+ {
+ /* Direct invocation of GCM setiv in FIPS mode disables encryption. */
+ c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 1;
+ }
+
+ return _gcry_cipher_gcm_initiv (c, iv, ivlen);
+}
+
+
+#if 0 && TODO
+void
+_gcry_cipher_gcm_geniv (gcry_cipher_hd_t c,
+ byte *ivout, unsigned int ivoutlen, const byte *nonce,
+ unsigned int noncelen)
+{
+ /* nonce: user provided part (might be null) */
+ /* noncelen: check if proper length (if nonce not null) */
+ /* ivout: iv used to initialize gcm, output to user */
+ /* ivoutlen: check correct size */
+ byte iv[IVLEN];
+
+ if (!ivout)
+ return GPG_ERR_INV_ARG;
+ if (ivoutlen != IVLEN)
+ return GPG_ERR_INV_LENGTH;
+ if (nonce != NULL && !is_nonce_ok_len(noncelen))
+ return GPG_ERR_INV_ARG;
+
+ gcm_generate_iv(iv, nonce, noncelen);
+
+ c->marks.iv = 0;
+ c->marks.tag = 0;
+ c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0;
+
+ _gcry_cipher_gcm_initiv (c, iv, IVLEN);
+
+ buf_cpy(ivout, iv, IVLEN);
+ wipememory(iv, sizeof(iv));
+}
+#endif
+
+
static gcry_err_code_t
_gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
byte * outbuf, unsigned int outbuflen, int check)
@@ -1042,6 +1095,10 @@ gcry_err_code_t
_gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
size_t taglen)
{
+ /* Outputting authentication tag is part of encryption. */
+ if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode)
+ return GPG_ERR_INV_STATE;
+
return _gcry_cipher_gcm_tag (c, outtag, taglen, 0);
}