diff options
Diffstat (limited to 'chacha-poly1305.c')
-rw-r--r-- | chacha-poly1305.c | 68 |
1 files changed, 36 insertions, 32 deletions
diff --git a/chacha-poly1305.c b/chacha-poly1305.c index 35c4bfe7..c5109b86 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); } |