diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2021-08-11 18:02:07 +0300 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2021-08-26 20:30:31 +0300 |
commit | 1b8994c4ecf2cb53fff46fa84a95a7c259e7cec7 (patch) | |
tree | 8b07e25cdc96e8590ca91c3e4a9e8abd69a55b09 /cipher/cipher.c | |
parent | 659a208cb065d686f60e2c4f51856f460d6b44f5 (diff) | |
download | libgcrypt-1b8994c4ecf2cb53fff46fa84a95a7c259e7cec7.tar.gz |
Add AES-GCM-SIV mode (RFC 8452)
* cipher/Makefile.am: Add 'cipher-gcm-siv.c'.
* cipher/cipher-gcm-siv.c: New.
* cipher/cipher-gcm.c (_gcry_cipher_gcm_setupM): New.
* cipher/cipher-internal.h (gcry_cipher_handle): Add 'siv_keylen'.
(_gcry_cipher_gcm_setupM, _gcry_cipher_gcm_siv_encrypt)
(_gcry_cipher_gcm_siv_decrypt, _gcry_cipher_gcm_siv_set_nonce)
(_gcry_cipher_gcm_siv_authenticate)
(_gcry_cipher_gcm_siv_set_decryption_tag)
(_gcry_cipher_gcm_siv_get_tag, _gcry_cipher_gcm_siv_check_tag)
(_gcry_cipher_gcm_siv_setkey): New prototypes.
(cipher_block_bswap): New helper function.
* cipher/cipher.c (_gcry_cipher_open_internal): Add
'GCRY_CIPHER_MODE_GCM_SIV'; Refactor mode requirement checks for
better size optimization (check pointers & blocksize in same order
for all).
(cipher_setkey, cipher_reset, _gcry_cipher_setup_mode_ops)
(_gcry_cipher_setup_mode_ops, _gcry_cipher_info): Add GCM-SIV.
(_gcry_cipher_ctl): Handle 'set decryption tag' for GCM-SIV.
* doc/gcrypt.texi: Add GCM-SIV.
* src/gcrypt.h.in (GCRY_CIPHER_MODE_GCM_SIV): New.
(GCRY_SIV_BLOCK_LEN, gcry_cipher_set_decryption_tag): Add to comment
that these are also for GCM-SIV in addition to SIV mode.
* tests/basic.c (check_gcm_siv_cipher): New.
(check_cipher_modes): Check for GCM-SIV.
* tests/bench-slope.c (bench_gcm_siv_encrypt_do_bench)
(bench_gcm_siv_decrypt_do_bench, bench_gcm_siv_authenticate_do_bench)
(gcm_siv_encrypt_ops, gcm_siv_decrypt_ops)
(gcm_siv_authenticate_ops): New.
(cipher_modes): Add GCM-SIV.
(cipher_bench_one): Check key length requirement for GCM-SIV.
--
GnuPG-bug-id: T4485
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/cipher.c')
-rw-r--r-- | cipher/cipher.c | 69 |
1 files changed, 55 insertions, 14 deletions
diff --git a/cipher/cipher.c b/cipher/cipher.c index a274466f..2bde99ef 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -526,33 +526,46 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, if (! err) switch (mode) { - case GCRY_CIPHER_MODE_CCM: - if (spec->blocksize != GCRY_CCM_BLOCK_LEN) + case GCRY_CIPHER_MODE_ECB: + case GCRY_CIPHER_MODE_CBC: + case GCRY_CIPHER_MODE_CFB: + case GCRY_CIPHER_MODE_CFB8: + case GCRY_CIPHER_MODE_OFB: + case GCRY_CIPHER_MODE_CTR: + case GCRY_CIPHER_MODE_AESWRAP: + case GCRY_CIPHER_MODE_CMAC: + case GCRY_CIPHER_MODE_EAX: + if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; + break; + + case GCRY_CIPHER_MODE_CCM: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; + else if (spec->blocksize != GCRY_CCM_BLOCK_LEN) + err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_XTS: - if (spec->blocksize != GCRY_XTS_BLOCK_LEN) - err = GPG_ERR_INV_CIPHER_MODE; if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; + else if (spec->blocksize != GCRY_XTS_BLOCK_LEN) + err = GPG_ERR_INV_CIPHER_MODE; break; - case GCRY_CIPHER_MODE_ECB: - case GCRY_CIPHER_MODE_CBC: - case GCRY_CIPHER_MODE_CFB: - case GCRY_CIPHER_MODE_CFB8: - case GCRY_CIPHER_MODE_OFB: - case GCRY_CIPHER_MODE_CTR: - case GCRY_CIPHER_MODE_AESWRAP: - case GCRY_CIPHER_MODE_CMAC: - case GCRY_CIPHER_MODE_EAX: case GCRY_CIPHER_MODE_GCM: + if (!spec->encrypt || !spec->decrypt) + err = GPG_ERR_INV_CIPHER_MODE; + else if (spec->blocksize != GCRY_GCM_BLOCK_LEN) + err = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_SIV: + case GCRY_CIPHER_MODE_GCM_SIV: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; + else if (spec->blocksize != GCRY_SIV_BLOCK_LEN) + err = GPG_ERR_INV_CIPHER_MODE; break; case GCRY_CIPHER_MODE_POLY1305: @@ -569,7 +582,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, security too much. */ if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; - else if (spec->blocksize != (128/8)) + else if (spec->blocksize != GCRY_OCB_BLOCK_LEN) err = GPG_ERR_INV_CIPHER_MODE; break; @@ -769,6 +782,12 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) _gcry_cipher_gcm_setkey (c); break; + case GCRY_CIPHER_MODE_GCM_SIV: + rc = _gcry_cipher_gcm_siv_setkey (c, keylen); + if (rc) + c->marks.key = 0; + break; + case GCRY_CIPHER_MODE_OCB: _gcry_cipher_ocb_setkey (c); break; @@ -884,6 +903,7 @@ cipher_reset (gcry_cipher_hd_t c) break; case GCRY_CIPHER_MODE_GCM: + case GCRY_CIPHER_MODE_GCM_SIV: /* Only clear head of u_mode, keep ghash_key and gcm_table. */ { byte *u_mode_pos = (void *)&c->u_mode; @@ -1375,6 +1395,11 @@ _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode) c->mode_ops.decrypt = _gcry_cipher_siv_decrypt; break; + case GCRY_CIPHER_MODE_GCM_SIV: + c->mode_ops.encrypt = _gcry_cipher_gcm_siv_encrypt; + c->mode_ops.decrypt = _gcry_cipher_gcm_siv_decrypt; + break; + default: c->mode_ops.encrypt = do_encrypt_none_unknown; c->mode_ops.decrypt = do_decrypt_none_unknown; @@ -1408,6 +1433,10 @@ _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode) c->mode_ops.setiv = _gcry_cipher_siv_set_nonce; break; + case GCRY_CIPHER_MODE_GCM_SIV: + c->mode_ops.setiv = _gcry_cipher_gcm_siv_set_nonce; + break; + default: c->mode_ops.setiv = cipher_setiv; break; @@ -1459,6 +1488,12 @@ _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode) c->mode_ops.check_tag = _gcry_cipher_siv_check_tag; break; + case GCRY_CIPHER_MODE_GCM_SIV: + c->mode_ops.authenticate = _gcry_cipher_gcm_siv_authenticate; + c->mode_ops.get_tag = _gcry_cipher_gcm_siv_get_tag; + c->mode_ops.check_tag = _gcry_cipher_gcm_siv_check_tag; + break; + default: c->mode_ops.authenticate = NULL; c->mode_ops.get_tag = NULL; @@ -1540,6 +1575,8 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) if (h->mode == GCRY_CIPHER_MODE_SIV) rc = _gcry_cipher_siv_set_decryption_tag (h, buffer, buflen); + else if (h->mode == GCRY_CIPHER_MODE_GCM_SIV) + rc = _gcry_cipher_gcm_siv_set_decryption_tag (h, buffer, buflen); else rc = GPG_ERR_INV_CIPHER_MODE; } @@ -1682,6 +1719,10 @@ _gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) *nbytes = GCRY_SIV_BLOCK_LEN; break; + case GCRY_CIPHER_MODE_GCM_SIV: + *nbytes = GCRY_SIV_BLOCK_LEN; + break; + default: rc = GPG_ERR_INV_CIPHER_MODE; break; |