diff --git a/doc/crypt.tex b/doc/crypt.tex
index 1c3a10288..150cc45b8 100644
--- a/doc/crypt.tex
+++ b/doc/crypt.tex
@@ -1250,13 +1250,17 @@ \chapter{Stream Ciphers}
however LibTomCrypt's implementation works with bytes).
The API for all stream ciphers operates in mode: \textit{setup} -- \textit{crypt} -- \textit{crypt} -- ... -- \textit{done}.
+The proper order of progression through these modes is enforced with a \textit{status} flag in the cipher's state.
+(An empty state has a \textit{status} of 0, a state after \textit{setup} has a \textit{status} of 1 or 3,
+and a state after \textit{setiv} has a \textit{status} of 2.)
+
Please note that both encryption and decryption are implemented via \textit{crypt}.
Another useful feature of the stream ciphers API is generation of a random stream of bytes which works like:
\textit{setup} -- \textit{keystream} -- \textit{keystream} -- ... -- \textit{done}. The random stream generation is
implemented like encryption of a stream of \textit{0x00} bytes.
-Note: You shouldn't use the keystream interface as a PRNG, as it doesn't allow to re-seed the internal state.
+Note: You shouldn't use the keystream interface as a PRNG, as it doesn't allow re-seeding the internal state.
\mysection{ChaCha}
@@ -1336,7 +1340,7 @@ \chapter{Stream Ciphers}
\end{verbatim}
To initialize \textit{XSalsa20} for the recommended 20 rounds with a 256-bit
-key (32 bytes) and a 192-bit nonce (24 bytes), use:
+key (32 bytes) and a 192-bit nonce (24 bytes), use:
\begin{verbatim}
salsa20_state st;
@@ -1361,6 +1365,21 @@ \chapter{Stream Ciphers}
err = salsa20_done(&st);
\end{verbatim}
+Many encryptions/decryptions are performed on small data. To make this process easier,
+Salsa20 has a helper function \textit{salsa20\_onecall()} that with one function call,
+will instantiate a state, call \textit{salsa20\_setup()}, \textit{salsa20\_ivctr64()},
+\textit{salsa20\_crypt()}, and \textit{salsa20\_done()}, returning the crypted data.
+\begin{verbatim}
+int salsa20_onecall(key, keylen, iv ivlen, datain, datalen, rounds, dataout);
+\end{verbatim}
+
+XSalsa20 likewise has a helper function \textit{xsalsa20\_onecall()} that with one
+function call, will instantiate a state, call \textit{xsalsa20\_setup()},
+\textit{salsa20\_crypt()}, and \textit{salsa20\_done()}, returning the crypted data.
+\begin{verbatim}
+int xsalsa20_onecall(key, keylen, nonce, noncelen, datain, datalen, rounds, dataout);
+\end{verbatim}
+
For both \textit{Salsa20} and \textit{XSalsa20} rounds must be an even number
and if set to 0 the default number of rounds, 20, will be used.
\vspace{1mm}
@@ -1387,10 +1406,9 @@ \chapter{Stream Ciphers}
another stream cipher, and the block cipher Serpent. (Sosemanuk means "snow snake" in the
Cree Indian language.)
-Sosemanuk will accept a key between 1 and 256 bits, but Sosemanuk's security level of 128
-bits is achieved only if the key is between 128 and 256 bits. Keys longer than 128 bits
-are not guaranteed to provided higher security. The initialization vector is 128 bits.
-(All length arguments are expressed in bytes.)
+Sosemanuk will accept a key between 16 and 32 bytes (128 and 256 bits). The initialization
+vector is 16 bytes (128 bits). Keys longer than 128 bits are not guaranteed to increase
+Sosemanuk's security level of 128 bits. All length arguments are expressed in bytes.
See \url{http://www.ecrypt.eu.org/stream/p3ciphers/sosemanuk/sosemanuk_p3.pdf} for more
information.
@@ -1427,6 +1445,14 @@ \chapter{Stream Ciphers}
you do not need to re-run \textit{sosemanuk\_setup()} again, unless of course, you called
\textit{sosemanuk\_done()}.
+Many encryptions/decryptions are performed on small data. To make this process easier,
+Sosemanuk has a helper function \textit{sosemanuk\_onecall()} that with one function call,
+will instantiate a state, call \textit{sosemanuk\_setup()}, \textit{sosemanuk\_setiv()},
+\textit{sosemanuk\_crypt()}, and \textit{sosemanuk\_done()}, returning the crypted data.
+\begin{verbatim}
+int sosemanuk_onecall(key, keylen, iv ivlen, datain, datalen, dataout);
+\end{verbatim}
+
\mysection{Rabbit}
\textit{Rabbit}, along with Salsa20, Sosemanuk, and HC-128, was named one of the winners
@@ -7058,6 +7084,43 @@ \subsection{Radix to binary conversion}
print(names_list.value)
\end{verbatim}
+For stream ciphers, currently only Salsa20/XSalsa20 and Sosemanuk,
+LTC now supports an alternate and arguably a preferred way to get
+state sizes.
+\begin{verbatim}
+size = salsa20_state_size();
+size = sosemanuk_state_size();
+\end{verbatim}
+
+These new functions greatly simplify the supporting code needed
+in the calling programs. Using Python as an example, this new
+function instantiates \textit{sosemanuk\_state} with one line.
+\begin{verbatim}
+import ctypes
+...
+LTC = ctypes.CDLL('libtomcrypt.dylib')
+...
+state = ctypes.c_buffer(LTC.sosemanuk_state_size())
+\end{verbatim}
+replaces
+\begin{verbatim}
+import ctypes
+...
+LTC = ctypes.CDLL('libtomcrypt.dylib')
+...
+def _get_size(name):
+ size = ctypes.c_int(0)
+ rc = LTC.crypt_get_size(bytes(name), byref(size))
+ if rc != 0:
+ raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc))
+ return size.value
+...
+state = ctypes.c_buffer(_get_size(b'sosemanuk_state'))
+\end{verbatim}
+
+Over time this new alternate method will applied to all cipher and
+hash function state sizes.
+
\chapter{Programming Guidelines}
diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj
index da4fccab7..fd6fe96ed 100644
--- a/libtomcrypt_VS2008.vcproj
+++ b/libtomcrypt_VS2008.vcproj
@@ -1486,6 +1486,10 @@
RelativePath="src\misc\crypt\crypt_hash_is_valid.c"
>
+
+
diff --git a/makefile.mingw b/makefile.mingw
index 894b0422a..c7bfabb8e 100644
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -101,12 +101,12 @@ src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \
src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \
src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \
src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \
-src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \
-src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \
-src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \
-src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \
-src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \
-src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
+src/misc/crypt/crypt_helper_functions.o src/misc/crypt/crypt_inits.o \
+src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \
+src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \
+src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \
+src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \
+src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \
src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \
src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \
diff --git a/makefile.msvc b/makefile.msvc
index 9e039034d..c09731c40 100644
--- a/makefile.msvc
+++ b/makefile.msvc
@@ -94,12 +94,12 @@ src/misc/crypt/crypt_find_cipher_id.obj src/misc/crypt/crypt_find_hash.obj \
src/misc/crypt/crypt_find_hash_any.obj src/misc/crypt/crypt_find_hash_id.obj \
src/misc/crypt/crypt_find_hash_oid.obj src/misc/crypt/crypt_find_prng.obj src/misc/crypt/crypt_fsa.obj \
src/misc/crypt/crypt_hash_descriptor.obj src/misc/crypt/crypt_hash_is_valid.obj \
-src/misc/crypt/crypt_inits.obj src/misc/crypt/crypt_ltc_mp_descriptor.obj \
-src/misc/crypt/crypt_prng_descriptor.obj src/misc/crypt/crypt_prng_is_valid.obj \
-src/misc/crypt/crypt_prng_rng_descriptor.obj src/misc/crypt/crypt_register_all_ciphers.obj \
-src/misc/crypt/crypt_register_all_hashes.obj src/misc/crypt/crypt_register_all_prngs.obj \
-src/misc/crypt/crypt_register_cipher.obj src/misc/crypt/crypt_register_hash.obj \
-src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \
+src/misc/crypt/crypt_helper_functions.obj src/misc/crypt/crypt_inits.obj \
+src/misc/crypt/crypt_ltc_mp_descriptor.obj src/misc/crypt/crypt_prng_descriptor.obj \
+src/misc/crypt/crypt_prng_is_valid.obj src/misc/crypt/crypt_prng_rng_descriptor.obj \
+src/misc/crypt/crypt_register_all_ciphers.obj src/misc/crypt/crypt_register_all_hashes.obj \
+src/misc/crypt/crypt_register_all_prngs.obj src/misc/crypt/crypt_register_cipher.obj \
+src/misc/crypt/crypt_register_hash.obj src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \
src/misc/crypt/crypt_unregister_cipher.obj src/misc/crypt/crypt_unregister_hash.obj \
src/misc/crypt/crypt_unregister_prng.obj src/misc/error_to_string.obj src/misc/hkdf/hkdf.obj \
src/misc/hkdf/hkdf_test.obj src/misc/mem_neq.obj src/misc/padding/padding_depad.obj \
diff --git a/makefile.unix b/makefile.unix
index 4fa6ac732..f31b37cf5 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -111,12 +111,12 @@ src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \
src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \
src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \
src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \
-src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \
-src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \
-src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \
-src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \
-src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \
-src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
+src/misc/crypt/crypt_helper_functions.o src/misc/crypt/crypt_inits.o \
+src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \
+src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \
+src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \
+src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \
+src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \
src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \
src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \
diff --git a/makefile_include.mk b/makefile_include.mk
index b03f76d10..ec3d37f34 100644
--- a/makefile_include.mk
+++ b/makefile_include.mk
@@ -271,12 +271,12 @@ src/misc/crypt/crypt_find_cipher_id.o src/misc/crypt/crypt_find_hash.o \
src/misc/crypt/crypt_find_hash_any.o src/misc/crypt/crypt_find_hash_id.o \
src/misc/crypt/crypt_find_hash_oid.o src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o \
src/misc/crypt/crypt_hash_descriptor.o src/misc/crypt/crypt_hash_is_valid.o \
-src/misc/crypt/crypt_inits.o src/misc/crypt/crypt_ltc_mp_descriptor.o \
-src/misc/crypt/crypt_prng_descriptor.o src/misc/crypt/crypt_prng_is_valid.o \
-src/misc/crypt/crypt_prng_rng_descriptor.o src/misc/crypt/crypt_register_all_ciphers.o \
-src/misc/crypt/crypt_register_all_hashes.o src/misc/crypt/crypt_register_all_prngs.o \
-src/misc/crypt/crypt_register_cipher.o src/misc/crypt/crypt_register_hash.o \
-src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
+src/misc/crypt/crypt_helper_functions.o src/misc/crypt/crypt_inits.o \
+src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \
+src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \
+src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \
+src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \
+src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \
src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \
src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \
src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \
diff --git a/src/encauth/chachapoly/chacha20poly1305_setiv.c b/src/encauth/chachapoly/chacha20poly1305_setiv.c
index 4e770a013..80a9a1b49 100644
--- a/src/encauth/chachapoly/chacha20poly1305_setiv.c
+++ b/src/encauth/chachapoly/chacha20poly1305_setiv.c
@@ -41,6 +41,7 @@ int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv,
/* copy chacha20 key to temporary state */
for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i];
tmp_st.rounds = 20;
+ tmp_st.status = st->chacha.status;
/* set IV */
if (ivlen == 12) {
/* IV 32bit */
diff --git a/src/headers/tomcrypt_cipher.h b/src/headers/tomcrypt_cipher.h
index 4b983593d..34e9ad821 100644
--- a/src/headers/tomcrypt_cipher.h
+++ b/src/headers/tomcrypt_cipher.h
@@ -995,13 +995,22 @@ LTC_MUTEX_PROTO(ltc_cipher_mutex)
#ifdef LTC_CHACHA
typedef struct {
- ulong32 input[16];
+ ulong32 input[16];
unsigned char kstream[64];
unsigned long ksleft;
+ unsigned long rounds;
unsigned long ivlen;
- int rounds;
+ unsigned long status; /* 0=uninitialized, 1=finished setup(), 2=finished ivctrXX() */
} chacha_state;
+int chacha_state_size(void);
+
+int chacha_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned long rounds,
+ unsigned char *dataout);
+
int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds);
int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter);
int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter);
@@ -1015,14 +1024,22 @@ int chacha_test(void);
#ifdef LTC_SALSA20
typedef struct {
- ulong32 input[16];
+ ulong32 input[16];
unsigned char kstream[64];
unsigned long ksleft;
- unsigned long ivlen;
- int rounds;
+ unsigned long rounds;
+ unsigned long status; /* 0=uninitialized, 1,3=finished setup(), 2=finished setiv() */
} salsa20_state;
-int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds);
+int salsa20_state_size(void);
+
+int salsa20_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned long rounds,
+ unsigned char *dataout);
+
+int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, unsigned long rounds);
int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter);
int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen);
@@ -1033,9 +1050,17 @@ int salsa20_test(void);
#ifdef LTC_XSALSA20
+int xsalsa20_state_size(void);
+
+int xsalsa20_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned long rounds,
+ unsigned char *dataout);
+
int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen,
const unsigned char *nonce, unsigned long noncelen,
- int rounds);
+ unsigned long rounds);
int xsalsa20_test(void);
#endif /* LTC_XSALSA20 */
@@ -1043,23 +1068,32 @@ int xsalsa20_test(void);
#ifdef LTC_SOSEMANUK
typedef struct {
- ulong32 kc[100]; /* key_context */
- ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09;
- ulong32 r1, r2;
- /*
- * Buffering: the stream cipher produces output data by
- * blocks of 640 bits. buf[] contains such a block, and
- * "ptr" is the index of the next output byte.
- */
- unsigned char buf[80];
- unsigned ptr;
+ ulong32 kc[100]; /* key_context */
+ ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09;
+ ulong32 r1, r2;
+ /*
+ * Buffering: the stream cipher produces output data by
+ * blocks of 640 bits. buf[] contains such a block, and
+ * "ptr" is the index of the next output byte.
+ */
+ unsigned char buf[80];
+ unsigned ptr;
+ unsigned long ivlen;
+ unsigned long status; /* 0=uninitialized, 1=finished setup(), 2=finished setiv() */
} sosemanuk_state;
-int sosemanuk_setup(sosemanuk_state *ss, const unsigned char *key, unsigned long keylen);
-int sosemanuk_setiv(sosemanuk_state *ss, const unsigned char *iv, unsigned long ivlen);
-int sosemanuk_crypt(sosemanuk_state *ss, const unsigned char *in, unsigned long datalen, unsigned char *out);
-int sosemanuk_keystream(sosemanuk_state *ss, unsigned char *out, unsigned long outlen);
-int sosemanuk_done(sosemanuk_state *ss);
+int sosemanuk_state_size(void);
+
+int sosemanuk_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
+int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen);
+int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen);
+int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long datalen, unsigned char *out);
+int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen);
+int sosemanuk_done(sosemanuk_state *st);
int sosemanuk_test(void);
#endif /* LTC_SOSEMANUK */
@@ -1075,10 +1109,18 @@ typedef struct {
typedef struct {
rabbit_ctx master_ctx;
rabbit_ctx work_ctx;
- unsigned char block[16]; /* last keystream block containing unused bytes */
- ulong32 unused; /* count fm right */
+ unsigned char block[16]; /* last keystream block containing unused bytes */
+ ulong32 unused; /* count fm right */
+ ulong32 status; /* 0=uninitialized, 1=finished setup(), 2=finished setiv() */
} rabbit_state;
+int rabbit_state_size(void);
+
+int rabbit_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen);
int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen);
int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out);
@@ -1093,8 +1135,15 @@ int rabbit_test(void);
typedef struct {
unsigned int x, y;
unsigned char buf[256];
+ unsigned long status; /* 0=uninitialized, 1=finished setup() */
} rc4_state;
+int rc4_state_size(void);
+
+int rc4_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen);
int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen);
@@ -1110,9 +1159,17 @@ typedef struct {
initR[17], /* saved register contents */
konst, /* key dependent constant */
sbuf; /* partial word encryption buffer */
- int nbuf; /* number of part-word stream bits buffered */
+ ulong32 nbuf; /* number of part-word stream bits buffered */
+ ulong32 status; /* 0=uninitialized, 1=finished setup(), 2=finished setiv() */
} sober128_state;
+int sober128_state_size(void);
+
+int sober128_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout);
+
int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen);
int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen);
int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out);
diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h
index 277271868..cc2e9cb33 100644
--- a/src/headers/tomcrypt_custom.h
+++ b/src/headers/tomcrypt_custom.h
@@ -641,6 +641,9 @@
#endif
+/* helper functions for stream ciphers (disable to prevent building them) */
+#define LTC_HELPER_FUNCTIONS
+
/* Debuggers */
/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */
diff --git a/src/misc/crypt/crypt_helper_functions.c b/src/misc/crypt/crypt_helper_functions.c
new file mode 100644
index 000000000..f4c7714bb
--- /dev/null
+++ b/src/misc/crypt/crypt_helper_functions.c
@@ -0,0 +1,185 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt_private.h"
+
+#ifdef LTC_HELPER_FUNCTIONS
+
+/**
+ @file crypt_helper_functions.c
+
+ A home for the "one call" and other helper functions.
+ Larry Bugbee - June 2018
+*/
+
+/* ======================================================================== */
+
+#ifdef LTC_CHACHA
+
+int chacha_memory(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned long rounds,
+ unsigned char *dataout)
+{
+ chacha_state state;
+ int err;
+
+ if ((err = chacha_setup(&state, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY;
+ if (ivlen == 12) {
+ if ((err = chacha_ivctr32(&state, iv, ivlen, 0)) != CRYPT_OK) goto WIPE_KEY;
+ } else {
+ if ((err = chacha_ivctr64(&state, iv, ivlen, 0)) != CRYPT_OK) goto WIPE_KEY;
+ }
+ err = chacha_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ chacha_done(&state);
+ return err;
+}
+
+#endif /* LTC_CHACHA */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#ifdef LTC_SALSA20
+
+int salsa20_onecall(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned long rounds,
+ unsigned char *dataout)
+{
+ salsa20_state state;
+ int err;
+
+ if ((err = salsa20_setup(&state, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = salsa20_ivctr64(&state, iv, ivlen, 0)) != CRYPT_OK) goto WIPE_KEY;
+ err = salsa20_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ salsa20_done(&state);
+ return err;
+}
+
+#endif /* LTC_SALSA20 */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#ifdef LTC_XSALSA20
+
+int xsalsa20_onecall(const unsigned char *key, unsigned long keylen,
+ const unsigned char *nonce, unsigned long noncelen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned long rounds,
+ unsigned char *dataout)
+{
+ salsa20_state state;
+ int err;
+
+ if ((err = xsalsa20_setup(&state, key, keylen, nonce, noncelen, rounds)) != CRYPT_OK) goto WIPE_KEY;
+ err = salsa20_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ salsa20_done(&state);
+ return err;
+}
+
+#endif /* LTC_XSALSA20 */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+
+#ifdef LTC_SOSEMANUK
+
+int sosemanuk_onecall(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ sosemanuk_state state;
+ int err;
+
+ if ((err = sosemanuk_setup(&state, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = sosemanuk_setiv(&state, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY;
+ err = sosemanuk_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ sosemanuk_done(&state);
+ return err;
+}
+
+#endif /* LTC_SOSEMANUK */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#ifdef LTC_RABBIT
+
+int rabbit_onecall(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ rabbit_state state;
+ int err;
+
+ if ((err = rabbit_setup(&state, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = rabbit_setiv(&state, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY;
+ err = rabbit_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ rabbit_done(&state);
+ return err;
+}
+
+#endif /* LTC_RABBIT */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#ifdef LTC_RC4_STREAM
+
+int rc4_stream_onecall(const unsigned char *key, unsigned long keylen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ rc4_state state;
+ int err;
+
+ if ((err = rc4_stream_setup(&state, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ err = rc4_stream_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ rc4_stream_done(&state);
+ return err;
+}
+
+#endif /* LTC_RC4_STREAM */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+#ifdef LTC_SOBER128_STREAM
+
+int sober128_stream_onecall(const unsigned char *key, unsigned long keylen,
+ const unsigned char *iv, unsigned long ivlen,
+ const unsigned char *datain, unsigned long datalen,
+ unsigned char *dataout)
+{
+ sober128_state state;
+ int err;
+
+ if ((err = sober128_stream_setup(&state, key, keylen)) != CRYPT_OK) goto WIPE_KEY;
+ if ((err = sober128_stream_setiv(&state, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY;
+ err = sober128_stream_crypt(&state, datain, datalen, dataout);
+WIPE_KEY:
+ sober128_stream_done(&state);
+ return err;
+}
+
+#endif /* LTC_SOBER128_STREAM */
+
+/* ======================================================================== */
+
+#endif /* LTC_HELPER_FUNCTIONS */
+
+/* ref: $Format:%D$ */
+/* git commit: $Format:%H$ */
+/* commit time: $Format:%ai$ */
diff --git a/src/misc/crypt/crypt_sizes.c b/src/misc/crypt/crypt_sizes.c
index 5681cc001..7c9121dd4 100644
--- a/src/misc/crypt/crypt_sizes.c
+++ b/src/misc/crypt/crypt_sizes.c
@@ -290,6 +290,31 @@ static const crypt_size _crypt_sizes[] = {
};
+/* ======================================================================== */
+
+#ifdef LTC_CHACHA
+int chacha_state_size(void) { return sizeof(chacha_state); }
+#endif
+#ifdef LTC_SALSA20
+int salsa20_state_size(void) { return sizeof(salsa20_state); }
+#endif
+#ifdef LTC_XSALSA20
+int xsalsa20_state_size(void) { return sizeof(salsa20_state); }
+#endif
+#ifdef LTC_SOSEMANUK
+int sosemanuk_state_size(void) { return sizeof(sosemanuk_state); }
+#endif
+#ifdef LTC_RABBIT
+int rabbit_state_size(void) { return sizeof(rabbit_state); }
+#endif
+#ifdef LTC_RC4_STREAM
+int rc4_state_size(void) { return sizeof(rc4_state); }
+#endif
+#ifdef LTC_SOBER128_STREAM
+int sober128_state_size(void) { return sizeof(sober128_state); }
+#endif
+
+/* ======================================================================== */
/* crypt_get_size()
* sizeout will be the size (bytes) of the named struct or union
* return -1 if named item not found
@@ -306,6 +331,7 @@ int crypt_get_size(const char* namein, unsigned int *sizeout) {
return -1;
}
+/* ======================================================================== */
/* crypt_list_all_sizes()
* if names_list is NULL, names_list_size will be the minimum
* size needed to receive the complete names_list
diff --git a/src/stream/chacha/chacha_crypt.c b/src/stream/chacha/chacha_crypt.c
index d72c84e7e..d67d55868 100644
--- a/src/stream/chacha/chacha_crypt.c
+++ b/src/stream/chacha/chacha_crypt.c
@@ -58,10 +58,10 @@ int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen,
if (inlen == 0) return CRYPT_OK; /* nothing to do */
- LTC_ARGCHK(st != NULL);
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(st->ivlen != 0);
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->status == 2);
if (st->ksleft > 0) {
j = MIN(st->ksleft, inlen);
diff --git a/src/stream/chacha/chacha_ivctr32.c b/src/stream/chacha/chacha_ivctr32.c
index 72856a090..fe22e2b43 100644
--- a/src/stream/chacha/chacha_ivctr32.c
+++ b/src/stream/chacha/chacha_ivctr32.c
@@ -28,15 +28,16 @@ int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivle
{
LTC_ARGCHK(st != NULL);
LTC_ARGCHK(iv != NULL);
- /* 96bit IV + 32bit counter */
- LTC_ARGCHK(ivlen == 12);
+ LTC_ARGCHK(ivlen == 12); /* 96bit IV + 32bit counter */
+ LTC_ARGCHK(st->status == 1 || st->status == 2);
st->input[12] = counter;
LOAD32L(st->input[13], iv + 0);
LOAD32L(st->input[14], iv + 4);
LOAD32L(st->input[15], iv + 8);
st->ksleft = 0;
- st->ivlen = ivlen;
+ st->status = 2;
+ st->ivlen = ivlen;
return CRYPT_OK;
}
diff --git a/src/stream/chacha/chacha_ivctr64.c b/src/stream/chacha/chacha_ivctr64.c
index f7cf721fa..1a27dc13d 100644
--- a/src/stream/chacha/chacha_ivctr64.c
+++ b/src/stream/chacha/chacha_ivctr64.c
@@ -28,15 +28,16 @@ int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivle
{
LTC_ARGCHK(st != NULL);
LTC_ARGCHK(iv != NULL);
- /* 64bit IV + 64bit counter */
- LTC_ARGCHK(ivlen == 8);
+ LTC_ARGCHK(ivlen == 8); /* 64bit IV + 64bit counter */
+ LTC_ARGCHK(st->status == 1 || st->status == 2);
st->input[12] = (ulong32)(counter & 0xFFFFFFFF);
st->input[13] = (ulong32)(counter >> 32);
LOAD32L(st->input[14], iv + 0);
LOAD32L(st->input[15], iv + 4);
st->ksleft = 0;
- st->ivlen = ivlen;
+ st->ivlen = ivlen;
+ st->status = 2;
return CRYPT_OK;
}
diff --git a/src/stream/chacha/chacha_setup.c b/src/stream/chacha/chacha_setup.c
index e997fc951..e6526389a 100644
--- a/src/stream/chacha/chacha_setup.c
+++ b/src/stream/chacha/chacha_setup.c
@@ -19,6 +19,7 @@
static const char * const sigma = "expand 32-byte k";
static const char * const tau = "expand 16-byte k";
+/* ======================================================================== */
/**
Initialize an ChaCha context (only the key)
@param st [out] The destination of the ChaCha state
@@ -56,7 +57,7 @@ int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keyle
LOAD32L(st->input[2], constants + 8);
LOAD32L(st->input[3], constants + 12);
st->rounds = rounds; /* e.g. 20 for chacha20 */
- st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */
+ st->status = 1;
return CRYPT_OK;
}
diff --git a/src/stream/rabbit/rabbit.c b/src/stream/rabbit/rabbit.c
index 4607bc9ed..9f6dfd646 100644
--- a/src/stream/rabbit/rabbit.c
+++ b/src/stream/rabbit/rabbit.c
@@ -19,46 +19,50 @@
* The eSTREAM submission was rather picky about the calling sequence of
* ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed
* calling ECRYPT_process_blocks() multiple times for a multiple of whole
- * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls
+ * 16-byte blocks, but once ECRYPT_process_bytes() was called, no more calls
* were supported correctly. This implementation handles the keystream
* differently and rabbit_crypt() may be called as many times as desired,
* crypting any number of bytes each time.
*
* http://www.ecrypt.eu.org/stream/e2-rabbit.html
+ * https://www.ietf.org/rfc/rfc4503.txt
*
* NB: One of the test vectors distributed by the eSTREAM site in the file
* "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt"
* in that ZIP file, the 3rd line in "out1" should be
* "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4".
*
+ *---------------------------------------------------------------------------
* Here is the original legal notice accompanying the Rabbit submission
* to the EU eSTREAM competition.
- *---------------------------------------------------------------------------
- * Copyright (C) Cryptico A/S. All rights reserved.
*
- * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE.
+ * Copyright (C) Cryptico A/S. All rights reserved.
+ *
+ * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE.
+ *
+ * This software is developed by Cryptico A/S and/or its suppliers.
+ * All title and intellectual property rights in and to the software,
+ * including but not limited to patent rights and copyrights, are owned
+ * by Cryptico A/S and/or its suppliers.
*
- * This software is developed by Cryptico A/S and/or its suppliers.
- * All title and intellectual property rights in and to the software,
- * including but not limited to patent rights and copyrights, are owned
- * by Cryptico A/S and/or its suppliers.
+ * The software may be used solely for non-commercial purposes
+ * without the prior written consent of Cryptico A/S. For further
+ * information on licensing terms and conditions please contact
+ * Cryptico A/S at info@cryptico.com
*
- * The software may be used solely for non-commercial purposes
- * without the prior written consent of Cryptico A/S. For further
- * information on licensing terms and conditions please contact
- * Cryptico A/S at info@cryptico.com
+ * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption"
+ * are either trademarks or registered trademarks of Cryptico A/S.
*
- * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption"
- * are either trademarks or registered trademarks of Cryptico A/S.
+ * Cryptico A/S shall not in any way be liable for any use of this
+ * software. The software is provided "as is" without any express or
+ * implied warranty.
*
- * Cryptico A/S shall not in any way be liable for any use of this
- * software. The software is provided "as is" without any express or
- * implied warranty.
*---------------------------------------------------------------------------
* On October 6, 2008, Rabbit was "released into the public domain and
* may be used freely for any purpose."
+ *
* http://www.ecrypt.eu.org/stream/rabbitpf.html
- * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244
+ *
******************************************************************************/
@@ -145,8 +149,7 @@ static LTC_INLINE void _rabbit_gen_1_block(rabbit_state* st, unsigned char *out)
STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12);
}
-/* -------------------------------------------------------------------------- */
-
+/* ======================================================================== */
/* Key setup */
int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen)
{
@@ -214,6 +217,7 @@ int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keyle
/* ...and prepare block for crypt() */
XMEMSET(&(st->block), 0, sizeof(st->block));
st->unused = 0;
+ st->status = 1;
return CRYPT_OK;
}
@@ -229,6 +233,7 @@ int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen)
LTC_ARGCHK(st != NULL);
LTC_ARGCHK(iv != NULL || ivlen == 0);
LTC_ARGCHK(ivlen <= 8);
+ LTC_ARGCHK(st->status != 0);
/* pad iv in tmpiv */
if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen);
@@ -261,6 +266,7 @@ int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen)
/* reset keystream buffer and unused count */
XMEMSET(&(st->block), 0, sizeof(st->block));
st->unused = 0;
+ st->status = 2;
return CRYPT_OK;
}
@@ -275,9 +281,10 @@ int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen,
if (inlen == 0) return CRYPT_OK; /* nothing to do */
- LTC_ARGCHK(st != NULL);
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->status == 2);
if (st->unused > 0) {
j = MIN(st->unused, inlen);
diff --git a/src/stream/rc4/rc4_stream.c b/src/stream/rc4/rc4_stream.c
index f1c225d01..059f5505e 100644
--- a/src/stream/rc4/rc4_stream.c
+++ b/src/stream/rc4/rc4_stream.c
@@ -42,6 +42,7 @@ int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keyl
}
st->x = 0;
st->y = 0;
+ st->status = 1;
return CRYPT_OK;
}
@@ -61,6 +62,7 @@ int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen
LTC_ARGCHK(st != NULL);
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->status == 1);
x = st->x;
y = st->y;
diff --git a/src/stream/salsa20/salsa20_crypt.c b/src/stream/salsa20/salsa20_crypt.c
index bf1b00167..07764ffc6 100644
--- a/src/stream/salsa20/salsa20_crypt.c
+++ b/src/stream/salsa20/salsa20_crypt.c
@@ -59,10 +59,10 @@ int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inle
if (inlen == 0) return CRYPT_OK; /* nothing to do */
- LTC_ARGCHK(st != NULL);
- LTC_ARGCHK(in != NULL);
- LTC_ARGCHK(out != NULL);
- LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24);
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(in != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->status == 2 || st->status == 3);
if (st->ksleft > 0) {
j = MIN(st->ksleft, inlen);
diff --git a/src/stream/salsa20/salsa20_ivctr64.c b/src/stream/salsa20/salsa20_ivctr64.c
index 9c7ac74f7..241999f5a 100644
--- a/src/stream/salsa20/salsa20_ivctr64.c
+++ b/src/stream/salsa20/salsa20_ivctr64.c
@@ -29,15 +29,15 @@ int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long iv
{
LTC_ARGCHK(st != NULL);
LTC_ARGCHK(iv != NULL);
- /* Salsa20: 64-bit IV (nonce) + 64-bit counter */
LTC_ARGCHK(ivlen == 8);
+ LTC_ARGCHK(st->status == 1 || st->status == 2);
LOAD32L(st->input[6], iv + 0);
LOAD32L(st->input[7], iv + 4);
st->input[8] = (ulong32)(counter & 0xFFFFFFFF);
st->input[9] = (ulong32)(counter >> 32);
st->ksleft = 0;
- st->ivlen = ivlen;
+ st->status = 2;
return CRYPT_OK;
}
diff --git a/src/stream/salsa20/salsa20_setup.c b/src/stream/salsa20/salsa20_setup.c
index 872bd121d..fa4e5a2fa 100644
--- a/src/stream/salsa20/salsa20_setup.c
+++ b/src/stream/salsa20/salsa20_setup.c
@@ -20,6 +20,7 @@
static const char * const sigma = "expand 32-byte k";
static const char * const tau = "expand 16-byte k";
+/* ======================================================================== */
/**
Initialize an Salsa20 context (only the key)
@param st [out] The destination of the Salsa20 state
@@ -28,7 +29,7 @@ static const char * const tau = "expand 16-byte k";
@param rounds Number of rounds (e.g. 20 for Salsa20)
@return CRYPT_OK if successful
*/
-int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds)
+int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, unsigned long rounds)
{
const char *constants;
@@ -37,7 +38,7 @@ int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long key
LTC_ARGCHK(keylen == 32 || keylen == 16);
if (rounds == 0) rounds = 20;
- LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */
+ LTC_ARGCHK(rounds % 2 == 0); /* rounds must be evenly divisible by 2 */
LOAD32L(st->input[1], key + 0);
LOAD32L(st->input[2], key + 4);
@@ -58,7 +59,7 @@ int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long key
LOAD32L(st->input[10], constants + 8);
LOAD32L(st->input[15], constants + 12);
st->rounds = rounds; /* default is 20 for salsa20 */
- st->ivlen = 0; /* will be set later by salsa20_ivctr(32|64) */
+ st->status = 1;
return CRYPT_OK;
}
diff --git a/src/stream/salsa20/xsalsa20_setup.c b/src/stream/salsa20/xsalsa20_setup.c
index 94133a7f3..41bf0a9d1 100644
--- a/src/stream/salsa20/xsalsa20_setup.c
+++ b/src/stream/salsa20/xsalsa20_setup.c
@@ -18,6 +18,8 @@
#ifdef LTC_XSALSA20
+/* ======================================================================== */
+
static const char * const constants = "expand 32-byte k";
#define QUARTERROUND(a,b,c,d) \
@@ -59,7 +61,7 @@ static void _xsalsa20_doubleround(ulong32 *x, int rounds)
*/
int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen,
const unsigned char *nonce, unsigned long noncelen,
- int rounds)
+ unsigned long rounds)
{
const int sti[] = {0, 5, 10, 15, 6, 7, 8, 9}; /* indices used to build subkey fm x */
ulong32 x[64]; /* input to & output fm doubleround */
@@ -72,7 +74,7 @@ int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long ke
LTC_ARGCHK(nonce != NULL);
LTC_ARGCHK(noncelen == 24);
if (rounds == 0) rounds = 20;
- LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */
+ LTC_ARGCHK(rounds % 2 == 0); /* rounds must be evenly divisible by 2 */
/* load the state to "hash" the key */
LOAD32L(x[ 0], constants + 0);
@@ -119,7 +121,7 @@ int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long ke
st->input[ 9] = 0;
st->rounds = rounds;
st->ksleft = 0;
- st->ivlen = 24; /* set switch to say nonce/IV has been loaded */
+ st->status = 3;
#ifdef LTC_CLEAN_STACK
zeromem(x, sizeof(x));
diff --git a/src/stream/sober128/sober128_stream.c b/src/stream/sober128/sober128_stream.c
index 44e0c3278..b5b8188a9 100644
--- a/src/stream/sober128/sober128_stream.c
+++ b/src/stream/sober128/sober128_stream.c
@@ -152,6 +152,7 @@ static void s128_diffuse(sober128_state *c)
DROUND(16);
}
+/* ======================================================================== */
/**
Initialize an Sober128 context (only the key)
@param c [out] The destination of the Sober128 state
@@ -195,6 +196,7 @@ int sober128_stream_setup(sober128_state *c, const unsigned char *key, unsigned
s128_genkonst(c);
s128_savestate(c);
c->nbuf = 0;
+ c->status = 1;
return CRYPT_OK;
}
@@ -213,6 +215,7 @@ int sober128_stream_setiv(sober128_state *c, const unsigned char *iv, unsigned l
LTC_ARGCHK(c != NULL);
LTC_ARGCHK(iv != NULL);
LTC_ARGCHK(ivlen > 0);
+ LTC_ARGCHK(c->status != 0);
/* ok we are adding an IV then... */
s128_reloadstate(c);
@@ -235,6 +238,7 @@ int sober128_stream_setiv(sober128_state *c, const unsigned char *iv, unsigned l
/* now diffuse */
s128_diffuse(c);
c->nbuf = 0;
+ c->status = 2;
return CRYPT_OK;
}
@@ -258,6 +262,7 @@ int sober128_stream_crypt(sober128_state *c, const unsigned char *in, unsigned l
if (inlen == 0) return CRYPT_OK; /* nothing to do */
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(c != NULL);
+ LTC_ARGCHK(c->status == 2);
/* handle any previously buffered bytes */
while (c->nbuf != 0 && inlen != 0) {
diff --git a/src/stream/sosemanuk/sosemanuk.c b/src/stream/sosemanuk/sosemanuk.c
index b0838f847..4caa7ecf7 100644
--- a/src/stream/sosemanuk/sosemanuk.c
+++ b/src/stream/sosemanuk/sosemanuk.c
@@ -10,6 +10,12 @@
/*
* This LTC implementation was adapted from:
* http://www.ecrypt.eu.org/stream/e2-sosemanuk.html
+ *
+ * Sosemanuk specifications require:
+ * 1- a key of at least 128 bits (16 bytes), not exceeding 256 bits (32 bytes).
+ * 2- keys < 32 bytes are terminated with 0x01 followed by NULLs as needed.
+ * 3- an iv of 128 bits (16 bytes).
+ * See http://www.ecrypt.eu.org/stream/p3ciphers/sosemanuk/sosemanuk_p3.pdf
*/
/*
@@ -195,13 +201,13 @@
/*
* Initialize Sosemanuk's state by providing a key. The key is an array of
- * 1 to 32 bytes.
+ * 16 to 32 bytes.
* @param ss The Sosemanuk state
* @param key Key
* @param keylen Length of key in bytes
* @return CRYPT_OK on success
*/
-int sosemanuk_setup(sosemanuk_state *ss, const unsigned char *key, unsigned long keylen)
+int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen)
{
/*
* This key schedule is actually a truncated Serpent key schedule.
@@ -216,10 +222,10 @@ int sosemanuk_setup(sosemanuk_state *ss, const unsigned char *key, unsigned long
r2 = w ## o2; \
r3 = w ## o3; \
S(r0, r1, r2, r3, r4); \
- ss->kc[i ++] = r ## d0; \
- ss->kc[i ++] = r ## d1; \
- ss->kc[i ++] = r ## d2; \
- ss->kc[i ++] = r ## d3; \
+ st->kc[i ++] = r ## d0; \
+ st->kc[i ++] = r ## d1; \
+ st->kc[i ++] = r ## d2; \
+ st->kc[i ++] = r ## d3; \
} while (0)
#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0)
@@ -255,9 +261,9 @@ int sosemanuk_setup(sosemanuk_state *ss, const unsigned char *key, unsigned long
ulong32 w0, w1, w2, w3, w4, w5, w6, w7;
int i = 0;
- LTC_ARGCHK(ss != NULL);
+ LTC_ARGCHK(st != NULL);
LTC_ARGCHK(key != NULL);
- LTC_ARGCHK(keylen > 0 && keylen <= 32);
+ LTC_ARGCHK(keylen >= 16 && keylen <= 32);
/*
* The key is copied into the wbuf[] buffer and padded to 256 bits
@@ -318,32 +324,31 @@ int sosemanuk_setup(sosemanuk_state *ss, const unsigned char *key, unsigned long
#undef WUP0
#undef WUP1
+ st->status = 1; /* 0=uninitialized, 1=finished setup(), 2=finished setiv() */
return CRYPT_OK;
}
/*
- * Initialization continues by setting the IV. The IV length is up to 16 bytes.
- * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple
- * encryptions/decryptions are to be performed with the same key and
+ * Initialization continues by setting the IV. The IV length is 16 bytes. If
+ * multiple encryptions/decryptions are to be performed with the same key and
* sosemanuk_done() has not been called, only sosemanuk_setiv() need be called
* to set the state.
- * @param ss The Sosemanuk state
+ * @param st The Sosemanuk state
* @param iv Initialization vector
- * @param ivlen Length of iv in bytes
* @return CRYPT_OK on success
*/
-int sosemanuk_setiv(sosemanuk_state *ss, const unsigned char *iv, unsigned long ivlen)
+int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen)
{
/*
* The Serpent key addition step.
*/
#define KA(zc, x0, x1, x2, x3) do { \
- x0 ^= ss->kc[(zc)]; \
- x1 ^= ss->kc[(zc) + 1]; \
- x2 ^= ss->kc[(zc) + 2]; \
- x3 ^= ss->kc[(zc) + 3]; \
+ x0 ^= st->kc[(zc)]; \
+ x1 ^= st->kc[(zc) + 1]; \
+ x2 ^= st->kc[(zc) + 2]; \
+ x3 ^= st->kc[(zc) + 3]; \
} while (0)
/*
@@ -373,11 +378,12 @@ int sosemanuk_setiv(sosemanuk_state *ss, const unsigned char *iv, unsigned long
ulong32 r0, r1, r2, r3, r4;
unsigned char ivtmp[16] = {0};
- LTC_ARGCHK(ss != NULL);
- LTC_ARGCHK(ivlen <= 16);
- LTC_ARGCHK(iv != NULL || ivlen == 0);
+ LTC_ARGCHK(st != NULL);
+ LTC_ARGCHK(iv != NULL);
+ LTC_ARGCHK(ivlen == 16);
+ LTC_ARGCHK(st->status != 0);
- if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen);
+ XMEMCPY(ivtmp, iv, ivlen);
/*
* Decode IV into four 32-bit words (little-endian).
@@ -403,10 +409,10 @@ int sosemanuk_setiv(sosemanuk_state *ss, const unsigned char *iv, unsigned long
FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3);
FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0);
FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2);
- ss->s09 = r3;
- ss->s08 = r1;
- ss->s07 = r0;
- ss->s06 = r2;
+ st->s09 = r3;
+ st->s08 = r1;
+ st->s07 = r0;
+ st->s06 = r2;
FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2);
FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3);
@@ -414,10 +420,10 @@ int sosemanuk_setiv(sosemanuk_state *ss, const unsigned char *iv, unsigned long
FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4);
FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3);
FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0);
- ss->r1 = r2;
- ss->s04 = r1;
- ss->r2 = r3;
- ss->s05 = r0;
+ st->r1 = r2;
+ st->s04 = r1;
+ st->r2 = r3;
+ st->s05 = r0;
FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4);
FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2);
@@ -425,17 +431,18 @@ int sosemanuk_setiv(sosemanuk_state *ss, const unsigned char *iv, unsigned long
FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0);
FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1);
FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3);
- ss->s03 = r0;
- ss->s02 = r1;
- ss->s01 = r2;
- ss->s00 = r3;
+ st->s03 = r0;
+ st->s02 = r1;
+ st->s01 = r2;
+ st->s00 = r3;
- ss->ptr = sizeof(ss->buf);
+ st->ptr = sizeof(st->buf);
#undef KA
#undef FSS
#undef FSF
+ st->status = 2; /* 0=uninitialized, 1=finished setup(), 2=finished setiv() */
return CRYPT_OK;
}
@@ -584,7 +591,7 @@ static const ulong32 mul_ia[] = {
* Compute the next block of bits of output stream. This is equivalent
* to one full rotation of the shift register.
*/
-static LTC_INLINE void _sosemanuk_internal(sosemanuk_state *ss)
+static LTC_INLINE void _sosemanuk_internal(sosemanuk_state *st)
{
/*
* MUL_A(x) computes alpha * x (in F_{2^32}).
@@ -655,24 +662,24 @@ static LTC_INLINE void _sosemanuk_internal(sosemanuk_state *ss)
*/
#define SRD(S, x0, x1, x2, x3, ooff) do { \
S(u0, u1, u2, u3, u4); \
- STORE32L(u ## x0 ^ v0, ss->buf + ooff); \
- STORE32L(u ## x1 ^ v1, ss->buf + ooff + 4); \
- STORE32L(u ## x2 ^ v2, ss->buf + ooff + 8); \
- STORE32L(u ## x3 ^ v3, ss->buf + ooff + 12); \
+ STORE32L(u ## x0 ^ v0, st->buf + ooff); \
+ STORE32L(u ## x1 ^ v1, st->buf + ooff + 4); \
+ STORE32L(u ## x2 ^ v2, st->buf + ooff + 8); \
+ STORE32L(u ## x3 ^ v3, st->buf + ooff + 12); \
} while (0)
- ulong32 s00 = ss->s00;
- ulong32 s01 = ss->s01;
- ulong32 s02 = ss->s02;
- ulong32 s03 = ss->s03;
- ulong32 s04 = ss->s04;
- ulong32 s05 = ss->s05;
- ulong32 s06 = ss->s06;
- ulong32 s07 = ss->s07;
- ulong32 s08 = ss->s08;
- ulong32 s09 = ss->s09;
- ulong32 r1 = ss->r1;
- ulong32 r2 = ss->r2;
+ ulong32 s00 = st->s00;
+ ulong32 s01 = st->s01;
+ ulong32 s02 = st->s02;
+ ulong32 s03 = st->s03;
+ ulong32 s04 = st->s04;
+ ulong32 s05 = st->s05;
+ ulong32 s06 = st->s06;
+ ulong32 s07 = st->s07;
+ ulong32 s08 = st->s08;
+ ulong32 s09 = st->s09;
+ ulong32 r1 = st->r1;
+ ulong32 r2 = st->r2;
ulong32 u0, u1, u2, u3, u4;
ulong32 v0, v1, v2, v3;
@@ -702,18 +709,18 @@ static LTC_INLINE void _sosemanuk_internal(sosemanuk_state *ss)
STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v3, u3);
SRD(S2, 2, 3, 1, 4, 64);
- ss->s00 = s00;
- ss->s01 = s01;
- ss->s02 = s02;
- ss->s03 = s03;
- ss->s04 = s04;
- ss->s05 = s05;
- ss->s06 = s06;
- ss->s07 = s07;
- ss->s08 = s08;
- ss->s09 = s09;
- ss->r1 = r1;
- ss->r2 = r2;
+ st->s00 = s00;
+ st->s01 = s01;
+ st->s02 = s02;
+ st->s03 = s03;
+ st->s04 = s04;
+ st->s05 = s05;
+ st->s06 = s06;
+ st->s07 = s07;
+ st->s08 = s08;
+ st->s09 = s09;
+ st->r1 = r1;
+ st->r2 = r2;
}
/*
@@ -735,40 +742,41 @@ static LTC_INLINE void _xorbuf(const unsigned char *in1, const unsigned char *in
* buffer, combined by XOR with the stream, and the result is written
* in the "out" buffer. "in" and "out" must be either equal, or
* reference distinct buffers (no partial overlap is allowed).
- * @param ss The Sosemanuk state
+ * @param st The Sosemanuk state
* @param in Data in
* @param inlen Length of data in bytes
* @param out Data out
* @return CRYPT_OK on success
*/
-int sosemanuk_crypt(sosemanuk_state *ss,
+int sosemanuk_crypt(sosemanuk_state *st,
const unsigned char *in, unsigned long inlen, unsigned char *out)
{
- LTC_ARGCHK(ss != NULL);
+ LTC_ARGCHK(st != NULL);
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(st->status == 2);
- if (ss->ptr < (sizeof(ss->buf))) {
- unsigned long rlen = (sizeof(ss->buf)) - ss->ptr;
+ if (st->ptr < (sizeof(st->buf))) {
+ unsigned long rlen = (sizeof(st->buf)) - st->ptr;
if (rlen > inlen)
rlen = inlen;
- _xorbuf(ss->buf + ss->ptr, in, out, rlen);
+ _xorbuf(st->buf + st->ptr, in, out, rlen);
in += rlen;
out += rlen;
inlen -= rlen;
- ss->ptr += rlen;
+ st->ptr += rlen;
}
while (inlen > 0) {
- _sosemanuk_internal(ss);
- if (inlen >= sizeof(ss->buf)) {
- _xorbuf(ss->buf, in, out, sizeof(ss->buf));
- in += sizeof(ss->buf);
- out += sizeof(ss->buf);
- inlen -= sizeof(ss->buf);
+ _sosemanuk_internal(st);
+ if (inlen >= sizeof(st->buf)) {
+ _xorbuf(st->buf, in, out, sizeof(st->buf));
+ in += sizeof(st->buf);
+ out += sizeof(st->buf);
+ inlen -= sizeof(st->buf);
} else {
- _xorbuf(ss->buf, in, out, inlen);
- ss->ptr = inlen;
+ _xorbuf(st->buf, in, out, inlen);
+ st->ptr = inlen;
inlen = 0;
}
}
@@ -780,29 +788,29 @@ int sosemanuk_crypt(sosemanuk_state *ss,
/*
* Cipher operation, as a PRNG: the provided output buffer is filled with
* pseudo-random bytes as output from the stream cipher.
- * @param ss The Sosemanuk state
+ * @param st The Sosemanuk state
* @param out Data out
* @param outlen Length of output in bytes
* @return CRYPT_OK on success
*/
-int sosemanuk_keystream(sosemanuk_state *ss, unsigned char *out, unsigned long outlen)
+int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen)
{
if (outlen == 0) return CRYPT_OK; /* nothing to do */
LTC_ARGCHK(out != NULL);
XMEMSET(out, 0, outlen);
- return sosemanuk_crypt(ss, out, outlen, out);
+ return sosemanuk_crypt(st, out, outlen, out);
}
/*
* Terminate and clear Sosemanuk key context
- * @param ss The Sosemanuk state
+ * @param st The Sosemanuk state
* @return CRYPT_OK on success
*/
-int sosemanuk_done(sosemanuk_state *ss)
+int sosemanuk_done(sosemanuk_state *st)
{
- LTC_ARGCHK(ss != NULL);
- XMEMSET(ss, 0, sizeof(sosemanuk_state));
+ LTC_ARGCHK(st != NULL);
+ XMEMSET(st, 0, sizeof(sosemanuk_state));
return CRYPT_OK;
}
diff --git a/src/stream/sosemanuk/sosemanuk_test.c b/src/stream/sosemanuk/sosemanuk_test.c
index e5514df10..8eb68b400 100644
--- a/src/stream/sosemanuk/sosemanuk_test.c
+++ b/src/stream/sosemanuk/sosemanuk_test.c
@@ -38,7 +38,7 @@ int sosemanuk_test(void)
if ((err = sosemanuk_crypt(&ss, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err;
if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV1", 1)) return CRYPT_FAIL_TESTVECTOR;
- /* crypt in one go - using sosemanuk_ivctr64() */
+ /* crypt in one go - using sosemanuk_setiv() */
if ((err = sosemanuk_setup(&ss, k, sizeof(k))) != CRYPT_OK) return err;
if ((err = sosemanuk_setiv(&ss, n, sizeof(n))) != CRYPT_OK) return err;
if ((err = sosemanuk_crypt(&ss, (unsigned char*)pt, len, out)) != CRYPT_OK) return err;