Commit bb6be1a9 authored by Niels Möller's avatar Niels Möller

Update chacha-poly1305 for draft-irtf-cfrg-chacha20-poly1305-08.

parent c6319980
2015-01-30 Niels Möller <nisse@lysator.liu.se> 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-set-nonce.c (chacha_set_nonce96): New function.
* chacha.h (CHACHA_NONCE96_SIZE): New constant. * chacha.h (CHACHA_NONCE96_SIZE): New constant.
* testsuite/chacha-test.c: Add test for chacha with 96-bit nonce. * testsuite/chacha-test.c: Add test for chacha with 96-bit nonce.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
AEAD mechanism based on chacha and poly1305. 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. This file is part of GNU Nettle.
...@@ -31,6 +31,20 @@ ...@@ -31,6 +31,20 @@
not, see http://www.gnu.org/licenses/. 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 #if HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
...@@ -62,7 +76,7 @@ chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx, ...@@ -62,7 +76,7 @@ chacha_poly1305_set_nonce (struct chacha_poly1305_ctx *ctx,
uint8_t subkey[32]; uint8_t subkey[32];
} u; } u;
chacha_set_nonce (&ctx->chacha, nonce); chacha_set_nonce96 (&ctx->chacha, nonce);
/* Generate authentication key */ /* Generate authentication key */
_chacha_core (u.x, ctx->chacha.state, CHACHA_ROUNDS); _chacha_core (u.x, ctx->chacha.state, CHACHA_ROUNDS);
poly1305_set_key (&ctx->poly1305, u.subkey); poly1305_set_key (&ctx->poly1305, u.subkey);
...@@ -84,6 +98,17 @@ poly1305_update (struct chacha_poly1305_ctx *ctx, ...@@ -84,6 +98,17 @@ poly1305_update (struct chacha_poly1305_ctx *ctx,
MD_UPDATE (ctx, length, data, COMPRESS, (void) 0); 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 void
chacha_poly1305_update (struct chacha_poly1305_ctx *ctx, chacha_poly1305_update (struct chacha_poly1305_ctx *ctx,
size_t length, const uint8_t *data) size_t length, const uint8_t *data)
...@@ -102,12 +127,8 @@ chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx, ...@@ -102,12 +127,8 @@ chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx,
return; return;
assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0); assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
if (!ctx->data_size) poly1305_pad (ctx);
{
uint8_t buf[8];
LE_WRITE_UINT64 (buf, ctx->auth_size);
poly1305_update (ctx, sizeof(buf), buf);
}
chacha_crypt (&ctx->chacha, length, dst, src); chacha_crypt (&ctx->chacha, length, dst, src);
poly1305_update (ctx, length, dst); poly1305_update (ctx, length, dst);
ctx->data_size += length; ctx->data_size += length;
...@@ -121,12 +142,8 @@ chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx, ...@@ -121,12 +142,8 @@ chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx,
return; return;
assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0); assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
if (!ctx->data_size) poly1305_pad (ctx);
{
uint8_t buf[8];
LE_WRITE_UINT64 (buf, ctx->auth_size);
poly1305_update (ctx, sizeof(buf), buf);
}
poly1305_update (ctx, length, src); poly1305_update (ctx, length, src);
chacha_crypt (&ctx->chacha, length, dst, src); chacha_crypt (&ctx->chacha, length, dst, src);
ctx->data_size += length; ctx->data_size += length;
...@@ -136,27 +153,14 @@ void ...@@ -136,27 +153,14 @@ void
chacha_poly1305_digest (struct chacha_poly1305_ctx *ctx, chacha_poly1305_digest (struct chacha_poly1305_ctx *ctx,
size_t length, uint8_t *digest) size_t length, uint8_t *digest)
{ {
uint8_t buf[8]; uint8_t buf[16];
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);
/* Final bytes. FIXME: Duplicated in poly1305_aes128.c */ poly1305_pad (ctx);
if (ctx->index > 0) LE_WRITE_UINT64 (buf, ctx->auth_size);
{ LE_WRITE_UINT64 (buf + 8, ctx->data_size);
assert (ctx->index < POLY1305_BLOCK_SIZE);
ctx->block[ctx->index] = 1; _poly1305_block (&ctx->poly1305, buf, 1);
memset (ctx->block + ctx->index + 1,
0, POLY1305_BLOCK_SIZE - 1 - ctx->index);
_poly1305_block (&ctx->poly1305, ctx->block, 0);
}
poly1305_digest (&ctx->poly1305, &ctx->s); poly1305_digest (&ctx->poly1305, &ctx->s);
memcpy (digest, &ctx->s.b, length); memcpy (digest, &ctx->s.b, length);
} }
...@@ -53,7 +53,7 @@ extern "C" { ...@@ -53,7 +53,7 @@ extern "C" {
#define CHACHA_POLY1305_BLOCK_SIZE 64 #define CHACHA_POLY1305_BLOCK_SIZE 64
/* FIXME: Any need for 128-bit variant? */ /* FIXME: Any need for 128-bit variant? */
#define CHACHA_POLY1305_KEY_SIZE 32 #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 #define CHACHA_POLY1305_DIGEST_SIZE 16
struct chacha_poly1305_ctx struct chacha_poly1305_ctx
......
...@@ -4,13 +4,30 @@ ...@@ -4,13 +4,30 @@
void void
test_main(void) test_main(void)
{ {
/* From draft-agl-tls-chacha20poly1305-04 */ /* From draft-irtf-cfrg-chacha20-poly1305-08 */
test_aead (&nettle_chacha_poly1305, NULL, test_aead (&nettle_chacha_poly1305, NULL,
SHEX("4290bcb154173531f314af57f3be3b50" SHEX("8081828384858687 88898a8b8c8d8e8f"
"06da371ece272afa1b5dbdd1100a1007"), /* key */ "9091929394959697 98999a9b9c9d9e9f"),
SHEX("87e229d4500845a079c0"), /* auth data */ SHEX("50515253c0c1c2c3 c4c5c6c7"),
SHEX("86d09974840bded2a5ca"), /* plain text */ SHEX("4c61646965732061 6e642047656e746c"
SHEX("e3e446f7ede9a19b62a4"), /* ciphertext */ "656d656e206f6620 74686520636c6173"
SHEX("cd7cf67be39c794a"), /* nonce */ "73206f6620273939 3a20496620492063"
SHEX("677dabf4e3d24b876bb284753896e1d6")); /* tag */ "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"));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment