summaryrefslogtreecommitdiff
path: root/cipher/cipher.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2014-05-11 12:00:19 +0300
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2014-05-12 20:32:45 +0300
commite813958419b0ec4439e6caf07d3b2234cffa2bfa (patch)
tree6d50e973040b0f4efbd90ad94c0f4efd81d8d266 /cipher/cipher.c
parent73b3b75c2221a6e3bed4117e0a206a1193acd2ed (diff)
downloadlibgcrypt-e813958419b0ec4439e6caf07d3b2234cffa2bfa.tar.gz
Add Poly1305 based cipher AEAD mode
* cipher/Makefile.am: Add 'cipher-poly1305.c'. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.poly1305'. (_gcry_cipher_poly1305_encrypt, _gcry_cipher_poly1305_decrypt) (_gcry_cipher_poly1305_setiv, _gcry_cipher_poly1305_authenticate) (_gcry_cipher_poly1305_get_tag, _gcry_cipher_poly1305_check_tag): New. * cipher/cipher-poly1305.c: New. * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey) (cipher_reset, cipher_encrypt, cipher_decrypt, _gcry_cipher_setiv) (_gcry_cipher_authenticate, _gcry_cipher_gettag) (_gcry_cipher_checktag): Handle 'GCRY_CIPHER_MODE_POLY1305'. (cipher_setiv): Move handling of 'GCRY_CIPHER_MODE_GCM' to ... (_gcry_cipher_setiv): ... here, as with other modes. * src/gcrypt.h.in: Add 'GCRY_CIPHER_MODE_POLY1305'. * tests/basic.c (_check_poly1305_cipher, check_poly1305_cipher): New. (check_ciphers): Add Poly1305 check. (check_cipher_modes): Call 'check_poly1305_cipher'. * tests/bench-slope.c (bench_gcm_encrypt_do_bench): Rename to bench_aead_... and take nonce as argument. (bench_gcm_decrypt_do_bench, bench_gcm_authenticate_do_bench): Ditto. (bench_gcm_encrypt_do_bench, bench_gcm_decrypt_do_bench) (bench_gcm_authenticate_do_bench, bench_poly1305_encrypt_do_bench) (bench_poly1305_decrypt_do_bench) (bench_poly1305_authenticate_do_bench, poly1305_encrypt_ops) (poly1305_decrypt_ops, poly1305_authenticate_ops): New. (cipher_modes): Add Poly1305. (cipher_bench_one): Add special handling for Poly1305. -- Patch adds Poly1305 based AEAD cipher mode to libgcrypt. ChaCha20 variant of this mode is proposed for use in TLS and ipsec: https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-02 Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/cipher.c')
-rw-r--r--cipher/cipher.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 47513021..da590610 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -418,6 +418,15 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
err = GPG_ERR_INV_CIPHER_MODE;
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv)
+ err = GPG_ERR_INV_CIPHER_MODE;
+ else if (spec->algo != GCRY_CIPHER_SALSA20 &&
+ spec->algo != GCRY_CIPHER_SALSA20R12 &&
+ spec->algo != GCRY_CIPHER_CHACHA20)
+ err = GPG_ERR_INV_CIPHER_MODE;
+ break;
+
case GCRY_CIPHER_MODE_STREAM:
if (!spec->stencrypt || !spec->stdecrypt)
err = GPG_ERR_INV_CIPHER_MODE;
@@ -611,6 +620,10 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
_gcry_cipher_gcm_setkey (c);
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ _gcry_cipher_poly1305_setkey (c);
+ break;
+
default:
break;
};
@@ -627,10 +640,6 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
static gcry_err_code_t
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)
- return _gcry_cipher_gcm_setiv (c, iv, ivlen);
-
/* 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)
@@ -699,6 +708,10 @@ cipher_reset (gcry_cipher_hd_t c)
}
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ memset (&c->u_mode.poly1305, 0, sizeof c->u_mode.poly1305);
+ break;
+
#ifdef HAVE_U64_TYPEDEF
case GCRY_CIPHER_MODE_CCM:
memset (&c->u_mode.ccm, 0, sizeof c->u_mode.ccm);
@@ -811,6 +824,11 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
rc = _gcry_cipher_gcm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ rc = _gcry_cipher_poly1305_encrypt (c, outbuf, outbuflen,
+ inbuf, inbuflen);
+ break;
+
case GCRY_CIPHER_MODE_STREAM:
c->spec->stencrypt (&c->context.c,
outbuf, (byte*)/*arggg*/inbuf, inbuflen);
@@ -919,6 +937,11 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
rc = _gcry_cipher_gcm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ rc = _gcry_cipher_poly1305_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 +1023,14 @@ _gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
rc = _gcry_cipher_ccm_set_nonce (hd, iv, ivlen);
break;
+ case GCRY_CIPHER_MODE_GCM:
+ rc = _gcry_cipher_gcm_setiv (hd, iv, ivlen);
+ break;
+
+ case GCRY_CIPHER_MODE_POLY1305:
+ rc = _gcry_cipher_poly1305_setiv (hd, iv, ivlen);
+ break;
+
default:
rc = cipher_setiv (hd, iv, ivlen);
break;
@@ -1050,6 +1081,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf,
rc = _gcry_cipher_gcm_authenticate (hd, abuf, abuflen);
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ rc = _gcry_cipher_poly1305_authenticate (hd, abuf, abuflen);
+ break;
+
default:
log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode);
rc = GPG_ERR_INV_CIPHER_MODE;
@@ -1079,6 +1114,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen)
rc = _gcry_cipher_gcm_get_tag (hd, outtag, taglen);
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ rc = _gcry_cipher_poly1305_get_tag (hd, outtag, taglen);
+ break;
+
default:
log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode);
rc = GPG_ERR_INV_CIPHER_MODE;
@@ -1108,6 +1147,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen)
rc = _gcry_cipher_gcm_check_tag (hd, intag, taglen);
break;
+ case GCRY_CIPHER_MODE_POLY1305:
+ rc = _gcry_cipher_poly1305_check_tag (hd, intag, taglen);
+ break;
+
default:
log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode);
rc = GPG_ERR_INV_CIPHER_MODE;