From bf920dc717f5ac48b7baf3512afe98fc9d71af08 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 11 Feb 2015 12:34:29 +0100 Subject: [PATCH] Add IETF-compatible version of chacha20poly1305 --- .../sodium/aead_chacha20poly1305.c | 154 ++++++++++++++-- .../crypto_stream/chacha20/ref/api.h | 10 ++ .../chacha20/ref/stream_chacha20_ref.c | 51 ++++++ .../chacha20/stream_chacha20_api.c | 29 +++ .../sodium/crypto_aead_chacha20poly1305.h | 30 +++- .../include/sodium/crypto_stream_chacha20.h | 23 +++ test/default/aead_chacha20poly1305.c | 167 ++++++++++++++++-- test/default/aead_chacha20poly1305.exp | 51 ++++++ test/default/chacha20.c | 75 +++++++- test/default/chacha20.exp | 9 + 10 files changed, 559 insertions(+), 40 deletions(-) diff --git a/src/libsodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c b/src/libsodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c index 945efe33..68b96c7a 100644 --- a/src/libsodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c +++ b/src/libsodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c @@ -8,6 +8,8 @@ #include "crypto_verify_16.h" #include "utils.h" +static unsigned char _pad0[16]; + static inline void _u64_le_from_ull(unsigned char out[8U], unsigned long long x) { @@ -23,7 +25,7 @@ _u64_le_from_ull(unsigned char out[8U], unsigned long long x) int crypto_aead_chacha20poly1305_encrypt(unsigned char *c, - unsigned long long *clen, + unsigned long long *clen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, @@ -40,8 +42,8 @@ crypto_aead_chacha20poly1305_encrypt(unsigned char *c, /* LCOV_EXCL_START */ #ifdef ULONG_LONG_MAX if (mlen > ULONG_LONG_MAX - crypto_aead_chacha20poly1305_ABYTES) { - if (clen != NULL) { - *clen = 0ULL; + if (clen_p != NULL) { + *clen_p = 0ULL; } return -1; } @@ -65,15 +67,69 @@ crypto_aead_chacha20poly1305_encrypt(unsigned char *c, crypto_onetimeauth_poly1305_final(&state, c + mlen); sodium_memzero(&state, sizeof state); - if (clen != NULL) { - *clen = mlen + crypto_aead_chacha20poly1305_ABYTES; + if (clen_p != NULL) { + *clen_p = mlen + crypto_aead_chacha20poly1305_ABYTES; + } + return 0; +} + +int +crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c, + unsigned long long *clen_p, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *ad, + unsigned long long adlen, + const unsigned char *nsec, + const unsigned char *npub, + const unsigned char *k) +{ + crypto_onetimeauth_poly1305_state state; + unsigned char block0[64U]; + unsigned char slen[8U]; + + (void) nsec; +/* LCOV_EXCL_START */ +#ifdef ULONG_LONG_MAX + if (mlen > ULONG_LONG_MAX - crypto_aead_chacha20poly1305_ABYTES) { + if (clen_p != NULL) { + *clen_p = 0ULL; + } + return -1; + } +#endif +/* LCOV_EXCL_STOP */ + + crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k); + crypto_onetimeauth_poly1305_init(&state, block0); + sodium_memzero(block0, sizeof block0); + + crypto_onetimeauth_poly1305_update(&state, ad, adlen); + crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf); + + crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, npub, 1U, k); + + crypto_onetimeauth_poly1305_update(&state, c, mlen); + crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf); + + _u64_le_from_ull(slen, adlen); + crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); + + _u64_le_from_ull(slen, mlen); + crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); + + crypto_onetimeauth_poly1305_final(&state, c + mlen); + sodium_memzero(&state, sizeof state); + + if (clen_p != NULL) { + *clen_p = mlen + crypto_aead_chacha20poly1305_ABYTES; } return 0; } int crypto_aead_chacha20poly1305_decrypt(unsigned char *m, - unsigned long long *mlen, + unsigned long long *mlen_p, unsigned char *nsec, const unsigned char *c, unsigned long long clen, @@ -86,11 +142,12 @@ crypto_aead_chacha20poly1305_decrypt(unsigned char *m, unsigned char block0[64U]; unsigned char slen[8U]; unsigned char mac[crypto_aead_chacha20poly1305_ABYTES]; + unsigned long long mlen; int ret; (void) nsec; - if (mlen != NULL) { - *mlen = 0ULL; + if (mlen_p != NULL) { + *mlen_p = 0ULL; } if (clen < crypto_aead_chacha20poly1305_ABYTES) { return -1; @@ -103,26 +160,84 @@ crypto_aead_chacha20poly1305_decrypt(unsigned char *m, _u64_le_from_ull(slen, adlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); - crypto_onetimeauth_poly1305_update - (&state, c, clen - crypto_aead_chacha20poly1305_ABYTES); - _u64_le_from_ull(slen, clen - crypto_aead_chacha20poly1305_ABYTES); + mlen = clen - crypto_aead_chacha20poly1305_ABYTES; + crypto_onetimeauth_poly1305_update(&state, c, mlen); + _u64_le_from_ull(slen, mlen); crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); crypto_onetimeauth_poly1305_final(&state, mac); sodium_memzero(&state, sizeof state); (void) sizeof(int[sizeof mac == 16U ? 1 : -1]); - ret = crypto_verify_16(mac, - c + clen - crypto_aead_chacha20poly1305_ABYTES); + ret = crypto_verify_16(mac, c + mlen); sodium_memzero(mac, sizeof mac); if (ret != 0) { - memset(m, 0, clen - crypto_aead_chacha20poly1305_ABYTES); + memset(m, 0, mlen); return -1; } crypto_stream_chacha20_xor_ic - (m, c, clen - crypto_aead_chacha20poly1305_ABYTES, npub, 1U, k); - if (mlen != NULL) { - *mlen = clen - crypto_aead_chacha20poly1305_ABYTES; + (m, c, mlen, npub, 1U, k); + if (mlen_p != NULL) { + *mlen_p = mlen; + } + return 0; +} + +int +crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m, + unsigned long long *mlen_p, + unsigned char *nsec, + const unsigned char *c, + unsigned long long clen, + const unsigned char *ad, + unsigned long long adlen, + const unsigned char *npub, + const unsigned char *k) +{ + crypto_onetimeauth_poly1305_state state; + unsigned char block0[64U]; + unsigned char slen[8U]; + unsigned char mac[crypto_aead_chacha20poly1305_ABYTES]; + unsigned long long mlen; + int ret; + + (void) nsec; + if (mlen_p != NULL) { + *mlen_p = 0ULL; + } + if (clen < crypto_aead_chacha20poly1305_ABYTES) { + return -1; + } + crypto_stream_chacha20_ietf(block0, sizeof block0, npub, k); + crypto_onetimeauth_poly1305_init(&state, block0); + sodium_memzero(block0, sizeof block0); + + crypto_onetimeauth_poly1305_update(&state, ad, adlen); + crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - adlen) & 0xf); + + mlen = clen - crypto_aead_chacha20poly1305_ABYTES; + crypto_onetimeauth_poly1305_update(&state, c, mlen); + crypto_onetimeauth_poly1305_update(&state, _pad0, (0x10 - mlen) & 0xf); + + _u64_le_from_ull(slen, adlen); + crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); + + _u64_le_from_ull(slen, mlen); + crypto_onetimeauth_poly1305_update(&state, slen, sizeof slen); + + crypto_onetimeauth_poly1305_final(&state, mac); + sodium_memzero(&state, sizeof state); + + (void) sizeof(int[sizeof mac == 16U ? 1 : -1]); + ret = crypto_verify_16(mac, c + mlen); + sodium_memzero(mac, sizeof mac); + if (ret != 0) { + memset(m, 0, mlen); + return -1; + } + crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, npub, 1U, k); + if (mlen_p != NULL) { + *mlen_p = mlen; } return 0; } @@ -137,6 +252,11 @@ crypto_aead_chacha20poly1305_npubbytes(void) { return crypto_aead_chacha20poly1305_NPUBBYTES; } +size_t +crypto_aead_chacha20poly1305_ietf_npubbytes(void) { + return crypto_aead_chacha20poly1305_IETF_NPUBBYTES; +} + size_t crypto_aead_chacha20poly1305_nsecbytes(void) { return crypto_aead_chacha20poly1305_NSECBYTES; diff --git a/src/libsodium/crypto_stream/chacha20/ref/api.h b/src/libsodium/crypto_stream/chacha20/ref/api.h index 3d858670..d7290815 100644 --- a/src/libsodium/crypto_stream/chacha20/ref/api.h +++ b/src/libsodium/crypto_stream/chacha20/ref/api.h @@ -10,3 +10,13 @@ crypto_stream_chacha20_ref_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, uint64_t ic, const unsigned char *k); + +int +crypto_stream_chacha20_ietf_ref(unsigned char *c, unsigned long long clen, + const unsigned char *n, const unsigned char *k); + +int +crypto_stream_chacha20_ietf_ref_xor_ic(unsigned char *c, const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, uint32_t ic, + const unsigned char *k); diff --git a/src/libsodium/crypto_stream/chacha20/ref/stream_chacha20_ref.c b/src/libsodium/crypto_stream/chacha20/ref/stream_chacha20_ref.c index 967015f2..c7d6e39a 100644 --- a/src/libsodium/crypto_stream/chacha20/ref/stream_chacha20_ref.c +++ b/src/libsodium/crypto_stream/chacha20/ref/stream_chacha20_ref.c @@ -91,6 +91,15 @@ chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) x->input[15] = U8TO32_LITTLE(iv + 4); } +static void +chacha_ietf_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) +{ + x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter); + x->input[13] = U8TO32_LITTLE(iv + 0); + x->input[14] = U8TO32_LITTLE(iv + 4); + x->input[15] = U8TO32_LITTLE(iv + 8); +} + static void chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, unsigned long long bytes) { @@ -248,6 +257,25 @@ crypto_stream_chacha20_ref(unsigned char *c, unsigned long long clen, return 0; } +int +crypto_stream_chacha20_ietf_ref(unsigned char *c, unsigned long long clen, + const unsigned char *n, const unsigned char *k) +{ + struct chacha_ctx ctx; + + if (!clen) { + return 0; + } + (void) sizeof(int[crypto_stream_chacha20_KEYBYTES == 256 / 8 ? 1 : -1]); + chacha_keysetup(&ctx, k); + chacha_ietf_ivsetup(&ctx, n, NULL); + memset(c, 0, clen); + chacha_encrypt_bytes(&ctx, c, c, clen); + sodium_memzero(&ctx, sizeof ctx); + + return 0; +} + int crypto_stream_chacha20_ref_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, @@ -269,6 +297,29 @@ crypto_stream_chacha20_ref_xor_ic(unsigned char *c, const unsigned char *m, chacha_keysetup(&ctx, k); chacha_ivsetup(&ctx, n, ic_bytes); chacha_encrypt_bytes(&ctx, m, c, mlen); + + sodium_memzero(&ctx, sizeof ctx); + sodium_memzero(ic_bytes, sizeof ic_bytes); + + return 0; +} + +int +crypto_stream_chacha20_ietf_ref_xor_ic(unsigned char *c, const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, uint32_t ic, + const unsigned char *k) +{ + struct chacha_ctx ctx; + uint8_t ic_bytes[4]; + + if (!mlen) { + return 0; + } + U32TO8_LITTLE(ic_bytes, ic); + chacha_keysetup(&ctx, k); + chacha_ietf_ivsetup(&ctx, n, ic_bytes); + chacha_encrypt_bytes(&ctx, m, c, mlen); sodium_memzero(&ctx, sizeof ctx); sodium_memzero(ic_bytes, sizeof ic_bytes); diff --git a/src/libsodium/crypto_stream/chacha20/stream_chacha20_api.c b/src/libsodium/crypto_stream/chacha20/stream_chacha20_api.c index 412cdfab..14c51ca1 100644 --- a/src/libsodium/crypto_stream/chacha20/stream_chacha20_api.c +++ b/src/libsodium/crypto_stream/chacha20/stream_chacha20_api.c @@ -11,6 +11,11 @@ crypto_stream_chacha20_noncebytes(void) { return crypto_stream_chacha20_NONCEBYTES; } +size_t +crypto_stream_chacha20_ietf_noncebytes(void) { + return crypto_stream_chacha20_IETF_NONCEBYTES; +} + int crypto_stream_chacha20(unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k) @@ -18,6 +23,13 @@ crypto_stream_chacha20(unsigned char *c, unsigned long long clen, return crypto_stream_chacha20_ref(c, clen, n, k); } +int +crypto_stream_chacha20_ietf(unsigned char *c, unsigned long long clen, + const unsigned char *n, const unsigned char *k) +{ + return crypto_stream_chacha20_ietf_ref(c, clen, n, k); +} + int crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, @@ -27,6 +39,15 @@ crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m, return crypto_stream_chacha20_ref_xor_ic(c, m, mlen, n, ic, k); } +int +crypto_stream_chacha20_ietf_xor_ic(unsigned char *c, const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, uint32_t ic, + const unsigned char *k) +{ + return crypto_stream_chacha20_ietf_ref_xor_ic(c, m, mlen, n, ic, k); +} + int crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, @@ -34,3 +55,11 @@ crypto_stream_chacha20_xor(unsigned char *c, const unsigned char *m, { return crypto_stream_chacha20_ref_xor_ic(c, m, mlen, n, 0U, k); } + +int +crypto_stream_chacha20_ietf_xor(unsigned char *c, const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k) +{ + return crypto_stream_chacha20_ietf_ref_xor_ic(c, m, mlen, n, 0U, k); +} diff --git a/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h b/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h index b36807c6..49e6bd40 100644 --- a/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h +++ b/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h @@ -29,7 +29,7 @@ size_t crypto_aead_chacha20poly1305_abytes(void); SODIUM_EXPORT int crypto_aead_chacha20poly1305_encrypt(unsigned char *c, - unsigned long long *clen, + unsigned long long *clen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *ad, @@ -40,7 +40,7 @@ int crypto_aead_chacha20poly1305_encrypt(unsigned char *c, SODIUM_EXPORT int crypto_aead_chacha20poly1305_decrypt(unsigned char *m, - unsigned long long *mlen, + unsigned long long *mlen_p, unsigned char *nsec, const unsigned char *c, unsigned long long clen, @@ -48,6 +48,32 @@ int crypto_aead_chacha20poly1305_decrypt(unsigned char *m, unsigned long long adlen, const unsigned char *npub, const unsigned char *k); + +#define crypto_aead_chacha20poly1305_IETF_NPUBBYTES 12U +SODIUM_EXPORT +size_t crypto_aead_chacha20poly1305_ietf_npubbytes(void); + +SODIUM_EXPORT +int crypto_aead_chacha20poly1305_ietf_encrypt(unsigned char *c, + unsigned long long *clen_p, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *ad, + unsigned long long adlen, + const unsigned char *nsec, + const unsigned char *npub, + const unsigned char *k); + +SODIUM_EXPORT +int crypto_aead_chacha20poly1305_ietf_decrypt(unsigned char *m, + unsigned long long *mlen_p, + unsigned char *nsec, + const unsigned char *c, + unsigned long long clen, + const unsigned char *ad, + unsigned long long adlen, + const unsigned char *npub, + const unsigned char *k); #ifdef __cplusplus } #endif diff --git a/src/libsodium/include/sodium/crypto_stream_chacha20.h b/src/libsodium/include/sodium/crypto_stream_chacha20.h index 6b577fcc..612c4a74 100644 --- a/src/libsodium/include/sodium/crypto_stream_chacha20.h +++ b/src/libsodium/include/sodium/crypto_stream_chacha20.h @@ -28,6 +28,8 @@ size_t crypto_stream_chacha20_keybytes(void); SODIUM_EXPORT size_t crypto_stream_chacha20_noncebytes(void); +/* ChaCha20 with a 64-bit nonce and a 64-bit counter, as originally designed */ + SODIUM_EXPORT int crypto_stream_chacha20(unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k); @@ -42,6 +44,27 @@ int crypto_stream_chacha20_xor_ic(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, uint64_t ic, const unsigned char *k); + +/* ChaCha20 with a 96-bit nonce and a 32-bit counter (IETF) */ + +#define crypto_stream_chacha20_IETF_NONCEBYTES 12U +SODIUM_EXPORT +size_t crypto_stream_chacha20_ietf_noncebytes(void); + +SODIUM_EXPORT +int crypto_stream_chacha20_ietf(unsigned char *c, unsigned long long clen, + const unsigned char *n, const unsigned char *k); + +SODIUM_EXPORT +int crypto_stream_chacha20_ietf_xor(unsigned char *c, const unsigned char *m, + unsigned long long mlen, const unsigned char *n, + const unsigned char *k); + +SODIUM_EXPORT +int crypto_stream_chacha20_ietf_xor_ic(unsigned char *c, const unsigned char *m, + unsigned long long mlen, + const unsigned char *n, uint32_t ic, + const unsigned char *k); #ifdef __cplusplus } #endif diff --git a/test/default/aead_chacha20poly1305.c b/test/default/aead_chacha20poly1305.c index 83374b20..d82319b2 100644 --- a/test/default/aead_chacha20poly1305.c +++ b/test/default/aead_chacha20poly1305.c @@ -2,24 +2,21 @@ #define TEST_NAME "aead_chacha20poly1305" #include "cmptest.h" -static unsigned char firstkey[crypto_aead_chacha20poly1305_KEYBYTES] - = { 0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf, - 0x57, 0xf3, 0xbe, 0x3b, 0x50, 0x06, 0xda, 0x37, 0x1e, 0xce, 0x27, - 0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 0x10, 0x0a, 0x10, 0x07 }; - -static unsigned char m[10U] - = { 0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca }; - -static unsigned char nonce[crypto_aead_chacha20poly1305_NPUBBYTES] - = { 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a }; - -static unsigned char ad[10U] - = { 0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0 }; - -static unsigned char c[10U + crypto_aead_chacha20poly1305_ABYTES]; - -int main(void) +static int +tv(void) { + static unsigned char firstkey[crypto_aead_chacha20poly1305_KEYBYTES] + = { 0x42, 0x90, 0xbc, 0xb1, 0x54, 0x17, 0x35, 0x31, 0xf3, 0x14, 0xaf, + 0x57, 0xf3, 0xbe, 0x3b, 0x50, 0x06, 0xda, 0x37, 0x1e, 0xce, 0x27, + 0x2a, 0xfa, 0x1b, 0x5d, 0xbd, 0xd1, 0x10, 0x0a, 0x10, 0x07 }; + static unsigned char m[10U] + = { 0x86, 0xd0, 0x99, 0x74, 0x84, 0x0b, 0xde, 0xd2, 0xa5, 0xca }; + static unsigned char nonce[crypto_aead_chacha20poly1305_NPUBBYTES] + = { 0xcd, 0x7c, 0xf6, 0x7b, 0xe3, 0x9c, 0x79, 0x4a }; + static unsigned char ad[10U] + = { 0x87, 0xe2, 0x29, 0xd4, 0x50, 0x08, 0x45, 0xa0, 0x79, 0xc0 }; + static unsigned char c[10U + crypto_aead_chacha20poly1305_ABYTES]; + unsigned char m2[10U]; unsigned long long clen; unsigned long long m2len; @@ -126,3 +123,139 @@ int main(void) return 0; } + +static int +tv_ietf(void) +{ + static unsigned char firstkey[crypto_aead_chacha20poly1305_KEYBYTES] + = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + }; +#define MESSAGE "Ladies and Gentlemen of the class of '99: If I could offer you " \ +"only one tip for the future, sunscreen would be it." + static unsigned char m[114U]; + static unsigned char nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] + = { 0x07, 0x00, 0x00, 0x00, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }; + static unsigned char ad[12U] + = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }; + static unsigned char c[114U + crypto_aead_chacha20poly1305_ABYTES]; + + unsigned char m2[114U]; + unsigned long long clen; + unsigned long long m2len; + size_t i; + + assert(sizeof MESSAGE - 1U == sizeof m); + memcpy(m, MESSAGE, sizeof m); + crypto_aead_chacha20poly1305_ietf_encrypt(c, &clen, m, sizeof m, ad, sizeof ad, + NULL, nonce, firstkey); + if (clen != sizeof m + crypto_aead_chacha20poly1305_abytes()) { + printf("clen is not properly set\n"); + } + for (i = 0U; i < sizeof c; ++i) { + printf(",0x%02x", (unsigned int)c[i]); + if (i % 8 == 7) { + printf("\n"); + } + } + printf("\n"); + + if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, &m2len, NULL, c, sizeof c, ad, + sizeof ad, nonce, firstkey) != 0) { + printf("crypto_aead_chacha20poly1305_ietf_decrypt() failed\n"); + } + if (m2len != sizeof c - crypto_aead_chacha20poly1305_abytes()) { + printf("m2len is not properly set\n"); + } + if (memcmp(m, m2, sizeof m) != 0) { + printf("m != m2\n"); + } + + for (i = 0U; i < sizeof c; i++) { + c[i] ^= (i + 1U); + if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, NULL, NULL, c, sizeof c, + ad, sizeof ad, nonce, firstkey) + == 0 || memcmp(m, m2, sizeof m) == 0) { + printf("message can be forged\n"); + } + c[i] ^= (i + 1U); + } + crypto_aead_chacha20poly1305_ietf_encrypt(c, &clen, m, sizeof m, NULL, 0U, NULL, + nonce, firstkey); + if (clen != sizeof m + crypto_aead_chacha20poly1305_abytes()) { + printf("clen is not properly set (adlen=0)\n"); + } + for (i = 0U; i < sizeof c; ++i) { + printf(",0x%02x", (unsigned int)c[i]); + if (i % 8 == 7) { + printf("\n"); + } + } + printf("\n"); + if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, &m2len, NULL, c, sizeof c, + NULL, 0U, nonce, firstkey) != 0) { + printf("crypto_aead_chacha20poly1305_ietf_decrypt() failed (adlen=0)\n"); + } + if (m2len != sizeof c - crypto_aead_chacha20poly1305_abytes()) { + printf("m2len is not properly set (adlen=0)\n"); + } + if (memcmp(m, m2, sizeof m) != 0) { + printf("m != m2 (adlen=0)\n"); + } + + if (crypto_aead_chacha20poly1305_ietf_decrypt( + m2, &m2len, NULL, c, crypto_aead_chacha20poly1305_ABYTES / 2, NULL, + 0U, nonce, firstkey) != -1) { + printf("crypto_aead_chacha20poly1305_ietf_decrypt() worked with a short " + "ciphertext\n"); + } + if (crypto_aead_chacha20poly1305_ietf_decrypt(m2, &m2len, NULL, c, 0U, NULL, 0U, + nonce, firstkey) != -1) { + printf("crypto_aead_chacha20poly1305_ietf_decrypt() worked with an empty " + "ciphertext\n"); + } + + memcpy(c, m, sizeof m); + crypto_aead_chacha20poly1305_ietf_encrypt(c, &clen, c, sizeof m, NULL, 0U, NULL, + nonce, firstkey); + if (clen != sizeof m + crypto_aead_chacha20poly1305_abytes()) { + printf("clen is not properly set (adlen=0)\n"); + } + for (i = 0U; i < sizeof c; ++i) { + printf(",0x%02x", (unsigned int)c[i]); + if (i % 8 == 7) { + printf("\n"); + } + } + printf("\n"); + + if (crypto_aead_chacha20poly1305_ietf_decrypt(c, &m2len, NULL, c, sizeof c, + NULL, 0U, nonce, firstkey) != 0) { + printf("crypto_aead_chacha20poly1305_ietf_decrypt() failed (adlen=0)\n"); + } + if (m2len != sizeof c - crypto_aead_chacha20poly1305_abytes()) { + printf("m2len is not properly set (adlen=0)\n"); + } + if (memcmp(m, c, sizeof m) != 0) { + printf("m != c (adlen=0)\n"); + } + + assert(crypto_aead_chacha20poly1305_keybytes() > 0U); + assert(crypto_aead_chacha20poly1305_ietf_npubbytes() > 0U); + assert(crypto_aead_chacha20poly1305_nsecbytes() == 0U); + + return 0; +} + +int +main(void) +{ + tv(); + tv_ietf(); + + return 0; +} diff --git a/test/default/aead_chacha20poly1305.exp b/test/default/aead_chacha20poly1305.exp index 9f90a523..1c6131ff 100644 --- a/test/default/aead_chacha20poly1305.exp +++ b/test/default/aead_chacha20poly1305.exp @@ -10,3 +10,54 @@ ,0x62,0xa4,0x69,0xe7,0x78,0x9b,0xcd,0x95 ,0x4e,0x65,0x8e,0xd3,0x84,0x23,0xe2,0x31 ,0x61,0xdc +,0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb +,0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2 +,0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe +,0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6 +,0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12 +,0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b +,0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29 +,0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36 +,0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c +,0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58 +,0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94 +,0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc +,0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d +,0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b +,0x61,0x16,0x1a,0xe1,0x0b,0x59,0x4f,0x09 +,0xe2,0x6a,0x7e,0x90,0x2e,0xcb,0xd0,0x60 +,0x06,0x91 +,0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb +,0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2 +,0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe +,0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6 +,0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12 +,0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b +,0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29 +,0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36 +,0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c +,0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58 +,0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94 +,0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc +,0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d +,0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b +,0x61,0x16,0x6a,0x23,0xa4,0x68,0x1f,0xd5 +,0x94,0x56,0xae,0xa1,0xd2,0x9f,0x82,0x47 +,0x72,0x16 +,0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb +,0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2 +,0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe +,0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6 +,0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12 +,0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b +,0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29 +,0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36 +,0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c +,0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58 +,0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94 +,0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc +,0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d +,0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b +,0x61,0x16,0x6a,0x23,0xa4,0x68,0x1f,0xd5 +,0x94,0x56,0xae,0xa1,0xd2,0x9f,0x82,0x47 +,0x72,0x16 diff --git a/test/default/chacha20.c b/test/default/chacha20.c index b4334a83..9e153555 100644 --- a/test/default/chacha20.c +++ b/test/default/chacha20.c @@ -2,7 +2,8 @@ #define TEST_NAME "chacha20" #include "cmptest.h" -static void tv(void) +static +void tv(void) { static struct { const char *key_hex; @@ -21,8 +22,8 @@ static void tv(void) unsigned char key[crypto_stream_chacha20_KEYBYTES]; unsigned char nonce[crypto_stream_chacha20_NONCEBYTES]; unsigned char out[160]; - char out_hex[160 * 2 + 1]; - size_t i = 0U; + char out_hex[160 * 2 + 1]; + size_t i = 0U; do { sodium_hex2bin((unsigned char *)key, sizeof key, tests[i].key_hex, @@ -54,12 +55,78 @@ static void tv(void) printf("[%s]\n", out_hex); }; -int main(void) +static +void tv_ietf(void) +{ + static struct { + const char *key_hex; + const char *nonce_hex; + uint32_t ic; + } tests[] + = { { "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + 0U }, + { "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + 1U }, + { "0000000000000000000000000000000000000000000000000000000000000001", + "000000000000000000000000", + 1U }, + { "00ff000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + 2U }, + { "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000002", + 0U }, + { "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "000000090000004a00000000", + 1U }}; + unsigned char key[crypto_stream_chacha20_KEYBYTES]; + unsigned char nonce[crypto_stream_chacha20_IETF_NONCEBYTES]; + unsigned char out[160]; + char out_hex[160 * 2 + 1]; + size_t i = 0U; + + do { + sodium_hex2bin((unsigned char *)key, sizeof key, tests[i].key_hex, + strlen(tests[i].key_hex), ": ", NULL, NULL); + sodium_hex2bin(nonce, sizeof nonce, tests[i].nonce_hex, + strlen(tests[i].nonce_hex), ": ", NULL, NULL); + memset(out, 0, sizeof out); + crypto_stream_chacha20_ietf_xor_ic(out, out, sizeof out, nonce, tests[i].ic, key); + sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); + printf("[%s]\n", out_hex); + } while (++i < (sizeof tests) / (sizeof tests[0])); + + memset(out, 0x42, sizeof out); + + assert(crypto_stream_chacha20_ietf(out, 0U, nonce, key) == 0); + assert(crypto_stream_chacha20_ietf_xor(out, out, 0U, nonce, key) == 0); + assert(crypto_stream_chacha20_ietf_xor(out, out, 0U, nonce, key) == 0); + assert(crypto_stream_chacha20_ietf_xor_ic(out, out, 0U, nonce, 1U, key) == 0); + + crypto_stream_chacha20_ietf_xor(out, out, sizeof out, nonce, key); + sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); + printf("[%s]\n", out_hex); + + crypto_stream_chacha20_ietf_xor_ic(out, out, sizeof out, nonce, 0U, key); + sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); + printf("[%s]\n", out_hex); + + crypto_stream_chacha20_ietf_xor_ic(out, out, sizeof out, nonce, 1U, key); + sodium_bin2hex(out_hex, sizeof out_hex, out, sizeof out); + printf("[%s]\n", out_hex); +}; + +int +main(void) { tv(); + tv_ietf(); assert(crypto_stream_chacha20_keybytes() > 0U); assert(crypto_stream_chacha20_noncebytes() > 0U); + assert(crypto_stream_chacha20_ietf_noncebytes() > 0U); return 0; } diff --git a/test/default/chacha20.exp b/test/default/chacha20.exp index b6694302..59a51fed 100644 --- a/test/default/chacha20.exp +++ b/test/default/chacha20.exp @@ -6,3 +6,12 @@ [b5dae3cbb3d7a42bc0521db92649f5373d15dfe15440bed1ae43ee14ba18818376e616393179040372008b06420b552b4791fc1ba85e11b31b54571e69aa66587a42c9d864fe77d65c6606553ec89c24cb9cd7640bc49b1acbb922aa046b8bffd818895e835afc147cfbf1e6e630ba6c4be5a53a0b69146cb5514cca9da27385dffb96b585eadb5759d8051270f47d81c7661da216a19f18d5e7b734bc440267] [42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242] [7a42c9d864fe77d65c6606553ec89c24cb9cd7640bc49b1acbb922aa046b8bffd818895e835afc147cfbf1e6e630ba6c4be5a53a0b69146cb5514cca9da27385dffb96b585eadb5759d8051270f47d81c7661da216a19f18d5e7b734bc440267918c466e1428f08745f37a99c77c7f2b1b244bd4162e8b86e4a8bf85358202954ced04b52fef7b3ba787744e715554285ecb0ed6e133c528d69d346abc0ce8b0] +[76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee65869f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d] +[9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f21320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a4] +[3aeb5224ecf849929b9d828db1ced4dd832025e8018b8160b82284f3c949aa5a8eca00bbb4a73bdad192b5c42f73f2fd4e273644c8b36125a64addeb006c13a096d68b9ff7b57e7090f880392effd5b297a83bbaf2fbe8cf5d4618965e3dc776cd430d9b4e7eda8a767fb0e860319aadb5fd96a855de1fbfc92cb0489190cfdd87da6dbf1f736a2d499941ca097e5170bd685578611323120cebf296181ed4f5] +[72d54dfbf12ec44b362692df94137f328fea8da73990265ec1bbbea1ae9af0ca13b25aa26cb4a648cb9b9d1be65b2c0924a66c54d545ec1b7374f4872e99f096bf74dbd52cc4fc95ceb6097fe5e65358c9dbc0a5ecbf7894a132a9a54ae3e951f2e9f209aa9c3d9a877ac9dab62433d2961a17d103e455dfb7337c90f6857aad233065955a212b5c7a8eab4dc8a629e5b6b8ba914afd06de7177054b33d21c96] +[c2c64d378cd536374ae204b9ef933fcd1a8b2288b3dfa49672ab765b54ee27c78a970e0e955c14f3a88e741b97c286f75f8fc299e8148362fa198a39531bed6d1a91288c874ec254f322c2a197340c55bb3e9b3998f7de2309486a0bb494abd20c9c5ef99c1370d61e77f408ac5514f49202bcc6828d45409d2d1416f8ae106b06ebd2541256264fa415bd54cb12e1d4449ed85299a1b7a249b75ff6c89b2e3f] +[10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8e721f89255f9c486bf21679c683d4f9c5cf2fa27865526005b06ca374c86af3bdcbfbdcb83be65862ed5c20eae5a43241d6a92da6dca9a156be25297f51c2718] +[c89ed3bfddb6b2b7594def12bd579475a64cbfe0448e1085c1e50042127e57c08fda71743f4816973f7edcdbcd0b4ca4dee10e5dbbab7be517c6876f2b48779652b3a5a693791b57124d9f5de16233868593b68571822a414660e8d881962e0c90c0260445dde84b568095479bc940e0f750de939c540cfb8992c1aae0127e0c48cac1357b95fd0cba8eeef2a869fb94df1481d6e8775fbfe7fd07dd486cddaa] +[42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242] +[52b3a5a693791b57124d9f5de16233868593b68571822a414660e8d881962e0c90c0260445dde84b568095479bc940e0f750de939c540cfb8992c1aae0127e0c48cac1357b95fd0cba8eeef2a869fb94df1481d6e8775fbfe7fd07dd486cddaaa563bad017bb86c4fd6325de2a7f0dde1eb0b865c4176442194488750ec4ed799efdff89c1fc27c46c97804cec1801665f28d0982f88d85729a010d5b75e655a]