diff --git a/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc b/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc index e5b32d0..42df04d 100644 --- a/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc +++ b/inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc @@ -36,6 +36,18 @@ Newz(0, RETVAL, 1, struct chacha20poly1305_struct); if (!RETVAL) croak("FATAL: Newz failed"); Copy(&self->state, &RETVAL->state, 1, struct chacha20poly1305_struct); + OUTPUT: + RETVAL + +int +increment_iv(Crypt::AuthEnc::ChaCha20Poly1305 self) + CODE: + { + int rv; + rv = chacha20poly1305_inciv(&self->state); + if (rv != CRYPT_OK) croak("FATAL: chacha20poly1305_inciv failed: %s", error_to_string(rv)); + RETVAL = rv; + } OUTPUT: RETVAL diff --git a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm index 4cf29d3..b7b483b 100644 --- a/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm +++ b/lib/Crypt/AuthEnc/ChaCha20Poly1305.pm @@ -82,7 +82,7 @@ =head1 DESCRIPTION -Galois/Counter Mode (ChaCha20Poly1305) - provides encryption and authentication. +Provides encryption and authentication based on ChaCha20 + Poly1305 as defined in RFC 7539 - L =head1 EXPORT @@ -145,6 +145,10 @@ my $ae_new = $ae->clone; +=head2 increment_iv + + $ae->increment_iv; + =head1 SEE ALSO =over diff --git a/src/Makefile b/src/Makefile index 3015d00..2c017bb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,6 +9,7 @@ ltc/encauth/chachapoly/chacha20poly1305_done.o ltc/encauth/chachapoly/chacha20poly1305_encrypt.o \ ltc/encauth/chachapoly/chacha20poly1305_init.o ltc/encauth/chachapoly/chacha20poly1305_memory.o \ ltc/encauth/chachapoly/chacha20poly1305_setiv.o ltc/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.o \ +ltc/encauth/chachapoly/chacha20poly1305_inciv.o \ ltc/encauth/ccm/ccm_add_aad.o ltc/encauth/ccm/ccm_add_nonce.o ltc/encauth/ccm/ccm_done.o ltc/encauth/ccm/ccm_init.o \ ltc/encauth/ccm/ccm_memory.o ltc/encauth/ccm/ccm_process.o ltc/encauth/ccm/ccm_reset.o \ ltc/encauth/eax/eax_addheader.o ltc/encauth/eax/eax_decrypt.o ltc/encauth/eax/eax_decrypt_verify_memory.o \ diff --git a/src/Makefile.nmake b/src/Makefile.nmake index 01003f4..4cd43d6 100644 --- a/src/Makefile.nmake +++ b/src/Makefile.nmake @@ -9,6 +9,7 @@ ltc/encauth/chachapoly/chacha20poly1305_done.obj ltc/encauth/chachapoly/chacha20poly1305_encrypt.obj \ ltc/encauth/chachapoly/chacha20poly1305_init.obj ltc/encauth/chachapoly/chacha20poly1305_memory.obj \ ltc/encauth/chachapoly/chacha20poly1305_setiv.obj ltc/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.obj \ +ltc/encauth/chachapoly/chacha20poly1305_inciv.obj \ ltc/encauth/ccm/ccm_add_aad.obj ltc/encauth/ccm/ccm_add_nonce.obj ltc/encauth/ccm/ccm_done.obj ltc/encauth/ccm/ccm_init.obj \ ltc/encauth/ccm/ccm_memory.obj ltc/encauth/ccm/ccm_process.obj ltc/encauth/ccm/ccm_reset.obj \ ltc/encauth/eax/eax_addheader.obj ltc/encauth/eax/eax_decrypt.obj ltc/encauth/eax/eax_decrypt_verify_memory.obj \ diff --git a/src/ltc/encauth/chachapoly/chacha20poly1305_inciv.c b/src/ltc/encauth/chachapoly/chacha20poly1305_inciv.c new file mode 100644 index 0000000..f7f3143 --- /dev/null +++ b/src/ltc/encauth/chachapoly/chacha20poly1305_inciv.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Reset ChaCha20Poly1305 state with incremented IV - used by https://shadowsocks.org/en/spec/AEAD-Ciphers.html + @param st The ChaCha20Poly1305 state + @param iv The IV data to add + @param inlen The length of the IV (must be 12 or 8) + @return CRYPT_OK on success + */ +int chacha20poly1305_inciv(chacha20poly1305_state *st) +{ + int err; + unsigned char tmp_iv[12]; + unsigned long ivlen; + + LTC_ARGCHK(st != NULL); + + ivlen = st->chacha.ivlen; + if (ivlen == 12) { + STORE32L(st->chacha.input[13], tmp_iv + 0); + STORE32L(st->chacha.input[14], tmp_iv + 4); + STORE32L(st->chacha.input[15], tmp_iv + 8); + /* increment IV 96bit / 12 bytes */ + if (!++tmp_iv[0] && !++tmp_iv[1] && !++tmp_iv[2] && !++tmp_iv[3] && + !++tmp_iv[4] && !++tmp_iv[5] && !++tmp_iv[6] && !++tmp_iv[7] && + !++tmp_iv[8] && !++tmp_iv[9] && !++tmp_iv[10] && !++tmp_iv[11]) + { + err = CRYPT_ERROR; /* IV overflow */ + } + else { + err = chacha20poly1305_setiv(st, tmp_iv, 12); + } + } + else if (ivlen == 8) { + STORE32L(st->chacha.input[14], tmp_iv + 0); + STORE32L(st->chacha.input[15], tmp_iv + 4); + /* increment IV 64bit / 8 bytes */ + if (!++tmp_iv[0] && !++tmp_iv[1] && !++tmp_iv[2] && !++tmp_iv[3] && + !++tmp_iv[4] && !++tmp_iv[5] && !++tmp_iv[6] && !++tmp_iv[7]) + { + err = CRYPT_ERROR; /* IV overflow */ + } + else { + err = chacha20poly1305_setiv(st, tmp_iv, 8); + } + } + else { + err = CRYPT_ERROR; /* invalid IV length */ + } + + return err; +} + +#endif diff --git a/src/ltc/stream/chacha/chacha_ivctr32.c b/src/ltc/stream/chacha/chacha_ivctr32.c index 64dc838..0321568 100644 --- a/src/ltc/stream/chacha/chacha_ivctr32.c +++ b/src/ltc/stream/chacha/chacha_ivctr32.c @@ -36,6 +36,7 @@ LOAD32L(st->input[14], iv + 4); LOAD32L(st->input[15], iv + 8); st->ksleft = 0; + st->ivlen = ivlen; return CRYPT_OK; }; diff --git a/src/ltc/stream/chacha/chacha_ivctr64.c b/src/ltc/stream/chacha/chacha_ivctr64.c index c2826bb..ccc3972 100644 --- a/src/ltc/stream/chacha/chacha_ivctr64.c +++ b/src/ltc/stream/chacha/chacha_ivctr64.c @@ -36,6 +36,7 @@ LOAD32L(st->input[14], iv + 0); LOAD32L(st->input[15], iv + 4); st->ksleft = 0; + st->ivlen = ivlen; return CRYPT_OK; };