diff --git a/ChangeLog b/ChangeLog index 863eeac258114b667b14182cc65eb6fac66ffa7f..87679c70cf892a203a8a958a5e14e7462549a772 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2013-11-08 Nikos Mavrogiannopoulos <nmav@gnutls.org> + + * poly1305.h: New file. + * poly1305.c: New file. + * poly1305-aes.h: New file. + * poly1305-aes.c: New file. + * Makefile.in (nettle_SOURCES): Added poly1305-aes.c and poly1305.c. + (HEADERS): Added poly1305-aes.h and poly1305.h. + + * testsuite/poly1305-test.c: New file. + * testsuite/Makefile.in (TS_NETTLE_SOURCES): Added poly1305-test.c. + + * examples/nettle-benchmark.c (time_poly1305_aes): New function. + (main): Benchmark poly1305. + 2013-10-05 Niels Möller <nisse@lysator.liu.se> * Makefile.in (nettle_SOURCES): Added eax.c. diff --git a/Makefile.in b/Makefile.in index 13acde64625cff7d88675c7f009d7137431d1694..63e0a2c84869de33d258345e73395d024149103b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -103,6 +103,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ serpent-set-key.c serpent-encrypt.c serpent-decrypt.c \ serpent-meta.c \ twofish.c twofish-meta.c \ + poly1305-aes.c poly1305.c \ umac-nh.c umac-nh-n.c umac-l2.c umac-l3.c \ umac-poly64.c umac-poly128.c umac-set-key.c \ umac32.c umac64.c umac96.c umac128.c \ @@ -162,7 +163,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \ pgp.h pkcs1.h realloc.h ripemd160.h rsa.h rsa-compat.h \ salsa20.h sexp.h \ serpent.h sha.h sha1.h sha2.h sha3.h twofish.h \ - umac.h yarrow.h + umac.h yarrow.h poly1305-aes.h poly1305.h INSTALL_HEADERS = $(HEADERS) nettle-stdint.h diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c index 6a8aa6e2a1fe4237a63b233f9e6bab8bb422ba48..0cb24e61fa27f6accca781571965746d44f3e7aa 100644 --- a/examples/nettle-benchmark.c +++ b/examples/nettle-benchmark.c @@ -56,6 +56,7 @@ #include "sha3.h" #include "twofish.h" #include "umac.h" +#include "poly1305-aes.h" #include "nettle-meta.h" #include "nettle-internal.h" @@ -398,6 +399,23 @@ time_umac(void) time_function(bench_hash, &info)); } +static void +time_poly1305_aes(void) +{ + static uint8_t data[BENCH_BLOCK]; + struct bench_hash_info info; + struct poly1305_aes_ctx ctx; + uint8_t key[32]; + + poly1305_aes_set_key (&ctx, key); + info.ctx = &ctx; + info.update = (nettle_hash_update_func *) poly1305_aes_update; + info.data = data; + + display("poly1305-aes", "update", 1024, + time_function(bench_hash, &info)); +} + static void time_gcm(void) { @@ -718,6 +736,9 @@ main(int argc, char **argv) if (!alg || strstr ("umac", alg)) time_umac(); + if (!alg || strstr ("poly1305-aes", alg)) + time_poly1305_aes(); + for (i = 0; ciphers[i]; i++) if (!alg || strstr(ciphers[i]->name, alg)) time_cipher(ciphers[i]); diff --git a/poly1305-aes.c b/poly1305-aes.c new file mode 100644 index 0000000000000000000000000000000000000000..d3846a4f7435697d7ef72163587662dd08931bc2 --- /dev/null +++ b/poly1305-aes.c @@ -0,0 +1,55 @@ +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The nettle library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the nettle library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02111-1301, USA. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include "macros.h" +#include "nettle-types.h" +#include "poly1305-aes.h" + +void +poly1305_aes_set_key (struct poly1305_aes_ctx *ctx, const uint8_t * key) +{ + POLY1305_SET_KEY(ctx, aes_set_encrypt_key, key); +} + +void +poly1305_aes_set_nonce (struct poly1305_aes_ctx *ctx, + const uint8_t * nonce) +{ + POLY1305_SET_NONCE(ctx, nonce); +} + +void +poly1305_aes_update (struct poly1305_aes_ctx *ctx, + size_t length, const uint8_t * data) +{ + POLY1305_UPDATE(ctx, length, data); +} + +void +poly1305_aes_digest (struct poly1305_aes_ctx *ctx, + size_t length, uint8_t * digest) +{ + POLY1305_DIGEST(ctx, aes_encrypt, length, digest); +} diff --git a/poly1305-aes.h b/poly1305-aes.h new file mode 100644 index 0000000000000000000000000000000000000000..fe19ee24cdcf2eac8af0c844a8f69d6e45717f2e --- /dev/null +++ b/poly1305-aes.h @@ -0,0 +1,69 @@ +/* poly1305-aes.h + * + * Poly1305 message authentication code. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The nettle library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the nettle library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02111-1301, USA. + */ + +#ifndef NETTLE_POLY1305_AES_H_INCLUDED +#define NETTLE_POLY1305_AES_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nettle-types.h" +#include "poly1305.h" +#include "aes.h" + +#define POLY1305_AES_KEY_SIZE 32 +#define POLY1305_AES_DIGEST_SIZE 16 + +#define poly1305_aes_set_key nettle_poly1305_aes_set_key +#define poly1305_aes_set_nonce nettle_poly1305_aes_set_nonce +#define poly1305_aes_update nettle_poly1305_aes_update +#define poly1305_aes_digest nettle_poly1305_aes_digest + +struct poly1305_aes_ctx POLY1305_CTX(struct aes_ctx); + +/* The _set_key function initialize the nonce to zero. */ +void +poly1305_aes_set_key (struct poly1305_aes_ctx *ctx, const uint8_t *key); + +/* Optional, if not used, messages get incrementing nonces starting from zero. */ +void +poly1305_aes_set_nonce (struct poly1305_aes_ctx *ctx, + const uint8_t *nonce); + +void +poly1305_aes_update (struct poly1305_aes_ctx *ctx, + size_t length, const uint8_t *data); + +/* The _digest functions increment the nonce */ +void +poly1305_aes_digest (struct poly1305_aes_ctx *ctx, + size_t length, uint8_t *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_POLY1305_AES_H_INCLUDED */ diff --git a/poly1305.c b/poly1305.c new file mode 100644 index 0000000000000000000000000000000000000000..aaf6600a37313cacdab9ce991bfd726217f1aa90 --- /dev/null +++ b/poly1305.c @@ -0,0 +1,198 @@ +/* nettle, low-level cryptographics library + * + * Placed by the author under public domain or the MIT license. + * (see https://github.com/floodyberry/poly1305-donna ) + * Modified for nettle by Nikos Mavrogiannopoulos. + * + * Copyright: 2012-2013 Andrew M. (floodyberry) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include "macros.h" +#include "nettle-types.h" +#include "poly1305.h" + +#define mul32x32_64(a,b) ((uint64_t)(a) * (b)) + +void poly1305_set_key(struct poly1305_ctx *ctx, const uint8_t key[16]) +{ +uint32_t t0,t1,t2,t3; + + t0 = LE_READ_UINT32(key); + t1 = LE_READ_UINT32(key+4); + t2 = LE_READ_UINT32(key+8); + t3 = LE_READ_UINT32(key+12); + + ctx->r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6; + ctx->r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12; + ctx->r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18; + ctx->r3 = t2 & 0x3f03fff; t3 >>= 8; + ctx->r4 = t3 & 0x00fffff; + + ctx->s1 = ctx->r1 * 5; + ctx->s2 = ctx->r2 * 5; + ctx->s3 = ctx->r3 * 5; + ctx->s4 = ctx->r4 * 5; + + ctx->h0 = 0; + ctx->h1 = 0; + ctx->h2 = 0; + ctx->h3 = 0; + ctx->h4 = 0; +} + +void +poly1305_set_nonce (struct poly1305_ctx *ctx, const uint8_t * nonce) +{ + memcpy (ctx->nonce, nonce, 16); +} + +void +poly1305_set_s (struct poly1305_ctx *ctx, const uint8_t * s) +{ + memcpy (ctx->s, s, 16); +} + +void +poly1305_block (struct poly1305_ctx *ctx, const uint8_t m[16]) +{ + uint32_t t0,t1,t2,t3; + uint32_t b; + uint64_t t[5]; + uint64_t c; + + /* full blocks */ + t0 = LE_READ_UINT32(m); + t1 = LE_READ_UINT32(m+4); + t2 = LE_READ_UINT32(m+8); + t3 = LE_READ_UINT32(m+12); + + ctx->h0 += t0 & 0x3ffffff; + ctx->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; + ctx->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; + ctx->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; + ctx->h4 += (t3 >> 8) | (1 << 24); + +/* poly1305_donna_mul: */ + t[0] = mul32x32_64(ctx->h0,ctx->r0) + mul32x32_64(ctx->h1,ctx->s4) + mul32x32_64(ctx->h2,ctx->s3) + mul32x32_64(ctx->h3,ctx->s2) + mul32x32_64(ctx->h4,ctx->s1); + t[1] = mul32x32_64(ctx->h0,ctx->r1) + mul32x32_64(ctx->h1,ctx->r0) + mul32x32_64(ctx->h2,ctx->s4) + mul32x32_64(ctx->h3,ctx->s3) + mul32x32_64(ctx->h4,ctx->s2); + t[2] = mul32x32_64(ctx->h0,ctx->r2) + mul32x32_64(ctx->h1,ctx->r1) + mul32x32_64(ctx->h2,ctx->r0) + mul32x32_64(ctx->h3,ctx->s4) + mul32x32_64(ctx->h4,ctx->s3); + t[3] = mul32x32_64(ctx->h0,ctx->r3) + mul32x32_64(ctx->h1,ctx->r2) + mul32x32_64(ctx->h2,ctx->r1) + mul32x32_64(ctx->h3,ctx->r0) + mul32x32_64(ctx->h4,ctx->s4); + t[4] = mul32x32_64(ctx->h0,ctx->r4) + mul32x32_64(ctx->h1,ctx->r3) + mul32x32_64(ctx->h2,ctx->r2) + mul32x32_64(ctx->h3,ctx->r1) + mul32x32_64(ctx->h4,ctx->r0); + + ctx->h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26); + t[1] += c; ctx->h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26); + t[2] += b; ctx->h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26); + t[3] += b; ctx->h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26); + t[4] += b; ctx->h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26); + ctx->h0 += b * 5; +} + +void +poly1305_digest (struct poly1305_ctx *ctx, + size_t length, uint8_t *digest) +{ + uint32_t t0,t1,t2,t3; + uint32_t b, nb; + size_t j; + uint64_t t[5]; + uint64_t f0,f1,f2,f3; + uint32_t g0,g1,g2,g3,g4; + uint64_t c; + uint8_t mp[16]; + uint8_t td[16]; + + /* final bytes */ +/* poly1305_donna_atmost15bytes: */ + if (!ctx->index) goto poly1305_donna_finish; + + for (j = 0; j < ctx->index; j++) mp[j] = ctx->block[j]; + mp[j++] = 1; + for (; j < 16; j++) mp[j] = 0; + + t0 = LE_READ_UINT32(mp); + t1 = LE_READ_UINT32(mp+4); + t2 = LE_READ_UINT32(mp+8); + t3 = LE_READ_UINT32(mp+12); + + ctx->h0 += t0 & 0x3ffffff; + ctx->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; + ctx->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; + ctx->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; + ctx->h4 += (t3 >> 8); + +/* poly1305_donna_mul: */ + t[0] = mul32x32_64(ctx->h0,ctx->r0) + mul32x32_64(ctx->h1,ctx->s4) + mul32x32_64(ctx->h2,ctx->s3) + mul32x32_64(ctx->h3,ctx->s2) + mul32x32_64(ctx->h4,ctx->s1); + t[1] = mul32x32_64(ctx->h0,ctx->r1) + mul32x32_64(ctx->h1,ctx->r0) + mul32x32_64(ctx->h2,ctx->s4) + mul32x32_64(ctx->h3,ctx->s3) + mul32x32_64(ctx->h4,ctx->s2); + t[2] = mul32x32_64(ctx->h0,ctx->r2) + mul32x32_64(ctx->h1,ctx->r1) + mul32x32_64(ctx->h2,ctx->r0) + mul32x32_64(ctx->h3,ctx->s4) + mul32x32_64(ctx->h4,ctx->s3); + t[3] = mul32x32_64(ctx->h0,ctx->r3) + mul32x32_64(ctx->h1,ctx->r2) + mul32x32_64(ctx->h2,ctx->r1) + mul32x32_64(ctx->h3,ctx->r0) + mul32x32_64(ctx->h4,ctx->s4); + t[4] = mul32x32_64(ctx->h0,ctx->r4) + mul32x32_64(ctx->h1,ctx->r3) + mul32x32_64(ctx->h2,ctx->r2) + mul32x32_64(ctx->h3,ctx->r1) + mul32x32_64(ctx->h4,ctx->r0); + + ctx->h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26); + t[1] += c; ctx->h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26); + t[2] += b; ctx->h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26); + t[3] += b; ctx->h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26); + t[4] += b; ctx->h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26); + ctx->h0 += b * 5; + +poly1305_donna_finish: + b = ctx->h0 >> 26; ctx->h0 = ctx->h0 & 0x3ffffff; + ctx->h1 += b; b = ctx->h1 >> 26; ctx->h1 = ctx->h1 & 0x3ffffff; + ctx->h2 += b; b = ctx->h2 >> 26; ctx->h2 = ctx->h2 & 0x3ffffff; + ctx->h3 += b; b = ctx->h3 >> 26; ctx->h3 = ctx->h3 & 0x3ffffff; + ctx->h4 += b; b = ctx->h4 >> 26; ctx->h4 = ctx->h4 & 0x3ffffff; + ctx->h0 += b * 5; b = ctx->h0 >> 26; ctx->h0 = ctx->h0 & 0x3ffffff; + ctx->h1 += b; + + g0 = ctx->h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff; + g1 = ctx->h1 + b; b = g1 >> 26; g1 &= 0x3ffffff; + g2 = ctx->h2 + b; b = g2 >> 26; g2 &= 0x3ffffff; + g3 = ctx->h3 + b; b = g3 >> 26; g3 &= 0x3ffffff; + g4 = ctx->h4 + b - (1 << 26); + + b = (g4 >> 31) - 1; + nb = ~b; + ctx->h0 = (ctx->h0 & nb) | (g0 & b); + ctx->h1 = (ctx->h1 & nb) | (g1 & b); + ctx->h2 = (ctx->h2 & nb) | (g2 & b); + ctx->h3 = (ctx->h3 & nb) | (g3 & b); + ctx->h4 = (ctx->h4 & nb) | (g4 & b); + + f0 = ((ctx->h0 ) | (ctx->h1 << 26)) + (uint64_t)LE_READ_UINT32(ctx->s); + f1 = ((ctx->h1 >> 6) | (ctx->h2 << 20)) + (uint64_t)LE_READ_UINT32(ctx->s+4); + f2 = ((ctx->h2 >> 12) | (ctx->h3 << 14)) + (uint64_t)LE_READ_UINT32(ctx->s+8); + f3 = ((ctx->h3 >> 18) | (ctx->h4 << 8)) + (uint64_t)LE_READ_UINT32(ctx->s+12); + + LE_WRITE_UINT32(td, f0); + f1 += (f0 >> 32); + LE_WRITE_UINT32(&td[4], f1); + f2 += (f1 >> 32); + LE_WRITE_UINT32(&td[8], f2); + f3 += (f2 >> 32); + LE_WRITE_UINT32(&td[12], f3); + + memcpy(digest, td, length); +} diff --git a/poly1305.h b/poly1305.h new file mode 100644 index 0000000000000000000000000000000000000000..db4c77f4d82e36569100059103267553876feaf6 --- /dev/null +++ b/poly1305.h @@ -0,0 +1,100 @@ +/* poly1305-aes.h + * + * Poly1305 message authentication code. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The nettle library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the nettle library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02111-1301, USA. + */ + +#ifndef NETTLE_POLY1305_H_INCLUDED +#define NETTLE_POLY1305_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/* Low level functions/macros for the poly1305 construction. + * For the macros to be useful include macros.h + */ + +#include "nettle-types.h" + +struct poly1305_ctx { + uint32_t h0; uint32_t h1; uint32_t h2; uint32_t h3; uint32_t h4; + uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r4; + uint32_t s1; uint32_t s2; uint32_t s3; uint32_t s4; + + uint8_t s[16]; /* typically AES_k(nonce) */ + uint8_t nonce[16]; + uint8_t block[16]; + unsigned index; +}; + +/* All-in-one context, with cipher, and state. Cipher must have a 128-bit block */ +#define POLY1305_CTX(type) \ +{ struct poly1305_ctx pctx; type cipher; } + +#define poly1305_set_key nettle_poly1305_set_key +#define poly1305_set_nonce nettle_poly1305_set_nonce +#define poly1305_set_s nettle_poly1305_set_s +#define poly1305_block nettle_poly1305_round +#define poly1305_digest nettle_poly1305_digest + +void poly1305_set_key(struct poly1305_ctx *ctx, const uint8_t key[16]); +void poly1305_set_nonce (struct poly1305_ctx *ctx, const uint8_t * nonce); +void poly1305_set_s (struct poly1305_ctx *ctx, const uint8_t *s); +void poly1305_block (struct poly1305_ctx *ctx, const uint8_t m[16]); +void poly1305_digest (struct poly1305_ctx *ctx, size_t length, uint8_t *digest); + +#define POLY1305_SET_KEY(ctx, set_key, key) \ + do { \ + poly1305_set_key(&(ctx)->pctx, (key+16)); \ + (set_key)(&(ctx)->cipher, 16, (key)); \ + (ctx)->pctx.index = 0; \ + } while (0) + +#define POLY1305_SET_NONCE(ctx, data) \ + poly1305_set_nonce(&(ctx)->pctx, (data)) + +#define _POLY1305_BLOCK(ctx, block) do { \ + poly1305_block(ctx, block); \ + } while (0) + + +#define POLY1305_UPDATE(ctx, length, data) \ + MD_UPDATE (&(ctx)->pctx, (length), (data), _POLY1305_BLOCK, (void) 0) + +#define POLY1305_DIGEST(ctx, encrypt, length, digest) \ + do { \ + uint8_t _ts[16]; \ + (encrypt)(&(ctx)->cipher, 16, _ts, (ctx)->pctx.nonce); \ + poly1305_set_s(&(ctx)->pctx, _ts); \ + poly1305_digest (&(ctx)->pctx, (length), (digest)); \ + INCREMENT (16, (ctx)->pctx.nonce); \ + (ctx)->pctx.index = 0; \ + } while(0); + + + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_POLY1305_H_INCLUDED */ diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make index 5549fc09929541c5cccca4493cd8f825dddd50a5..2900468b5df15a0c2a7e5bc35a0f30ca9cad7633 100644 --- a/testsuite/.test-rules.make +++ b/testsuite/.test-rules.make @@ -106,6 +106,9 @@ gcm-test$(EXEEXT): gcm-test.$(OBJEXT) eax-test$(EXEEXT): eax-test.$(OBJEXT) $(LINK) eax-test.$(OBJEXT) $(TEST_OBJS) -o eax-test$(EXEEXT) +poly1305-test$(EXEEXT): poly1305-test.$(OBJEXT) + $(LINK) poly1305-test.$(OBJEXT) $(TEST_OBJS) -o poly1305-test$(EXEEXT) + hmac-test$(EXEEXT): hmac-test.$(OBJEXT) $(LINK) hmac-test.$(OBJEXT) $(TEST_OBJS) -o hmac-test$(EXEEXT) diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 0ad950dbd8148f14687c11ec7518429b0be5ec8e..c02ee7ddd532a9208445ab4010b7d6ffce3eb6b9 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -26,6 +26,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \ serpent-test.c twofish-test.c \ knuth-lfib-test.c \ cbc-test.c ctr-test.c gcm-test.c eax-test.c \ + poly1305-test.c \ hmac-test.c umac-test.c \ meta-hash-test.c meta-cipher-test.c meta-armor-test.c \ buffer-test.c yarrow-test.c pbkdf2-test.c diff --git a/testsuite/poly1305-test.c b/testsuite/poly1305-test.c new file mode 100644 index 0000000000000000000000000000000000000000..a87ef6aecf1f83f0c3f4661fe21b043d9b0cfbf1 --- /dev/null +++ b/testsuite/poly1305-test.c @@ -0,0 +1,86 @@ +#include "testutils.h" +#include "poly1305-aes.h" + +static void +update (void *ctx, nettle_hash_update_func *f, + const struct tstring *msg, + unsigned length) +{ + for (; length > msg->length; length -= msg->length) + f(ctx, msg->length, msg->data); + f(ctx, length, msg->data); +} + +static void +check_digest (const char *name, void *ctx, nettle_hash_digest_func *f, + const struct tstring *msg, unsigned length, + unsigned tag_length, const uint8_t *ref) +{ + uint8_t tag[16]; + f(ctx, tag_length, tag); + if (memcmp (tag, ref, tag_length) != 0) + { + printf ("%s failed\n", name); + printf ("msg: "); print_hex (msg->length, msg->data); + printf ("length: %u\n", length); + printf ("tag: "); print_hex (tag_length, tag); + printf ("ref: "); print_hex (tag_length, ref); + abort (); + } + +} + +static void +test_poly1305 (const struct tstring *key, + const struct tstring *nonce, + const struct tstring *msg, + unsigned length, + const struct tstring *ref) +{ + struct poly1305_aes_ctx ctx; + + ASSERT (key->length == POLY1305_AES_KEY_SIZE); + ASSERT (ref->length == POLY1305_AES_DIGEST_SIZE); + + poly1305_aes_set_key (&ctx, key->data); + poly1305_aes_set_nonce (&ctx, nonce->data); + + update(&ctx, (nettle_hash_update_func *) poly1305_aes_update, msg, length); + + check_digest ("poly1305-aes", &ctx, (nettle_hash_digest_func *) poly1305_aes_digest, + msg, length, 16, ref->data); +} + +void +test_main(void) +{ + /* From Bernstein's paper. */ + test_poly1305 + (SHEX("75deaa25c09f208e1dc4ce6b5cad3fbfa0f3080000f46400d0c7e9076c834403"), + SHEX("61ee09218d29b0aaed7e154a2c5509cc"), + SHEX(""), 0, + SHEX("dd3fab2251f11ac759f0887129cc2ee7")); + + test_poly1305 + (SHEX("ec074c835580741701425b623235add6851fc40c3467ac0be05cc20404f3f700"), + SHEX("fb447350c4e868c52ac3275cf9d4327e"), + SHEX("f3f6"), 2, + SHEX("f4c633c3044fc145f84f335cb81953de")); + + test_poly1305 + (SHEX("6acb5f61a7176dd320c5c1eb2edcdc74" + "48443d0bb0d21109c89a100b5ce2c208"), + SHEX("ae212a55399729595dea458bc621ff0e"), + SHEX("663cea190ffb83d89593f3f476b6bc24" + "d7e679107ea26adb8caf6652d0656136"), 32, + SHEX("0ee1c16bb73f0f4fd19881753c01cdbe")); + + test_poly1305 + (SHEX("e1a5668a4d5b66a5f68cc5424ed5982d12976a08c4426d0ce8a82407c4f48207"), + SHEX("9ae831e743978d3a23527c7128149e3a"), + SHEX("ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491" + "faf0990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb2109" + "5c1bf9"), 63, + SHEX("5154ad0d2cb26e01274fc51148491f1b")); + +}