summaryrefslogtreecommitdiff
path: root/cipher/cipher.c
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2013-11-19 23:26:26 +0200
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-19 23:26:26 +0200
commit90cce18b9eced4f412ceeec5bcae18c4493322df (patch)
tree8018c676ab8f35e2e9b50938f90761e1454a6597 /cipher/cipher.c
parent9816ae9d9931b75e4fdc9a5be10e6af447132313 (diff)
downloadlibgcrypt-90cce18b9eced4f412ceeec5bcae18c4493322df.tar.gz
Initial implementation of GCM
* cipher/Makefile.am: Add 'cipher-gcm.c'. * cipher/cipher-ccm.c (_gcry_ciphert_ccm_set_lengths) (_gcry_cipher_ccm_authenticate, _gcry_cipher_ccm_tag) (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt): Change 'c->u_mode.ccm.tag' to 'c->marks.tag'. * cipher/cipher-gcm.c: New. * cipher/cipher-internal.h (GCM_USE_TABLES): New. (gcry_cipher_handle): Add 'marks.tag', 'u_tag', 'length' and 'gcm_table'; Remove 'u_mode.ccm.tag'. (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt) (_gcry_cipher_gcm_setiv, _gcry_cipher_gcm_authenticate) (_gcry_cipher_gcm_get_tag, _gcry_cipher_gcm_check_tag): New. * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey) (cipher_encrypt, cipher_decrypt, _gcry_cipher_authenticate) (_gcry_cipher_gettag, _gcry_cipher_checktag): Add GCM mode handling. * src/gcrypt.h.in (gcry_cipher_modes): Add GCRY_CIPHER_MODE_GCM. (GCRY_GCM_BLOCK_LEN): New. * tests/basic.c (check_gcm_cipher): New. (check_ciphers): Add GCM check. (check_cipher_modes): Call 'check_gcm_cipher'. * tests/bench-slope.c (bench_gcm_encrypt_do_bench) (bench_gcm_decrypt_do_bench, bench_gcm_authenticate_do_bench) (gcm_encrypt_ops, gcm_decrypt_ops, gcm_authenticate_ops): New. (cipher_modes): Add GCM enc/dec/auth. (cipher_bench_one): Limit GCM to block ciphers with 16 byte block-size. * tests/benchmark.c (cipher_bench): Add GCM. -- Currently it is still quite slow. Still no support for generate_iv(). Is it really necessary? TODO: Merge/reuse cipher-internal state used by CCM. Changelog entry will be present in final patch submission. Changes since v1: - 6x-7x speedup. - added bench-slope support Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> [jk: mangle new file throught 'indent -nut'] [jk: few fixes] [jk: changelog]
Diffstat (limited to 'cipher/cipher.c')
-rw-r--r--cipher/cipher.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/cipher/cipher.c b/cipher/cipher.c
index b68703e3..bba6abb8 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -407,6 +407,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
case GCRY_CIPHER_MODE_CTR:
case GCRY_CIPHER_MODE_AESWRAP:
case GCRY_CIPHER_MODE_CMAC:
+ case GCRY_CIPHER_MODE_GCM:
if (!spec->encrypt || !spec->decrypt)
err = GPG_ERR_INV_CIPHER_MODE;
break;
@@ -609,6 +610,13 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
static void
cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
{
+ /* GCM has its own IV handler */
+ if (c->mode == GCRY_CIPHER_MODE_GCM)
+ {
+ _gcry_cipher_gcm_setiv (c, iv, ivlen);
+ return;
+ }
+
/* If the cipher has its own IV handler, we use only this one. This
is currently used for stream ciphers requiring a nonce. */
if (c->spec->setiv)
@@ -767,6 +775,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
rc = GPG_ERR_INV_CIPHER_MODE;
break;
+ case GCRY_CIPHER_MODE_GCM:
+ rc = _gcry_cipher_gcm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
case GCRY_CIPHER_MODE_STREAM:
c->spec->stencrypt (&c->context.c,
outbuf, (byte*)/*arggg*/inbuf, inbuflen);
@@ -871,6 +883,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
rc = GPG_ERR_INV_CIPHER_MODE;
break;
+ case GCRY_CIPHER_MODE_GCM:
+ rc = _gcry_cipher_gcm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+ break;
+
case GCRY_CIPHER_MODE_STREAM:
c->spec->stdecrypt (&c->context.c,
outbuf, (byte*)/*arggg*/inbuf, inbuflen);
@@ -1000,6 +1016,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf,
rc = _gcry_cipher_cmac_authenticate (hd, abuf, abuflen);
break;
+ case GCRY_CIPHER_MODE_GCM:
+ rc = _gcry_cipher_gcm_authenticate (hd, abuf, abuflen);
+ break;
+
default:
log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode);
rc = GPG_ERR_INV_CIPHER_MODE;
@@ -1024,6 +1044,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen)
rc = _gcry_cipher_cmac_get_tag (hd, outtag, taglen);
break;
+ case GCRY_CIPHER_MODE_GCM:
+ rc = _gcry_cipher_gcm_get_tag (hd, outtag, taglen);
+ break;
+
default:
log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode);
rc = GPG_ERR_INV_CIPHER_MODE;
@@ -1048,6 +1072,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen)
rc = _gcry_cipher_cmac_check_tag (hd, intag, taglen);
break;
+ case GCRY_CIPHER_MODE_GCM:
+ rc = _gcry_cipher_gcm_check_tag (hd, intag, taglen);
+ break;
+
default:
log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode);
rc = GPG_ERR_INV_CIPHER_MODE;