Joachim Strömbergson joachim@secworks.se writes:
Here is the patch to add build chacha in Nettle.
Nice. I've tried this, together with your code at https://github.com/secworks/nettle/tree/master/chacha (is that your latest code? It was slightly inconsistent, with some function still expecting nrounds in the context struct).
I edited it a bit, to take out support for rounds != 20 for now (except for the _chacha_core_internal function), and I split the set key function into two functions for the two available key sizes, 128 and 256 bits.
Resulting patch below. I think I'll check this in soon. Next steps would be:
1. Add it to the benchmark (probably easiest to do it the same way as salsa20, with a struct in nettle-internal.c).
2. Adapt the test program to nettle conventions. Possibly convert the round != 20 test cases to tests of the chacha_core function?
3. Write some assembly.
Regards, /Niels
diff --git a/Makefile.in b/Makefile.in index 10715b2..092c217 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,8 +80,10 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ camellia-crypt.c camellia-crypt-internal.c \ camellia-set-encrypt-key.c camellia-set-decrypt-key.c \ camellia-table.c camellia-meta.c \ - cast128.c cast128-meta.c \ - cbc.c ctr.c \ + cast128.c cast128-meta.c cbc.c \ + chacha-crypt.c chacha-core-internal.c chacha-set-iv.c \ + chacha128-set-key.c chacha256-set-key.c \ + ctr.c \ des.c des3.c des-compat.c eax.c \ gcm.c gcm-aes.c gosthash94.c \ hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \ @@ -149,7 +151,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \ base16.h base64.h buffer.h camellia.h cast128.h \ - cbc.h ctr.h \ + cbc.h chacha.h ctr.h \ des.h des-compat.h dsa.h eax.h ecc-curve.h ecc.h ecdsa.h \ gcm.h gosthash94.h hmac.h \ knuth-lfib.h \ diff --git a/chacha-core-internal.c b/chacha-core-internal.c index e69de29..fb695ff 100644 --- a/chacha-core-internal.c +++ b/chacha-core-internal.c @@ -0,0 +1,120 @@ +/* chacha-core-internal.c + * + * Core functionality of the ChaCha stream cipher. + * Heavily based on the Salsa20 implementation in Nettle. + * + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergson + * Copyright (C) 2012 Simon Josefsson, Niels Möller + * + * 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. + */ + +/* Based on: + chacha-ref.c version 2008.01.20. + D. J. Bernstein + Public domain. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <string.h> + +#include "chacha.h" + +#include "macros.h" + +#ifndef CHACHA_DEBUG +# define CHACHA_DEBUG 0 +#endif + +#if CHACHA_DEBUG +# include <stdio.h> +# define DEBUG(i) do { \ + unsigned debug_j; \ + for (debug_j = 0; debug_j < 16; debug_j++) \ + { \ + if (debug_j == 0) \ + fprintf(stderr, "%2d:", (i)); \ + else if (debug_j % 4 == 0) \ + fprintf(stderr, "\n "); \ + fprintf(stderr, " %8x", x[debug_j]); \ + } \ + fprintf(stderr, "\n"); \ + } while (0) +#else +# define DEBUG(i) +#endif + +#ifdef WORDS_BIGENDIAN +#define LE_SWAP32(v) \ + ((ROTL32(8, v) & 0x00FF00FFUL) | \ + (ROTL32(24, v) & 0xFF00FF00UL)) +#else +#define LE_SWAP32(v) (v) +#endif + +#define QROUND(x0, x1, x2, x3) do { \ + x0 = x0 + x1; x3 = ROTL32(16, (x0 ^ x3)); \ + x2 = x2 + x3; x1 = ROTL32(12, (x1 ^ x2)); \ + x0 = x0 + x1; x3 = ROTL32(8, (x0 ^ x3)); \ + x2 = x2 + x3; x1 = ROTL32(7, (x1 ^ x2)); \ + } while(0) + +void +_chacha_core(uint32_t *dst, const uint32_t *src, unsigned rounds) +{ + uint32_t x[_CHACHA_STATE_LENGTH]; + unsigned i; + + assert ( (rounds & 1) == 0); + + memcpy (x, src, sizeof(x)); + for (i = 0; i < rounds;i += 2) + { + DEBUG (i); + QROUND(x[0], x[4], x[8], x[12]); + QROUND(x[1], x[5], x[9], x[13]); + QROUND(x[2], x[6], x[10], x[14]); + QROUND(x[3], x[7], x[11], x[15]); + + DEBUG (i+1); + QROUND(x[0], x[5], x[10], x[15]); + QROUND(x[1], x[6], x[11], x[12]); + QROUND(x[2], x[7], x[8], x[13]); + QROUND(x[3], x[4], x[9], x[14]); + } + DEBUG (i); + + for (i = 0; i < _CHACHA_STATE_LENGTH; i++) + { + uint32_t t = x[i] + src[i]; + dst[i] = LE_SWAP32 (t); + } +} + + + + + + + diff --git a/chacha-crypt.c b/chacha-crypt.c index e69de29..1aed643 100644 --- a/chacha-crypt.c +++ b/chacha-crypt.c @@ -0,0 +1,77 @@ +/* salsa20-crypt.c + * + * The crypt function in the ChaCha stream cipher. + * Heavily based on the Salsa20 implementation in Nettle. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergson + * Copyright (C) 2012 Simon Josefsson + * + * 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. + */ + +/* Based on: + chacha-ref.c version 2008.01.20. + D. J. Bernstein + Public domain. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <string.h> + +#include "chacha.h" + +#include "macros.h" +#include "memxor.h" + +#define CHACHA_ROUNDS 20 + +void +chacha_crypt(struct chacha_ctx *ctx, + size_t length, + uint8_t *c, + const uint8_t *m) +{ + if (!length) + return; + + for (;;) + { + uint32_t x[_CHACHA_STATE_LENGTH]; + + _chacha_core (x, ctx->state, CHACHA_ROUNDS); + + ctx->state[9] += (++ctx->state[8] == 0); + + /* stopping at 2^70 length per nonce is user's responsibility */ + + if (length <= CHACHA_BLOCK_SIZE) + { + memxor3 (c, m, x, length); + return; + } + memxor3 (c, m, x, CHACHA_BLOCK_SIZE); + + length -= CHACHA_BLOCK_SIZE; + c += CHACHA_BLOCK_SIZE; + m += CHACHA_BLOCK_SIZE; + } +} diff --git a/chacha-set-iv.c b/chacha-set-iv.c index e69de29..50d9835 100644 --- a/chacha-set-iv.c +++ b/chacha-set-iv.c @@ -0,0 +1,52 @@ +/* chacha-set-iv.c + * + * Setting the IV the ChaCha stream cipher. + * Based on the Salsa20 implementation in Nettle. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergon + * Copyright (C) 2012 Simon Josefsson + * Copyright (C) 2012, 2014 Niels Möller + * + * 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. + */ + +/* Based on: + ChaCha specification (doc id: 4027b5256e17b9796842e6d0f68b0b5e) and reference + implementation dated 2008.01.20 + D. J. Bernstein + Public domain. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> + +#include "chacha.h" + +#include "macros.h" +void +chacha_set_iv(struct chacha_ctx *ctx, const uint8_t *iv) +{ + ctx->state[12] = 0; + ctx->state[13] = 0; + ctx->state[14] = LE_READ_UINT32(iv + 0); + ctx->state[15] = LE_READ_UINT32(iv + 4); +} diff --git a/chacha.h b/chacha.h index e69de29..e965234 100644 --- a/chacha.h +++ b/chacha.h @@ -0,0 +1,91 @@ +/* chacha.h + * + * The ChaCha stream cipher. + * Heavily based on the Salsa20 source code in Nettle. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergson + * Copyright (C) 2012 Simon Josefsson + * Copyright (C) 2001 Niels Möller + * + * 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_CHACHA_H_INCLUDED +#define NETTLE_CHACHA_H_INCLUDED + +#include "nettle-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Name mangling */ +#define chacha128_set_key nettle_chacha128_set_key +#define chacha256_set_key nettle_chacha256_set_key +#define chacha_set_iv nettle_chacha_set_iv +#define chacha_crypt nettle_chacha_crypt +#define _chacha_core _nettle_chacha_core + +/* Minimum and maximum keysizes, and a reasonable default. + In octets. */ +#define CHACHA128_KEY_SIZE 16 +#define CHACHA256_KEY_SIZE 32 +#define CHACHA_BLOCK_SIZE 64 + +#define CHACHA_IV_SIZE 8 + +#define _CHACHA_STATE_LENGTH 16 + +struct chacha_ctx +{ + /* Indices 0-3 holds a constant (SIGMA or TAU). + Indices 4-11 holds the key. + Indices 12-13 holds the block counter. + Indices 14-15 holds the IV: + + This creates the state matrix: + C C C C + K K K K + K K K K + B B I I + */ + uint32_t state[_CHACHA_STATE_LENGTH]; +}; + +void +chacha128_set_key(struct chacha_ctx *ct, const uint8_t *key); + +void +chacha256_set_key(struct chacha_ctx *ct, const uint8_t *key); + +void +chacha_set_iv(struct chacha_ctx *ctx, const uint8_t *iv); + +void +chacha_crypt(struct chacha_ctx *ctx, size_t length, + uint8_t *dst, const uint8_t *src); + +void +_chacha_core(uint32_t *dst, const uint32_t *src, unsigned rounds); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_CHACHA_H_INCLUDED */ diff --git a/chacha128-set-key.c b/chacha128-set-key.c index e69de29..569e801 100644 --- a/chacha128-set-key.c +++ b/chacha128-set-key.c @@ -0,0 +1,61 @@ +/* chacha128-set-key.c + * + * ChaCha key setup for 128-bit keys. + * Based on the Salsa20 implementation in Nettle. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergon + * Copyright (C) 2012 Simon Josefsson + * Copyright (C) 2012, 2014 Niels Möller + * + * 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. + */ + +/* Based on: + ChaCha specification (doc id: 4027b5256e17b9796842e6d0f68b0b5e) and reference + implementation dated 2008.01.20 + D. J. Bernstein + Public domain. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <string.h> + +#include "chacha.h" + +#include "macros.h" + +void +chacha128_set_key(struct chacha_ctx *ctx, const uint8_t *key) +{ + static const uint32_t tau[4] = { + /* "expand 16-byte k" */ + 0x61707865, 0x3120646e, 0x79622d36, 0x6b206574 + }; + + ctx->state[8] = ctx->state[4] = LE_READ_UINT32(key + 0); + ctx->state[9] = ctx->state[5] = LE_READ_UINT32(key + 4); + ctx->state[10] = ctx->state[6] = LE_READ_UINT32(key + 8); + ctx->state[11] = ctx->state[7] = LE_READ_UINT32(key + 12); + + memcpy (ctx->state, tau, sizeof(tau)); +} diff --git a/chacha256-set-key.c b/chacha256-set-key.c index e69de29..66e314b 100644 --- a/chacha256-set-key.c +++ b/chacha256-set-key.c @@ -0,0 +1,65 @@ +/* chacha256-set-key.c + * + * ChaCha key setup for 256-bit keys. + * Based on the Salsa20 implementation in Nettle. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergon + * Copyright (C) 2012 Simon Josefsson + * Copyright (C) 2012, 2014 Niels Möller + * + * 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. + */ + +/* Based on: + ChaCha specification (doc id: 4027b5256e17b9796842e6d0f68b0b5e) and reference + implementation dated 2008.01.20 + D. J. Bernstein + Public domain. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> +#include <string.h> + +#include "chacha.h" + +#include "macros.h" + +void +chacha256_set_key(struct chacha_ctx *ctx, const uint8_t *key) +{ + static const uint32_t sigma[4] = { + /* "expand 32-byte k" */ + 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 + }; + ctx->state[4] = LE_READ_UINT32(key + 0); + ctx->state[5] = LE_READ_UINT32(key + 4); + ctx->state[6] = LE_READ_UINT32(key + 8); + ctx->state[7] = LE_READ_UINT32(key + 12); + + ctx->state[8] = LE_READ_UINT32(key + 16); + ctx->state[9] = LE_READ_UINT32(key + 20); + ctx->state[10] = LE_READ_UINT32(key + 24); + ctx->state[11] = LE_READ_UINT32(key + 28); + + memcpy (ctx->state, sigma, sizeof(sigma)); +} diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make index 5549fc0..3d6137f 100644 --- a/testsuite/.test-rules.make +++ b/testsuite/.test-rules.make @@ -22,6 +22,9 @@ base64-test$(EXEEXT): base64-test.$(OBJEXT) camellia-test$(EXEEXT): camellia-test.$(OBJEXT) $(LINK) camellia-test.$(OBJEXT) $(TEST_OBJS) -o camellia-test$(EXEEXT)
+chacha-test$(EXEEXT): chacha-test.$(OBJEXT) + $(LINK) chacha-test.$(OBJEXT) $(TEST_OBJS) -o chacha-test$(EXEEXT) + des-test$(EXEEXT): des-test.$(OBJEXT) $(LINK) des-test.$(OBJEXT) $(TEST_OBJS) -o des-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 0ad950d..8838bef 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -13,7 +13,7 @@ PRE_LDFLAGS = -L.. TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \ blowfish-test.c cast128-test.c \ base16-test.c base64-test.c \ - camellia-test.c \ + camellia-test.c chacha-test.c \ des-test.c des3-test.c des-compat-test.c \ md2-test.c md4-test.c md5-test.c md5-compat-test.c \ memxor-test.c gosthash94-test.c \ diff --git a/testsuite/chacha-test.c b/testsuite/chacha-test.c index e69de29..f1ed0ea 100644 --- a/testsuite/chacha-test.c +++ b/testsuite/chacha-test.c @@ -0,0 +1,251 @@ +/* chacha-test.c + * + * Test program for the ChaCha stream cipher implementation. + */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2013 Joachim Strömbergson + * Copyright (C) 2012 Niels Möller + * + * 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. + */ + +#include "testutils.h" + +#include "chacha.h" + +static void +print_block(uint8_t block[64]) +{ + uint8_t i; + + for (i = 0 ; i < 64 ; i++) { + printf("0x%02x ", block[i]); + if (((i + 1) % 8) == 0) { + printf("\n"); + } + } + printf("\n"); +} + + +static void +test_chacha(const uint8_t *key, const uint8_t *iv, uint8_t *expected, + uint8_t keylength) +{ + uint8_t cipher_data[64] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + uint8_t cipher_result[64] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + struct chacha_ctx cipher_ctx; + + unsigned i, errors; + + switch (keylength) + { + default: + abort (); + case 16: + chacha128_set_key(&cipher_ctx, key); + break; + case 32: + chacha256_set_key(&cipher_ctx, key); + break; + } + + chacha_set_iv(&cipher_ctx, iv); + chacha_crypt(&cipher_ctx, 64, &cipher_result[0], &cipher_data[0]); + + if (verbose) + { + printf("Result after encryption:\n"); + print_block(cipher_result); + } + + errors = 0; + for (i = 0 ; i < 64 ; i++) + if (cipher_result[i] != expected[i]) + errors++; + + if (errors > 0) + { + printf("Error, expected:\n"); + print_block(&expected[0]); + printf("Got:\n"); + print_block(cipher_result); + } + else + printf("Success, result matched expected.\n"); +} + + +void +test_main(void) +{ + printf("Test of chacha nettle implementation\n"); + printf("------------------------------------\n"); + + /* Test vectors from draft-strombergson-chacha-test-vectors */ + +#if 0 + // TC1: All zero key and IV. 128 bit key and 8 rounds. + uint8_t tc1_key[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t tc1_keylength = 16; + + uint8_t tc1_iv[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + uint8_t tc1_rounds = 8; + + uint8_t tc1_expected[64] = {0xe2, 0x8a, 0x5f, 0xa4, 0xa6, 0x7f, 0x8c, 0x5d, + 0xef, 0xed, 0x3e, 0x6f, 0xb7, 0x30, 0x34, 0x86, + 0xaa, 0x84, 0x27, 0xd3, 0x14, 0x19, 0xa7, 0x29, + 0x57, 0x2d, 0x77, 0x79, 0x53, 0x49, 0x11, 0x20, + 0xb6, 0x4a, 0xb8, 0xe7, 0x2b, 0x8d, 0xeb, 0x85, + 0xcd, 0x6a, 0xea, 0x7c, 0xb6, 0x08, 0x9a, 0x10, + 0x18, 0x24, 0xbe, 0xeb, 0x08, 0x81, 0x4a, 0x42, + 0x8a, 0xab, 0x1f, 0xa2, 0xc8, 0x16, 0x08, 0x1b}; + + test_chacha(&tc1_key[0], &tc1_iv[0], &tc1_expected[0], tc1_keylength, tc1_rounds); + + + // TC2: All zero key and IV. 128 bit key and 12 rounds. + uint8_t tc2_key[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t tc2_keylength = 16; + + uint8_t tc2_iv[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + uint8_t tc2_rounds = 12; + + uint8_t tc2_expected[64] = {0xe1, 0x04, 0x7b, 0xa9, 0x47, 0x6b, 0xf8, 0xff, + 0x31, 0x2c, 0x01, 0xb4, 0x34, 0x5a, 0x7d, 0x8c, + 0xa5, 0x79, 0x2b, 0x0a, 0xd4, 0x67, 0x31, 0x3f, + 0x1d, 0xc4, 0x12, 0xb5, 0xfd, 0xce, 0x32, 0x41, + 0x0d, 0xea, 0x8b, 0x68, 0xbd, 0x77, 0x4c, 0x36, + 0xa9, 0x20, 0xf0, 0x92, 0xa0, 0x4d, 0x3f, 0x95, + 0x27, 0x4f, 0xbe, 0xff, 0x97, 0xbc, 0x84, 0x91, + 0xfc, 0xef, 0x37, 0xf8, 0x59, 0x70, 0xb4, 0x50}; + + test_chacha(&tc2_key[0], &tc2_iv[0], &tc2_expected[0], tc2_keylength, tc2_rounds); + +#endif + // TC3: All zero key and IV. 128 bit key and 20 rounds. + uint8_t tc3_key[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t tc3_keylength = 16; + + uint8_t tc3_iv[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + uint8_t tc3_expected[64] = {0x89, 0x67, 0x09, 0x52, 0x60, 0x83, 0x64, 0xfd, + 0x00, 0xb2, 0xf9, 0x09, 0x36, 0xf0, 0x31, 0xc8, + 0xe7, 0x56, 0xe1, 0x5d, 0xba, 0x04, 0xb8, 0x49, + 0x3d, 0x00, 0x42, 0x92, 0x59, 0xb2, 0x0f, 0x46, + 0xcc, 0x04, 0xf1, 0x11, 0x24, 0x6b, 0x6c, 0x2c, + 0xe0, 0x66, 0xbe, 0x3b, 0xfb, 0x32, 0xd9, 0xaa, + 0x0f, 0xdd, 0xfb, 0xc1, 0x21, 0x23, 0xd4, 0xb9, + 0xe4, 0x4f, 0x34, 0xdc, 0xa0, 0x5a, 0x10, 0x3f}; + + test_chacha(&tc3_key[0], &tc3_iv[0], &tc3_expected[0], tc3_keylength); + +#if 0 + // TC4: Sequence patterns in key and IV. 256 bit key and 8 rounds. + uint8_t tc4_key[32] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; + uint8_t tc4_keylength = 32; + + uint8_t tc4_iv[8] = {0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x59, 0x68, 0x77}; + + uint8_t tc4_rounds = 8; + + uint8_t tc4_expected[64] = {0x60, 0xfd, 0xed, 0xbd, 0x1a, 0x28, 0x0c, 0xb7, + 0x41, 0xd0, 0x59, 0x3b, 0x6e, 0xa0, 0x30, 0x90, + 0x10, 0xac, 0xf1, 0x8e, 0x14, 0x71, 0xf6, 0x89, + 0x68, 0xf4, 0xc9, 0xe3, 0x11, 0xdc, 0xa1, 0x49, + 0xb8, 0xe0, 0x27, 0xb4, 0x7c, 0x81, 0xe0, 0x35, + 0x3d, 0xb0, 0x13, 0x89, 0x1a, 0xa5, 0xf6, 0x8e, + 0xa3, 0xb1, 0x3d, 0xd2, 0xf3, 0xb8, 0xdd, 0x08, + 0x73, 0xbf, 0x37, 0x46, 0xe7, 0xd6, 0xc5, 0x67}; + + test_chacha(&tc4_key[0], &tc4_iv[0], &tc4_expected[0], tc4_keylength, tc4_rounds); + + + // TC5: Sequence patterns in key and IV. 256 bit key and 12 rounds. + uint8_t tc5_key[32] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; + uint8_t tc5_keylength = 32; + + uint8_t tc5_iv[8] = {0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x59, 0x68, 0x77}; + + uint8_t tc5_rounds = 12; + + uint8_t tc5_expected[64] = {0x6e, 0x93, 0xf2, 0x58, 0x16, 0xed, 0x81, 0x51, + 0xdb, 0xab, 0x6c, 0x9a, 0x50, 0x0d, 0x56, 0x2e, + 0xf3, 0xac, 0x3c, 0xfd, 0x18, 0x99, 0x70, 0x8c, + 0x15, 0x74, 0xb9, 0x12, 0xf7, 0x1b, 0x13, 0x12, + 0x11, 0x49, 0x85, 0x21, 0x70, 0xbd, 0x0f, 0x45, + 0x43, 0xf0, 0xb7, 0x3f, 0x9f, 0x27, 0xc3, 0x63, + 0x77, 0x36, 0x32, 0xe9, 0xe2, 0xaa, 0x63, 0x24, + 0xf6, 0xbe, 0xd8, 0x7a, 0xb0, 0xd0, 0x30, 0x5e}; + + test_chacha(&tc5_key[0], &tc5_iv[0], &tc5_expected[0], tc5_keylength, tc5_rounds); + +#endif + // TC6: Sequence patterns in key and IV. 256 bit key and 20 rounds. + uint8_t tc6_key[32] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; + uint8_t tc6_keylength = 32; + + uint8_t tc6_iv[8] = {0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x59, 0x68, 0x77}; + + uint8_t tc6_expected[64] = {0x87, 0xfa, 0x92, 0x06, 0x10, 0x43, 0xca, 0x5e, + 0x63, 0x1f, 0xed, 0xd8, 0x8e, 0x8b, 0xfb, 0x84, + 0xad, 0x6b, 0x21, 0x3b, 0xde, 0xe4, 0xbc, 0x80, + 0x6e, 0x27, 0x64, 0x93, 0x5f, 0xb8, 0x90, 0x97, + 0x21, 0x8a, 0x89, 0x7b, 0x7a, 0xea, 0xd1, 0x0e, + 0x1b, 0x17, 0xf6, 0x80, 0x2b, 0x2a, 0xbd, 0xd9, + 0x55, 0x94, 0x90, 0x30, 0x83, 0x73, 0x56, 0x13, + 0xd6, 0xb3, 0x53, 0x1b, 0x9e, 0x0d, 0x1b, 0x67}; + + test_chacha(&tc6_key[0], &tc6_iv[0], &tc6_expected[0], tc6_keylength); +}