Hi! Please find attached a port of DJB's public domain code for Salsa20 to nettle. The patch is not meant to be applied as-is but to start a discussion. Review of the code itself is welcome.
While writing this I noticed a sub-optimal design of Nettle, in that it overloads the meaning of struct nettle_cipher->block_size as a flag of whether the cipher is a stream cipher or not. Before arcfour was the only stream cipher in nettle, and using block_size=0 to signal that it is a stream cipher worked fine. However, Salsa20 has a block size of 8 bytes. Another odd thing is that Salsa20 requires an IV. So some changes to the nettle_cipher struct are required.
This could be resolved better than I have done in the patch below. I see two reasonable alternatives:
1) Introduce a new struct 'struct nettle_stream_cipher' that applies to stream ciphers and use that.
2) Add a flag in 'struct nettle_cipher' to tell whether the cipher is a stream cipher or not.
I started out strongly prefering 1) because it appeared cleaner. After thinking about the changes required to implement that, I am now leaning towards 2) because of:
A) a lot of code would have to be duplicated if we have both 'struct nettle_cipher' and 'struct nettle_stream_cipher' for apparently little gain. Otherwise, most code could be the same, and where the distinction matters there could be a simple if-test.
B) it allows for full backwards compatibility in a clean way. With 1) we would have a transition period where people switch arcfour usage from nettle_cipher to nettle_stream_cipher. With 2) arcfour would continue to have block_size==0 but it would also set the new stream cipher flag. External code could incrementally be updated to check the new flag instead of block_size==0 (if it does that at all) but that is something that doesn't uglify nettle.
What do you think? I'd be happy to propose a patch to implement 2) and then a follow-on patch to add support for Salsa20.
/Simon
From 600ae2815634ad95c4d2d93821316ce20df19ae3 Mon Sep 17 00:00:00 2001
From: Simon Josefsson simon@josefsson.org Date: Wed, 21 Mar 2012 17:06:13 +0100 Subject: [PATCH] Implement Salsa20.
--- Makefile.in | 3 +- examples/nettle-benchmark.c | 3 + nettle-meta-ciphers.c | 2 + nettle-meta.h | 8 ++- nettle-types.h | 5 + salsa20-meta.c | 49 ++++++++++++ salsa20.c | 172 ++++++++++++++++++++++++++++++++++++++++++ salsa20.h | 71 +++++++++++++++++ testsuite/.gitignore | 1 + testsuite/.test-rules.make | 3 + testsuite/Makefile.in | 1 + testsuite/meta-cipher-test.c | 2 + testsuite/salsa20-test.c | 49 ++++++++++++ testsuite/testutils.c | 36 +++++++-- testsuite/testutils.h | 10 +++ 15 files changed, 407 insertions(+), 8 deletions(-) create mode 100644 salsa20-meta.c create mode 100644 salsa20.c create mode 100644 salsa20.h create mode 100644 testsuite/salsa20-test.c
diff --git a/Makefile.in b/Makefile.in index 1813a0d..6e2ec60 100644 --- a/Makefile.in +++ b/Makefile.in @@ -79,6 +79,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \ md2.c md2-meta.c md4.c md4-meta.c \ md5.c md5-compress.c md5-compat.c md5-meta.c \ ripemd160.c ripemd160-compress.c ripemd160-meta.c \ + salsa20.c salsa20-meta.c \ sha1.c sha1-compress.c sha1-meta.c \ sha256.c sha256-compress.c sha224-meta.c sha256-meta.c \ sha512.c sha512-compress.c sha384-meta.c sha512-meta.c \ @@ -113,7 +114,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ pgp-encode.c rsa2openpgp.c \ der-iterator.c der2rsa.c der2dsa.c
-HEADERS = aes.h arcfour.h arctwo.h asn1.h bignum.h blowfish.h \ +HEADERS = aes.h arcfour.h salsa20.h arctwo.h asn1.h bignum.h blowfish.h \ base16.h base64.h buffer.h camellia.h cast128.h \ cbc.h ctr.h gcm.h \ des.h des-compat.h dsa.h \ diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c index 424ef19..44fca4e 100644 --- a/examples/nettle-benchmark.c +++ b/examples/nettle-benchmark.c @@ -40,6 +40,7 @@
#include "aes.h" #include "arcfour.h" +#include "salsa20.h" #include "blowfish.h" #include "cast128.h" #include "cbc.h" @@ -612,6 +613,8 @@ main(int argc, char **argv) OPENSSL(&nettle_openssl_aes192) OPENSSL(&nettle_openssl_aes256) &nettle_arcfour128, OPENSSL(&nettle_openssl_arcfour128) + &nettle_salsa20_128, + &nettle_salsa20_256, &nettle_blowfish128, OPENSSL(&nettle_openssl_blowfish128) &nettle_camellia128, &nettle_camellia192, &nettle_camellia256, &nettle_cast128, OPENSSL(&nettle_openssl_cast128) diff --git a/nettle-meta-ciphers.c b/nettle-meta-ciphers.c index 1f07595..aae90f9 100644 --- a/nettle-meta-ciphers.c +++ b/nettle-meta-ciphers.c @@ -36,6 +36,8 @@ const struct nettle_cipher * const nettle_ciphers[] = { &nettle_camellia192, &nettle_camellia256, &nettle_cast128, + &nettle_salsa20_128, + &nettle_salsa20_256, &nettle_serpent128, &nettle_serpent192, &nettle_serpent256, diff --git a/nettle-meta.h b/nettle-meta.h index 54cbbd2..c8aabda 100644 --- a/nettle-meta.h +++ b/nettle-meta.h @@ -5,6 +5,7 @@
/* nettle, low-level cryptographics library * + * Copyright (C) 2012 Simon Josefsson * Copyright (C) 2002 Niels Möller * * The nettle library is free software; you can redistribute it and/or modify @@ -39,7 +40,7 @@ struct nettle_cipher
unsigned context_size;
- /* Zero for stream ciphers */ + /* Block size; 0 for byte-oriented stream ciphers. */ unsigned block_size;
/* Suggested key size; other sizes are sometimes possible. */ @@ -50,6 +51,8 @@ struct nettle_cipher
nettle_crypt_func *encrypt; nettle_crypt_func *decrypt; + + nettle_set_iv_func *set_iv; };
#define _NETTLE_CIPHER(name, NAME, key_size) { \ @@ -105,6 +108,9 @@ extern const struct nettle_cipher nettle_aes256;
extern const struct nettle_cipher nettle_arcfour128;
+extern const struct nettle_cipher nettle_salsa20_128; +extern const struct nettle_cipher nettle_salsa20_256; + extern const struct nettle_cipher nettle_camellia128; extern const struct nettle_cipher nettle_camellia192; extern const struct nettle_cipher nettle_camellia256; diff --git a/nettle-types.h b/nettle-types.h index b694332..e68cacb 100644 --- a/nettle-types.h +++ b/nettle-types.h @@ -2,6 +2,7 @@
/* nettle, low-level cryptographics library * + * Copyright (C) 2012 Simon Josefsson * Copyright (C) 2005 Niels Möller * * The nettle library is free software; you can redistribute it and/or modify @@ -44,6 +45,10 @@ typedef void nettle_set_key_func(void *ctx, unsigned length, const uint8_t *key);
+typedef void nettle_set_iv_func(void *ctx, + unsigned length, + const uint8_t *iv); + /* Uses a void * for cipher contexts.
For block ciphers it would make sense with a const void * for the diff --git a/salsa20-meta.c b/salsa20-meta.c new file mode 100644 index 0000000..8278e09 --- /dev/null +++ b/salsa20-meta.c @@ -0,0 +1,49 @@ +/* salsa20-meta.c */ + +/* nettle, low-level cryptographics library + * + * 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., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "nettle-meta.h" + +#include "salsa20.h" + +const struct nettle_cipher nettle_salsa20_128 = + { "salsa20-128", sizeof(struct salsa20_ctx), + 8, 16, + (nettle_set_key_func *) salsa20_set_key, + (nettle_set_key_func *) salsa20_set_key, + (nettle_crypt_func *) salsa20_crypt, + (nettle_crypt_func *) salsa20_crypt, + (nettle_set_iv_func *) salsa20_set_iv + }; + +const struct nettle_cipher nettle_salsa20_256 = + { "salsa20-256", sizeof(struct salsa20_ctx), + 8, 32, + (nettle_set_key_func *) salsa20_set_key, + (nettle_set_key_func *) salsa20_set_key, + (nettle_crypt_func *) salsa20_crypt, + (nettle_crypt_func *) salsa20_crypt, + (nettle_set_iv_func *) salsa20_set_iv + }; diff --git a/salsa20.c b/salsa20.c new file mode 100644 index 0000000..7885199 --- /dev/null +++ b/salsa20.c @@ -0,0 +1,172 @@ +/* salsa20.c + * + * The Salsa20 stream cipher. + */ + +/* nettle, low-level cryptographics library + * + * 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., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include <assert.h> + +#include "salsa20.h" + +#define ROTL32(x,n) ((((x))<<(n)) | (((x))>>(32-(n)))) + +#define SWAP32(v) \ + ((ROTL32(v, 8) & 0x00FF00FFUL) | \ + (ROTL32(v, 24) & 0xFF00FF00UL)) + +#ifdef WORDS_BIGENDIAN +#define U32TO32_LITTLE(v) SWAP32(v) +#else +#define U32TO32_LITTLE(v) (v) +#endif + +#define U8TO32_LITTLE(p) U32TO32_LITTLE(((uint32_t*)(p))[0]) +#define U32TO8_LITTLE(p, v) (((uint32_t*)(p))[0] = U32TO32_LITTLE(v)) + +/* +salsa20-ref.c version 20051118 +D. J. Bernstein +Public domain. +*/ + +#define ROTATE(v,c) (ROTL32(v,c)) +#define XOR(v,w) ((v) ^ (w)) +#define PLUS(v,w) ((v) + (w)) +#define PLUSONE(v) (PLUS((v),1)) + +static void salsa20_wordtobyte(uint8_t output[64],const uint32_t input[16]) +{ + uint32_t x[16]; + int i; + + for (i = 0;i < 16;++i) x[i] = input[i]; + for (i = 20;i > 0;i -= 2) { + x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7)); + x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9)); + x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13)); + x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18)); + x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7)); + x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9)); + x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13)); + x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18)); + x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7)); + x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9)); + x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13)); + x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18)); + x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7)); + x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9)); + x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13)); + x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18)); + x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7)); + x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9)); + x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13)); + x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18)); + x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7)); + x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9)); + x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13)); + x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18)); + x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7)); + x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9)); + x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13)); + x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18)); + x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7)); + x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9)); + x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13)); + x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18)); + } + for (i = 0;i < 16;++i) x[i] = PLUS(x[i],input[i]); + for (i = 0;i < 16;++i) U32TO8_LITTLE(output + 4 * i,x[i]); +} + +static const char sigma[16] = "expand 32-byte k"; +static const char tau[16] = "expand 16-byte k"; + +void +salsa20_set_key(struct salsa20_ctx *ctx, + unsigned length, const uint8_t *key) +{ + const char *constants; + + assert (length == SALSA20_MIN_KEY_SIZE || length == SALSA20_MAX_KEY_SIZE); + + ctx->input[1] = U8TO32_LITTLE(key + 0); + ctx->input[2] = U8TO32_LITTLE(key + 4); + ctx->input[3] = U8TO32_LITTLE(key + 8); + ctx->input[4] = U8TO32_LITTLE(key + 12); + if (length == SALSA20_MAX_KEY_SIZE) { /* recommended */ + key += 16; + constants = sigma; + } else { /* kbits == 128 */ + constants = tau; + } + ctx->input[11] = U8TO32_LITTLE(key + 0); + ctx->input[12] = U8TO32_LITTLE(key + 4); + ctx->input[13] = U8TO32_LITTLE(key + 8); + ctx->input[14] = U8TO32_LITTLE(key + 12); + ctx->input[0] = U8TO32_LITTLE(constants + 0); + ctx->input[5] = U8TO32_LITTLE(constants + 4); + ctx->input[10] = U8TO32_LITTLE(constants + 8); + ctx->input[15] = U8TO32_LITTLE(constants + 12); +} + +void +salsa20_set_iv(struct salsa20_ctx *ctx, unsigned length, const uint8_t *iv) +{ + assert (length == SALSA20_IV_SIZE); + + ctx->input[6] = U8TO32_LITTLE(iv + 0); + ctx->input[7] = U8TO32_LITTLE(iv + 4); + ctx->input[8] = 0; + ctx->input[9] = 0; +} + +void +salsa20_crypt(struct salsa20_ctx *ctx, + unsigned length, + uint8_t *c, + const uint8_t *m) +{ + uint8_t output[64]; + unsigned i; + + if (!length) return; + for (;;) { + salsa20_wordtobyte(output,ctx->input); + ctx->input[8] = PLUSONE(ctx->input[8]); + if (!ctx->input[8]) { + ctx->input[9] = PLUSONE(ctx->input[9]); + /* stopping at 2^70 length per nonce is user's responsibility */ + } + if (length <= 64) { + for (i = 0;i < length;++i) c[i] = m[i] ^ output[i]; + return; + } + for (i = 0;i < 64;++i) c[i] = m[i] ^ output[i]; + length -= 64; + c += 64; + m += 64; + } +} diff --git a/salsa20.h b/salsa20.h new file mode 100644 index 0000000..79f1505 --- /dev/null +++ b/salsa20.h @@ -0,0 +1,71 @@ +/* salsa20.h + * + * The Salsa20 stream cipher. + */ + +/* nettle, low-level cryptographics library + * + * 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., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef NETTLE_SALSA20_H_INCLUDED +#define NETTLE_SALSA20_H_INCLUDED + +#include "nettle-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Name mangling */ +#define salsa20_set_key nettle_salsa20_set_key +#define salsa20_set_iv nettle_salsa20_set_iv +#define salsa20_crypt nettle_salsa20_crypt + +/* Minimum and maximum keysizes, and a reasonable default. In + * octets.*/ +#define SALSA20_MIN_KEY_SIZE 16 +#define SALSA20_MAX_KEY_SIZE 32 +#define SALSA20_KEY_SIZE 32 + +#define SALSA20_IV_SIZE 8 + +struct salsa20_ctx +{ + uint32_t input[16]; +}; + +void +salsa20_set_key(struct salsa20_ctx *ctx, + unsigned length, const uint8_t *key); + +void +salsa20_set_iv(struct salsa20_ctx *ctx, + unsigned length, const uint8_t *iv); + +void +salsa20_crypt(struct salsa20_ctx *ctx, + unsigned length, uint8_t *dst, + const uint8_t *src); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_SALSA20_H_INCLUDED */ diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 1147cfb..c9f4698 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -36,6 +36,7 @@ /rsa-keygen-test /rsa-test /rsa2sexp-test +/salsa20-test /serpent-test /sexp-format-test /sexp-test diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make index e8f6650..10c993f 100644 --- a/testsuite/.test-rules.make +++ b/testsuite/.test-rules.make @@ -49,6 +49,9 @@ memxor-test$(EXEEXT): memxor-test.$(OBJEXT) ripemd160-test$(EXEEXT): ripemd160-test.$(OBJEXT) $(LINK) ripemd160-test.$(OBJEXT) $(TEST_OBJS) -o ripemd160-test$(EXEEXT)
+salsa20-test$(EXEEXT): salsa20-test.$(OBJEXT) + $(LINK) salsa20-test.$(OBJEXT) $(TEST_OBJS) -o salsa20-test$(EXEEXT) + sha1-test$(EXEEXT): sha1-test.$(OBJEXT) $(LINK) sha1-test.$(OBJEXT) $(TEST_OBJS) -o sha1-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index 8dfc62b..10ffae9 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -18,6 +18,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \ md2-test.c md4-test.c md5-test.c md5-compat-test.c \ memxor-test.c \ ripemd160-test.c \ + salsa20-test.c \ sha1-test.c sha224-test.c sha256-test.c \ sha384-test.c sha512-test.c \ serpent-test.c twofish-test.c \ diff --git a/testsuite/meta-cipher-test.c b/testsuite/meta-cipher-test.c index 1bb74d8..50a02ba 100644 --- a/testsuite/meta-cipher-test.c +++ b/testsuite/meta-cipher-test.c @@ -14,6 +14,8 @@ const char* ciphers[] = { "camellia192", "camellia256", "cast128", + "salsa20-128", + "salsa20-256", "serpent128", "serpent192", "serpent256", diff --git a/testsuite/salsa20-test.c b/testsuite/salsa20-test.c new file mode 100644 index 0000000..e1c13dd --- /dev/null +++ b/testsuite/salsa20-test.c @@ -0,0 +1,49 @@ +#include "testutils.h" +#include "salsa20.h" + +int +test_main(void) +{ + /* http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sal... */ + + test_cipher_iv(&nettle_salsa20_128, + HL("80000000 00000000 00000000 00000000"), + HL("00000000 00000000"), + HL("00000000 00000000"), + H("4DFA5E48 1DA23EA0")); + + test_cipher_iv(&nettle_salsa20_128, + HL("00000000 00000000 00000000 00000000"), + HL("80000000 00000000"), + HL("00000000 00000000"), + H("B66C1E44 46DD9557")); + + test_cipher_iv(&nettle_salsa20_128, + HL("0053A6F94C9FF24598EB3E91E4378ADD"), + HL("0D74DB42A91077DE"), + HL("00000000 00000000"), + H("05E1E7BE B697D999")); + + test_cipher_iv(&nettle_salsa20_256, + HL("80000000 00000000 00000000 00000000" + "00000000 00000000 00000000 00000000"), + HL("00000000 00000000"), + HL("00000000 00000000"), + H("E3BE8FDD 8BECA2E3")); + + test_cipher_iv(&nettle_salsa20_256, + HL("00000000 00000000 00000000 00000000" + "00000000 00000000 00000000 00000000"), + HL("80000000 00000000"), + HL("00000000 00000000"), + H("2ABA3DC45B494700")); + + test_cipher_iv(&nettle_salsa20_256, + HL("0053A6F94C9FF24598EB3E91E4378ADD" + "3083D6297CCF2275C81B6EC11467BA0D"), + HL("0D74DB42A91077DE"), + HL("00000000 00000000"), + H("F5FAD53F 79F9DF58")); + + SUCCESS(); +} diff --git a/testsuite/testutils.c b/testsuite/testutils.c index d77bb7e..8f5dab0 100644 --- a/testsuite/testutils.c +++ b/testsuite/testutils.c @@ -162,17 +162,21 @@ main(int argc, char **argv) }
void -test_cipher(const struct nettle_cipher *cipher, - unsigned key_length, - const uint8_t *key, - unsigned length, - const uint8_t *cleartext, - const uint8_t *ciphertext) +test_cipher_iv(const struct nettle_cipher *cipher, + unsigned key_length, + const uint8_t *key, + unsigned iv_length, + const uint8_t *iv, + unsigned length, + const uint8_t *cleartext, + const uint8_t *ciphertext) { void *ctx = xalloc(cipher->context_size); uint8_t *data = xalloc(length);
cipher->set_encrypt_key(ctx, key_length, key); + if (iv_length > 0 && iv) + cipher->set_iv(ctx, iv_length, iv); cipher->encrypt(ctx, length, data, cleartext);
if (!MEMEQ(length, data, ciphertext)) @@ -187,6 +191,8 @@ test_cipher(const struct nettle_cipher *cipher, FAIL(); } cipher->set_decrypt_key(ctx, key_length, key); + if (iv_length > 0 && iv) + cipher->set_iv(ctx, iv_length, iv); cipher->decrypt(ctx, length, data, data);
if (!MEMEQ(length, data, cleartext)) @@ -206,6 +212,24 @@ test_cipher(const struct nettle_cipher *cipher, }
void +test_cipher(const struct nettle_cipher *cipher, + unsigned key_length, + const uint8_t *key, + unsigned length, + const uint8_t *cleartext, + const uint8_t *ciphertext) +{ + test_cipher_iv(cipher, + key_length, + key, + 0, + NULL, + length, + cleartext, + ciphertext); +} + +void test_cipher_cbc(const struct nettle_cipher *cipher, unsigned key_length, const uint8_t *key, diff --git a/testsuite/testutils.h b/testsuite/testutils.h index d7ced9a..9d13dff 100644 --- a/testsuite/testutils.h +++ b/testsuite/testutils.h @@ -91,6 +91,16 @@ test_cipher(const struct nettle_cipher *cipher, const uint8_t *ciphertext);
void +test_cipher_iv(const struct nettle_cipher *cipher, + unsigned key_length, + const uint8_t *key, + unsigned iv_length, + const uint8_t *iv, + unsigned length, + const uint8_t *cleartext, + const uint8_t *ciphertext); + +void test_cipher_cbc(const struct nettle_cipher *cipher, unsigned key_length, const uint8_t *key,