nisse@lysator.liu.se (Niels Möller) writes:
Nikos Mavrogiannopoulos nmav@gnutls.org 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 nisse@lysator.liu.se + + 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 nisse@lysator.liu.se
* 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); }