diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-11-19 23:26:27 +0200 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-11-20 18:39:02 +0200 |
commit | 56d352d6bdcf7abaa33c3399741f5063e2ddc32a (patch) | |
tree | f0ff0624e5e0bdec3f2054a3fc0e36d1e47fb7c9 /cipher/cipher-gcm.c | |
parent | 32a2da9abc91394b23cf565c1c833fa964394083 (diff) | |
download | libgcrypt-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.c | 61 |
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); } |