From: Mark Wooding Date: Tue, 17 Jul 2018 12:00:26 +0000 (+0100) Subject: lib/: Use Salsa20/8 for random bits, rather than RC4. X-Git-Tag: 5.2~17 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/commitdiff_plain/ed8e4373ca22966011827552d0cb7dff531539cd?hp=f2b0ad05ebaac1d9ba9d900fc3719c388661c661 lib/: Use Salsa20/8 for random bits, rather than RC4. It's faster and produces better quality random bits; RC4's biases are somewhat notorious. --- diff --git a/.gitignore b/.gitignore index fa61290..ba1f52b 100644 --- a/.gitignore +++ b/.gitignore @@ -178,7 +178,6 @@ doc/disorder_options.5 doc/disorder_options.5.html doc/disorder_actions.5.in doc/disorder_templates.5.in -libtests/t-arcfour libtests/t-charset libtests/t-event libtests/t-dateparse @@ -221,3 +220,4 @@ server/disorder-gstdecode .dirstamp tests/*.trs /common/Makefile +libtests/t-salsa208 diff --git a/lib/Makefile.am b/lib/Makefile.am index 279f073..a6a362f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -29,7 +29,6 @@ endif libdisorder_a_SOURCES=charset.c charsetf.c charset.h \ addr.c addr.h \ - arcfour.c arcfour.h \ authhash.c authhash.h \ basen.c basen.h \ base64.c base64.h \ @@ -72,6 +71,7 @@ libdisorder_a_SOURCES=charset.c charsetf.c charset.h \ resample.c resample.h \ rights.c queue-rights.c rights.h \ rtp.h \ + salsa208.c salsa208.h \ selection.c selection.h \ sendmail.c sendmail.h \ signame.c signame.h \ diff --git a/lib/arcfour.c b/lib/arcfour.c deleted file mode 100644 index 3450562..0000000 --- a/lib/arcfour.c +++ /dev/null @@ -1,94 +0,0 @@ -/* arcfour.c --- The arcfour stream cipher - * Copyright (C) 2000, 2001, 2002, 2003, 2005, 2006 Free Software - * Foundation, Inc. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * This file 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ -/** @file lib/arcfour.c - * @brief Arcfour (RC4-compatible) stream cipher implementation - * - * Code from Libgcrypt adapted for gnulib by Simon Josefsson. - * - * For a description of the algorithm, see: - * - * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. - * ISBN 0-471-11709-9. Pages 397 ff. - */ - -#include "arcfour.h" - -/** @brief Encrypt using Arcfour stream cipher - * @param context Context structure - * @param inbuf Input buffer - * @param outbuf Output buffer - * @param length Number of bytes in @p inbuf - * - * Copies from @p inbuf to @p outbuf, encrypting (or decrypting) using - * the stream controlled by @p context. - */ -void -arcfour_stream (arcfour_context * context, const char *inbuf, char *outbuf, - size_t length) -{ - uint8_t i = context->idx_i; - uint8_t j = context->idx_j; - char *sbox = context->sbox; - - for (; length > 0; length--) - { - char t; - - i++; - j += sbox[i]; - t = sbox[i]; - sbox[i] = sbox[j]; - sbox[j] = t; - *outbuf++ = (*inbuf++ - ^ sbox[(0U + sbox[i] + sbox[j]) % ARCFOUR_SBOX_SIZE]); - } - - context->idx_i = i; - context->idx_j = j; -} - -/** @brief Initialize an @ref arcfour_context - * @param context Context structure - * @param key Key data - * @param keylen Length of key - * - * Initializes @p context using @p key. - */ -void -arcfour_setkey (arcfour_context * context, const char *key, size_t keylen) -{ - size_t i, j, k; - char *sbox = context->sbox; - - context->idx_i = context->idx_j = 0; - for (i = 0; i < ARCFOUR_SBOX_SIZE; i++) - sbox[i] = i; - for (i = j = k = 0; i < ARCFOUR_SBOX_SIZE; i++) - { - char t; - j = (j + sbox[i] + key[k]) % ARCFOUR_SBOX_SIZE; - t = sbox[i]; - sbox[i] = sbox[j]; - sbox[j] = t; - if (++k == keylen) - k = 0; - } -} diff --git a/lib/arcfour.h b/lib/arcfour.h deleted file mode 100644 index 4993961..0000000 --- a/lib/arcfour.h +++ /dev/null @@ -1,55 +0,0 @@ -/* arcfour.h --- The arcfour stream cipher - * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 - * Free Software Foundation, Inc. - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2, or (at your - * option) any later version. - * - * This file 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this file; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ -/** @file lib/arcfour.h - * @brief Arcfour (RC4-compatible) stream cipher implementation - */ - -/* Code from Libgcrypt adapted for gnulib by Simon Josefsson. */ - -#ifndef ARCFOUR_H -# define ARCFOUR_H - -# include -# include - -#define ARCFOUR_SBOX_SIZE 256 - -/** @brief Context structture for Arcfour stream cipher */ -typedef struct -{ - char sbox[ARCFOUR_SBOX_SIZE]; - uint8_t idx_i, idx_j; -} arcfour_context; - -/* Apply ARCFOUR stream to INBUF placing the result in OUTBUF, both of - LENGTH size. CONTEXT must be initialized with arcfour_setkey - before this function is called. */ -extern void -arcfour_stream (arcfour_context * context, - const char *inbuf, char *outbuf, size_t length); - -/* Initialize CONTEXT using encryption KEY of KEYLEN bytes. KEY - should be 40 bits (5 bytes) or longer. The KEY cannot be zero - length. */ -extern void -arcfour_setkey (arcfour_context * context, const char *key, size_t keylen); - -#endif /* ARCFOUR_H */ diff --git a/lib/lib.vcxproj b/lib/lib.vcxproj index f9087d1..5a12247 100644 --- a/lib/lib.vcxproj +++ b/lib/lib.vcxproj @@ -1,4 +1,4 @@ - + @@ -72,7 +72,6 @@ - @@ -105,6 +104,7 @@ + @@ -125,7 +125,6 @@ - @@ -156,6 +155,7 @@ + @@ -177,4 +177,4 @@ - \ No newline at end of file + diff --git a/lib/lib.vcxproj.filters b/lib/lib.vcxproj.filters index 281a585..a4f2458 100644 --- a/lib/lib.vcxproj.filters +++ b/lib/lib.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -48,9 +48,6 @@ Source Files - - Source Files - Source Files @@ -162,6 +159,9 @@ Source Files + + Source Files + @@ -212,9 +212,6 @@ Header Files - - Header Files - Header Files @@ -311,5 +308,8 @@ Header Files + + Header Files + - \ No newline at end of file + diff --git a/lib/random.c b/lib/random.c index e9933a2..ee53a9a 100644 --- a/lib/random.c +++ b/lib/random.c @@ -29,20 +29,20 @@ #include "random.h" #include "log.h" -#include "arcfour.h" +#include "salsa208.h" #include "basen.h" #include "mem.h" static int random_count; static int random_fd = -1; -static arcfour_context random_ctx[1]; +static salsa208_context random_ctx[1]; /** @brief Rekey the RNG * * Resets the RNG's key to a random one read from /dev/urandom */ static void random__rekey(void) { - char key[128]; + char key[32]; int n; if(random_fd < 0) { @@ -53,8 +53,8 @@ static void random__rekey(void) { disorder_fatal(errno, "reading from /dev/urandom"); if((size_t)n < sizeof key) disorder_fatal(0, "reading from /dev/urandom: short read"); - arcfour_setkey(random_ctx, key, sizeof key); - random_count = 8 * 1024 * 1024; + salsa208_setkey(random_ctx, key, sizeof key); + random_count = 256 * 1024 * 1024; } /** @brief Get random bytes @@ -64,9 +64,7 @@ static void random__rekey(void) { void random_get(void *ptr, size_t bytes) { if(random_count == 0) random__rekey(); - /* Encrypting 0s == just returning the keystream */ - memset(ptr, 0, bytes); - arcfour_stream(random_ctx, (char *)ptr, (char *)ptr, bytes); + salsa208_stream(random_ctx, 0, ptr, bytes); if(bytes > (size_t)random_count) random_count = 0; else diff --git a/lib/salsa208.c b/lib/salsa208.c new file mode 100644 index 0000000..a8adff4 --- /dev/null +++ b/lib/salsa208.c @@ -0,0 +1,258 @@ +/* salsa208.c --- The Salsa20/8 stream cipher + * Copyright (C) Mark Wooding + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * This file 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +/** @file lib/salsa208.c + * @brief Salsa20/8 stream cipher implementation + * + * For a description of the algorithm, see: + * + * Daniel J. Bernstein, `The Salsa20 family of stream ciphers', in Matthew + * Robshaw and Olivier Billet (eds.), `New Stream Cipher Designs', + * Springer--Verlag 2008, pp. 84--97; + * http://cr.yp.to/snuffle/salsafamily-20071225.pdf + * + * As far as I know, the best attack against all 8 rounds of Salsa20/8 is by + * Aumasson, Fischer, Khazaei, Meier, and Rechberger, which takes 2^251 + * operations to recover a 256-bit key, which is hopelessly impractical. + * Much more effective attacks are known against Salsa20/7, so we would have + * a tiny security margin if we were trying for security -- but we aren't. + * Instead, we want high-quality randomness for queue ids and for selecting + * random tracks. (The cookie machinery, which does want cryptographic + * security, makes its own arrangements.) Specifically, the intention is to + * replace RC4, which (a) is slow because it has a long dependency chain + * which plays badly with the deep pipelines in modern CPUs, and (b) has + * well-known and rather embarassing biases. On the other hand, Salsa20/8 + * has no known biases, and admits considerable instruction-level + * parallelism. In practice, Salsa20/8 is about 30% faster than RC4 even + * without a fancy SIMD implementation (which is good, because this isn't one + * of those); a vectorized implementation acting on multiple blocks at a time + * would be even faster. + * + * Salsa20/8 has a number of other attractive features, such as being + * trivially seekable, but we don't need those here and the necessary + * machinery is not implemented. + */ + +#include +#include + +#include "salsa208.h" + +static inline uint32_t ld16(const void *p) { + const unsigned char *q = p; + return ((uint32_t)q[0] << 0) | ((uint32_t)q[1] << 8); +} + +static inline uint32_t ld32(const void *p) { + const unsigned char *q = p; + return ((uint32_t)q[0] << 0) | ((uint32_t)q[1] << 8) | + ((uint32_t)q[2] << 16) | ((uint32_t)q[3] << 24); +} + +static inline void st32(void *p, uint32_t x) { + unsigned char *q = p; + q[0] = (x >> 0)&0xff; q[1] = (x >> 8)&0xff; + q[2] = (x >> 16)&0xff; q[3] = (x >> 24)&0xff; +} + +static inline uint32_t rol32(uint32_t x, unsigned n) + { return (x << n) | (x >> (32 - n)); } + +static inline void quarterround(uint32_t m[16], int a, int b, int c, int d) { + m[b] ^= rol32(m[a] + m[d], 7); m[c] ^= rol32(m[b] + m[a], 9); + m[d] ^= rol32(m[c] + m[b], 13); m[a] ^= rol32(m[d] + m[c], 18); +} + +static void core(salsa208_context *context) { + unsigned i; + uint32_t t[16]; + + /* Copy the state. */ + for(i = 0; i < 16; i++) t[i] = context->m[i]; + + /* Hack on the state. */ + for(i = 0; i < 4; i++) { + + /* Vertical quarter-rounds. */ + quarterround(t, 0, 4, 8, 12); + quarterround(t, 5, 9, 13, 1); + quarterround(t, 10, 14, 2, 6); + quarterround(t, 15, 3, 7, 11); + + /* Horizontal quarter-rounds. */ + quarterround(t, 0, 1, 2, 3); + quarterround(t, 5, 6, 7, 4); + quarterround(t, 10, 11, 8, 9); + quarterround(t, 15, 12, 13, 14); + } + + /* Final feedforward. */ + for(i = 0; i < 16; i++) t[i] += context->m[i]; + + /* Output. */ + for(i = 0; i < 16; i++) st32(context->buf + 4*i, t[i]); +} + +static inline void xorbuf(void *z, const void *x, const void *y, size_t sz) { + unsigned char *zz = z; + const unsigned char *xx = x, *yy = y; + + if(!xx) memcpy(zz, yy, sz); + else while(sz--) *zz++ = *xx++ ^ *yy++; +} + +static inline void step(salsa208_context *context) + { if(!++context->m[8]) context->m[9]++; } + +/** @brief Encrypt or decrypt data using Salsa20/8. + * + * @param context The Salsa20/8 context, initialized using salsa208_setkey(). + * @param inbuf Pointer to input buffer + * @param outbuf Pointer to output buffer + * @param length Common size of both buffers + * + * Encrypt or decrypt (the operations are the same) @p length bytes of input + * data, writing the result, of the same length, to @p outbuf. The input and + * output pointers may be equal; the two buffers may not otherwise overlap. + * + * If @p inbuf is null, then simply write the next @p length bytes of + * Salsa20/8 output to @p outbuf. + */ +void salsa208_stream(salsa208_context *context, + const void *inbuf, void *outbuf, size_t length) { + size_t left = 64 - context->i; + unsigned char *z = outbuf; + const unsigned char *x = inbuf; + + /* If we can satisfy the request from our buffer then we should do that. */ + if(length <= left) { + xorbuf(z, x, context->buf + context->i, length); + context->i += length; + return; + } + + /* Drain the buffer of what we currently have and cycle the state. */ + xorbuf(z, x, context->buf + context->i, left); + length -= left; z += left; if(x) x += left; + core(context); step(context); + + /* Take multiple complete blocks directly. */ + while(length > 64) { + xorbuf(z, x, context->buf, 64); + length -= 64; z += 64; if(x) x += 64; + core(context); step(context); + } + + /* And the final tail end. */ + xorbuf(z, x, context->buf, length); + context->i = length; +} + +/** @brief Initialize a Salsa20/8 context. + * + * @param context The Salsa20/8 context to initialize + * @param key A pointer to the key material + * @param keylen The length of the key data, in bytes (must be 10, 16, or 32) + * + * The context is implicitly initialized with a zero nonce, which is fine if + * the key will be used only for a single message. Otherwise, a fresh nonce + * should be chosen somehow and set using salsa208_setnonce(). + */ +void salsa208_setkey(salsa208_context *context, + const void *key, size_t keylen) { + const unsigned char *k = key; + switch(keylen) { + case 32: + context->m[ 0] = 0x61707865; + context->m[ 1] = ld32(k + 0); + context->m[ 2] = ld32(k + 4); + context->m[ 3] = ld32(k + 8); + context->m[ 4] = ld32(k + 12); + context->m[ 5] = 0x3320646e; + context->m[ 6] = 0; + context->m[ 7] = 0; + context->m[ 8] = 0; + context->m[ 9] = 0; + context->m[10] = 0x79622d32; + context->m[11] = ld32(k + 16); + context->m[12] = ld32(k + 20); + context->m[13] = ld32(k + 24); + context->m[14] = ld32(k + 28); + context->m[15] = 0x6b206574; + break; + case 16: + context->m[ 0] = 0x61707865; + context->m[ 1] = ld32(k + 0); + context->m[ 2] = ld32(k + 4); + context->m[ 3] = ld32(k + 8); + context->m[ 4] = ld32(k + 12); + context->m[ 5] = 0x3120646e; + context->m[ 6] = 0; + context->m[ 7] = 0; + context->m[ 8] = 0; + context->m[ 9] = 0; + context->m[10] = 0x79622d36; + context->m[11] = context->m[1]; + context->m[12] = context->m[2]; + context->m[13] = context->m[3]; + context->m[14] = context->m[4]; + context->m[15] = 0x6b206574; + break; + case 10: + context->m[ 0] = 0x61707865; + context->m[ 1] = ld32(k + 0); + context->m[ 2] = ld32(k + 4); + context->m[ 3] = ld16(k + 8); + context->m[ 4] = 0; + context->m[ 5] = 0x3120646e; + context->m[ 6] = 0; + context->m[ 7] = 0; + context->m[ 8] = 0; + context->m[ 9] = 0; + context->m[10] = 0x79622d30; + context->m[11] = context->m[1]; + context->m[12] = context->m[2]; + context->m[13] = context->m[3]; + context->m[14] = 0; + context->m[15] = 0x6b206574; + break; + default: + assert(!"bad Salsa20 key length"); + } + context->i = 64; +} + +/** @brief Set the Salsa20/8 nonce. + * + * @param context The Salsa20/8 context + * @param nonce A pointer to the nonce + * @param noncelen The length of the nonce data, in bytes (must be exactly 8) + * + * The context is automatically rewound to the start of the stream + * corresponding to this nonce. + */ +void salsa208_setnonce(salsa208_context *context, + const void *nonce, size_t noncelen) { + const unsigned char *n = nonce; + assert(noncelen == 8); + context->m[6] = ld32(n + 0); + context->m[7] = ld32(n + 4); + context->m[8] = context->m[9] = 0; + context->i = 64; +} diff --git a/lib/salsa208.h b/lib/salsa208.h new file mode 100644 index 0000000..3a4c230 --- /dev/null +++ b/lib/salsa208.h @@ -0,0 +1,44 @@ +/* salsa208.h --- The Salsa20/8 stream cipher + * Copyright (C) 2018 Mark Wooding + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * This file 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this file; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +/** @file lib/salsa208.h + * @brief Salsa20/8 stream cipher implementation + */ + +#ifndef SALSA208_H +# define SALSA208_H + +# include +# include + +/** @brief Context structure for Salsa208 stream cipher */ +typedef struct { + uint32_t m[16]; /* the raw state matrix */ + uint8_t buf[64]; /* current output buffer */ + unsigned i; /* cursor in output buffer */ +} salsa208_context; + +extern void salsa208_stream(salsa208_context *context, + const void *inbuf, void *outbuf, size_t length); +extern void salsa208_setkey(salsa208_context *context, + const void *key, size_t keylen); +extern void salsa208_setnonce(salsa208_context *context, + const void *nonce, size_t noncelen); + +#endif /* SALSA208_H */ diff --git a/libtests/Makefile.am b/libtests/Makefile.am index 83a7f97..e6fdaa7 100644 --- a/libtests/Makefile.am +++ b/libtests/Makefile.am @@ -16,12 +16,12 @@ # along with this program. If not, see . # -TESTS=t-addr t-arcfour t-basen t-bits t-cache t-casefold t-charset \ +TESTS=t-addr t-basen t-bits t-cache t-casefold t-charset \ t-cookies t-dateparse t-event t-filepart t-hash t-heap t-hex \ t-kvp t-mime t-printf t-regsub t-selection t-signame t-sink \ t-split t-syscalls t-trackname t-unicode t-url t-utf8 t-vector \ t-words t-wstat t-macros t-cgi t-eventdist t-resample \ - t-configuration t-timeval + t-configuration t-timeval t-salsa208 noinst_PROGRAMS=$(TESTS) @@ -29,7 +29,6 @@ AM_CPPFLAGS=-I${top_srcdir}/lib -I../lib LDADD=../lib/libdisorder.a $(LIBPCRE) $(LIBICONV) $(LIBGC) t_addr_SOURCES=t-addr.c test.c test.h -t_arcfour_SOURCES=t-arcfour.c test.c test.h t_basen_SOURCES=t-basen.c test.c test.h t_bits_SOURCES=t-bits.c test.c test.h t_cache_SOURCES=t-cache.c test.c test.h @@ -68,6 +67,7 @@ t_resample_LDADD=$(LDADD) $(LIBSAMPLERATE) t_configuration_SOURCES=t-configuration.c test.c test.h t_configuration_LDADD=$(LDADD) $(LIBGCRYPT) t_timeval_SOURCES=t-timeval.c test.c test.h +t_salsa208_SOURCES=t-salsa208.c test.c test.h check-report: before-check check make-coverage-reports before-check: diff --git a/libtests/t-arcfour.c b/libtests/t-arcfour.c deleted file mode 100644 index 3ae26fb..0000000 --- a/libtests/t-arcfour.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of DisOrder. - * Copyright (C) 2008 Richard Kettlewell - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include "test.h" -#include "arcfour.h" - -#define TEST_ARCFOUR(K, P, C) do { \ - arcfour_setkey(ac, K, strlen(K)); \ - arcfour_stream(ac, P, (char *)output, strlen(P)); \ - output_hex = hex(output, strlen(P)); \ - check_string(output_hex, C); \ -} while(0) - -static void test_arcfour(void) { - arcfour_context ac[1]; - uint8_t output[64]; - char *output_hex; - - /* from wikipedia */ - TEST_ARCFOUR("Key", "Plaintext", "bbf316e8d940af0ad3"); - TEST_ARCFOUR("Wiki", "pedia", "1021bf0420"); - TEST_ARCFOUR("Secret", "Attack at dawn", "45a01f645fc35b383552544b9bf5"); - -} - -TEST(arcfour); - -/* -Local Variables: -c-basic-offset:2 -comment-column:40 -fill-column:79 -indent-tabs-mode:nil -End: -*/ diff --git a/libtests/t-salsa208.c b/libtests/t-salsa208.c new file mode 100644 index 0000000..47779d2 --- /dev/null +++ b/libtests/t-salsa208.c @@ -0,0 +1,60 @@ +/* + * This file is part of DisOrder. + * Copyright (C) 2008 Richard Kettlewell, 2018 Mark Wooding + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "test.h" +#include "salsa208.h" + +#define TEST_SALSA208(K, N, P, C) do { \ + Kbytes = unhex(K, &Klen); \ + salsa208_setkey(ac, Kbytes, Klen); \ + Nbytes = unhex(N, &Nlen); \ + salsa208_setnonce(ac, Nbytes, Nlen); \ + Pbytes = unhex(P, &Plen); \ + salsa208_stream(ac, Pbytes, output, Plen); \ + output_hex = hex(output, Plen); \ + check_string(output_hex, C); \ +} while(0) + +static void test_salsa208(void) { + salsa208_context ac[1]; + uint8_t output[80], *Kbytes, *Nbytes, *Pbytes; + char *output_hex; + size_t Klen, Nlen, Plen; + + /* from the eStream submission */ + TEST_SALSA208("0f62b5085bae0154a7fa4da0f34699ec3f92e5388bde3184d72a7dd02376c91c", + "288ff65dc42b92f9", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "36ceb42e23ce2fed61d1a4e5a6e0a600dcca12ce4f1316c175c0bde0825d90972f574a7a25665fe6c3b91a70f1b83795330f5cfa8922c8f9b0589beade0b1432"); + + /* test against Catacomb implementation; checks XOR, state stepping */ + TEST_SALSA208("ce9b04eeb18bb1434d6f534880d8516ff65158f60832325269b5c5e517adb27e", + "41f4e1e0db3ef6f2", + "d3df3ab24ce7ef617148fdd461757d81b1b3abecb808b4e3ebb542675597c0ab6a4ae3888a7717a8eb2f80b8a3ca33e8c4280757b2f71d409c8618ee50648e35810dfdcbb3ad9436368fde5e645ef019", + "3132381a28814d1989bcf09656e64a0ee8c6dd723a3ba5f6a02111f86f5156321ea7300976b2393821d44c425754f6cc08b755ea07287cc77fead40c581259d24d127880b7597fc6a9ea8fba89dd3f4c"); +} + +TEST(salsa208); + +/* +Local Variables: +c-basic-offset:2 +comment-column:40 +fill-column:79 +indent-tabs-mode:nil +End: +*/