[email protected] (Niels Möller) writes: > Nikos Mavrogiannopoulos <[email protected]> writes: > >> For me OCB is low priority. > > Ok, let's leave ocb for now (I will still consider it if someone else > writes a complete patch, including testcases and docs, in time for the > release). > >> Chacha with poly (not in the list above) however is more important to me >> to implement the final draft (on the current state the algorithm is >> fixed, only typos and other non-essential parts can be changed) >> https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-08 > > Thanks for the reminder. I agree that makes a lot of sense for 3.1. You > have done some work to update of Nettle's implementation, but I don't > remember the status?
Patch below (and also in the "chacha96"-branch in the public repo). Any comments before I merge it? In particular, is chacha_set_nonce96 a good name and function? Regards, /Niels diff --git a/ChangeLog b/ChangeLog index 00007fe..9fd2d8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2015-01-30 Niels Möller <[email protected]> + + Update chacha-poly1305 for draft-irtf-cfrg-chacha20-poly1305-08. + * chacha-poly1305.h (CHACHA_POLY1305_NONCE_SIZE): Increase to 12 + bytes, i.e., CHACHA_NONCE96_SIZE. + * chacha-poly1305.c (chacha_poly1305_set_nonce): Use + chacha_set_nonce96. + (poly1305_pad): New function. + (chacha_poly1305_encrypt): Use poly1305_pad. + (chacha_poly1305_digest): Call poly1305_pad, and format length + fields as a single poly1305 block. + + * chacha-set-nonce.c (chacha_set_nonce96): New function. + * chacha.h (CHACHA_NONCE96_SIZE): New constant. + * testsuite/chacha-test.c: Add test for chacha with 96-bit nonce. + 2015-01-27 Niels Möller <[email protected]> * ecc.h: Deleted declarations of unused itch functions. Moved diff --git a/chacha-poly1305.c b/chacha-poly1305.c index 35c4bfe..c5109b8 100644 --- a/chacha-poly1305.c +++ b/chacha-poly1305.c @@ -2,7 +2,7 @@ AEAD mechanism based on chacha and poly1305. - Copyright (C) 2014 Niels Möller + Copyright (C) 2014, 2015 Niels Möller This file is part of GNU Nettle. @@ -31,6 +31,20 @@ not, see http://www.gnu.org/licenses/. */ +/* This implements chacha-poly1305 according to + draft-irtf-cfrg-chacha20-poly1305-08. The inputs to poly1305 are: + + associated data + zero padding + ciphertext + zero padding + length of associated data (64-bit, little endian) + length of ciphertext (64-bit, little endian) + + where the padding fields are 0-15 zero bytes, filling up to a + 16-byte boundary. +*/ + #if HAVE_CONFIG_H # include "config.h" #endif @@ -62,7 +76,7 @@ chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx, uint8_t subkey[32]; } u; - chacha_set_nonce (&ctx->chacha, nonce); + chacha_set_nonce96 (&ctx->chacha, nonce); /* Generate authentication key */ _chacha_core (u.x, ctx->chacha.state, CHACHA_ROUNDS); poly1305_set_key (&ctx->poly1305, u.subkey); @@ -84,6 +98,17 @@ poly1305_update (struct chacha_poly1305_ctx *ctx, MD_UPDATE (ctx, length, data, COMPRESS, (void) 0); } +static void +poly1305_pad (struct chacha_poly1305_ctx *ctx) +{ + if (ctx->index) + { + memset (ctx->block + ctx->index, 0, + POLY1305_BLOCK_SIZE - ctx->index); + _poly1305_block(&ctx->poly1305, ctx->block, 1); + ctx->index = 0; + } +} void chacha_poly1305_update (struct chacha_poly1305_ctx *ctx, size_t length, const uint8_t *data) @@ -102,12 +127,8 @@ chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx, return; assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0); - if (!ctx->data_size) - { - uint8_t buf[8]; - LE_WRITE_UINT64 (buf, ctx->auth_size); - poly1305_update (ctx, sizeof(buf), buf); - } + poly1305_pad (ctx); + chacha_crypt (&ctx->chacha, length, dst, src); poly1305_update (ctx, length, dst); ctx->data_size += length; @@ -121,12 +142,8 @@ chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx, return; assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0); - if (!ctx->data_size) - { - uint8_t buf[8]; - LE_WRITE_UINT64 (buf, ctx->auth_size); - poly1305_update (ctx, sizeof(buf), buf); - } + poly1305_pad (ctx); + poly1305_update (ctx, length, src); chacha_crypt (&ctx->chacha, length, dst, src); ctx->data_size += length; @@ -136,27 +153,14 @@ void chacha_poly1305_digest (struct chacha_poly1305_ctx *ctx, size_t length, uint8_t *digest) { - uint8_t buf[8]; - if (!ctx->data_size) - { - LE_WRITE_UINT64 (buf, ctx->auth_size); - poly1305_update (ctx, sizeof(buf), buf); - } - LE_WRITE_UINT64 (buf, ctx->data_size); - poly1305_update (ctx, sizeof(buf), buf); + uint8_t buf[16]; - /* Final bytes. FIXME: Duplicated in poly1305_aes128.c */ - if (ctx->index > 0) - { - assert (ctx->index < POLY1305_BLOCK_SIZE); + poly1305_pad (ctx); + LE_WRITE_UINT64 (buf, ctx->auth_size); + LE_WRITE_UINT64 (buf + 8, ctx->data_size); - ctx->block[ctx->index] = 1; - memset (ctx->block + ctx->index + 1, - 0, POLY1305_BLOCK_SIZE - 1 - ctx->index); + _poly1305_block (&ctx->poly1305, buf, 1); - _poly1305_block (&ctx->poly1305, ctx->block, 0); - } - poly1305_digest (&ctx->poly1305, &ctx->s); memcpy (digest, &ctx->s.b, length); } diff --git a/chacha-poly1305.h b/chacha-poly1305.h index 9c2688b..ce40b77 100644 --- a/chacha-poly1305.h +++ b/chacha-poly1305.h @@ -53,7 +53,7 @@ extern "C" { #define CHACHA_POLY1305_BLOCK_SIZE 64 /* FIXME: Any need for 128-bit variant? */ #define CHACHA_POLY1305_KEY_SIZE 32 -#define CHACHA_POLY1305_NONCE_SIZE CHACHA_NONCE_SIZE +#define CHACHA_POLY1305_NONCE_SIZE CHACHA_NONCE96_SIZE #define CHACHA_POLY1305_DIGEST_SIZE 16 struct chacha_poly1305_ctx diff --git a/chacha-set-nonce.c b/chacha-set-nonce.c index e73babc..607f176 100644 --- a/chacha-set-nonce.c +++ b/chacha-set-nonce.c @@ -59,3 +59,12 @@ chacha_set_nonce(struct chacha_ctx *ctx, const uint8_t *nonce) ctx->state[14] = LE_READ_UINT32(nonce + 0); ctx->state[15] = LE_READ_UINT32(nonce + 4); } + +void +chacha_set_nonce96(struct chacha_ctx *ctx, const uint8_t *nonce) +{ + ctx->state[12] = 0; + ctx->state[13] = LE_READ_UINT32(nonce + 0); + ctx->state[14] = LE_READ_UINT32(nonce + 4); + ctx->state[15] = LE_READ_UINT32(nonce + 8); +} diff --git a/chacha.h b/chacha.h index 41df707..3f08283 100644 --- a/chacha.h +++ b/chacha.h @@ -45,6 +45,7 @@ extern "C" { /* Name mangling */ #define chacha_set_key nettle_chacha_set_key #define chacha_set_nonce nettle_chacha_set_nonce +#define chacha_set_nonce96 nettle_chacha_set_nonce96 #define chacha_crypt nettle_chacha_crypt #define _chacha_core _nettle_chacha_core @@ -52,6 +53,7 @@ extern "C" { #define CHACHA_KEY_SIZE 32 #define CHACHA_BLOCK_SIZE 64 #define CHACHA_NONCE_SIZE 8 +#define CHACHA_NONCE96_SIZE 12 #define _CHACHA_STATE_LENGTH 16 @@ -78,6 +80,9 @@ void chacha_set_nonce(struct chacha_ctx *ctx, const uint8_t *nonce); void +chacha_set_nonce96(struct chacha_ctx *ctx, const uint8_t *nonce); + +void chacha_crypt(struct chacha_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src); diff --git a/testsuite/chacha-poly1305-test.c b/testsuite/chacha-poly1305-test.c index 2f320f3..313e822 100644 --- a/testsuite/chacha-poly1305-test.c +++ b/testsuite/chacha-poly1305-test.c @@ -4,13 +4,30 @@ void test_main(void) { - /* From draft-agl-tls-chacha20poly1305-04 */ + /* From draft-irtf-cfrg-chacha20-poly1305-08 */ test_aead (&nettle_chacha_poly1305, NULL, - SHEX("4290bcb154173531f314af57f3be3b50" - "06da371ece272afa1b5dbdd1100a1007"), /* key */ - SHEX("87e229d4500845a079c0"), /* auth data */ - SHEX("86d09974840bded2a5ca"), /* plain text */ - SHEX("e3e446f7ede9a19b62a4"), /* ciphertext */ - SHEX("cd7cf67be39c794a"), /* nonce */ - SHEX("677dabf4e3d24b876bb284753896e1d6")); /* tag */ + SHEX("8081828384858687 88898a8b8c8d8e8f" + "9091929394959697 98999a9b9c9d9e9f"), + SHEX("50515253c0c1c2c3 c4c5c6c7"), + SHEX("4c61646965732061 6e642047656e746c" + "656d656e206f6620 74686520636c6173" + "73206f6620273939 3a20496620492063" + "6f756c64206f6666 657220796f75206f" + "6e6c79206f6e6520 74697020666f7220" + "7468652066757475 72652c2073756e73" + "637265656e20776f 756c642062652069" + "742e"), + SHEX("d31a8d34648e60db7b86afbc53ef7ec2" + "a4aded51296e08fea9e2b5a736ee62d6" + "3dbea45e8ca9671282fafb69da92728b" + "1a71de0a9e060b2905d6a5b67ecd3b36" + "92ddbd7f2d778b8c9803aee328091b58" + "fab324e4fad675945585808b4831d7bc" + "3ff4def08e4b7a9de576d26586cec64b" + "6116"), + /* The draft splits the nonce into a "common part" and an + iv, and it seams the "common part" is the first 4 + bytes. */ + SHEX("0700000040414243 44454647"), + SHEX("1ae10b594f09e26a 7e902ecbd0600691")); } diff --git a/testsuite/chacha-test.c b/testsuite/chacha-test.c index 8c5630d..9edb941 100644 --- a/testsuite/chacha-test.c +++ b/testsuite/chacha-test.c @@ -44,20 +44,30 @@ test_chacha(const struct tstring *key, const struct tstring *nonce, ASSERT (key->length == CHACHA_KEY_SIZE); chacha_set_key (&ctx, key->data); - ASSERT (nonce->length == CHACHA_NONCE_SIZE); if (rounds == 20) { uint8_t *data = xalloc (expected->length + 2); - data++; size_t length; + data++; for (length = 1; length <= expected->length; length++) { data[-1] = 17; memset (data, 0, length); data[length] = 17; - chacha_set_nonce(&ctx, nonce->data); + if (nonce->length == CHACHA_NONCE_SIZE) + chacha_set_nonce(&ctx, nonce->data); + else if (nonce->length == CHACHA_NONCE96_SIZE) + { + chacha_set_nonce96(&ctx, nonce->data); + /* Use initial counter 1, for + draft-irtf-cfrg-chacha20-poly1305-08 test cases. */ + ctx.state[12]++; + } + else + die ("Bad nonce size %u.\n", (unsigned) nonce->length); + chacha_crypt (&ctx, length, data, data); ASSERT (data[-1] == 17); @@ -84,6 +94,7 @@ test_chacha(const struct tstring *key, const struct tstring *nonce, numbers of rounds. */ uint32_t out[_CHACHA_STATE_LENGTH]; ASSERT (expected->length == CHACHA_BLOCK_SIZE); + ASSERT (nonce->length == CHACHA_NONCE_SIZE); chacha_set_nonce(&ctx, nonce->data); _chacha_core (out, ctx.state, rounds); @@ -622,4 +633,14 @@ test_main(void) "ae2c4c90225ba9ea 14d518f55929dea0" "98ca7a6ccfe61227 053c84e49a4a3332"), 20); + + /* From draft-irtf-cfrg-chacha20-poly1305-08, with 96-bit nonce */ + test_chacha(SHEX("0001020304050607 08090a0b0c0d0e0f" + "1011121314151617 18191a1b1c1d1e1f"), + SHEX("000000090000004a 00000000"), + SHEX("10f1e7e4d13b5915 500fdd1fa32071c4" + "c7d1f4c733c06803 0422aa9ac3d46c4e" + "d2826446079faa09 14c2d705d98b02a2" + "b5129cd1de164eb9 cbd083e8a2503c4e"), + 20); } -- Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26. Internet email is subject to wholesale government surveillance. _______________________________________________ nettle-bugs mailing list [email protected] http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs
