Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 60 additions & 24 deletions doc/crypt.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1301,49 +1301,85 @@ \chapter{Stream Ciphers}
err = chacha_done(&st);
\end{verbatim}

\mysection{Salsa20}
\mysection{Salsa20 and XSalsa20}

\textit{Salsa20} was Daniel Bernstein's submission to the EU eSTREAM
competition where a reduced-round version, \textit{Salsa20/12}, was named
one of the winners. A third version, \textit{Salsa20/8}, was also evaluated.
\vspace{1mm}

While 20 rounds is the conservative default number of rounds, eSTREAM deemed
12 rounds to be a decent balance between strength and better performance.
The 8-round version, while still secure as of this writing, is faster but
does not enjoy the same margin of safety. Regardless of the number of rounds,
\textit{Salsa20} accepts either a 128- or a 256-bit key, a 64-bit IV, and a
64-bit counter.
\vspace{1mm}

\textit{XSalsa20} is yet another variant of \textit{Salsa20} designed to accept
only a 256-bit key and a longer 192-bit nonce, initialization being the only
difference between \textit{XSalsa20} and \textit{Salsa20}. Even the
\textit{salsa20\_state} is the same. Thereafter, salsa20\_crypt(),
salsa20\_keystream(), and salsa20\_done() are used unaltered.
salsa20\_ivctr64() is NOT used with xsalsa20\_setup().
\vspace{1mm}

To initialize \textit{Salsa20} for 8, 12, or 20 rounds with a 128- or a
256-bit key (16 or 32 bytes), a 64-bit IV (8 bytes), and counter (typically
zero), use:

\textit{Salsa20} is the forerunner of the ChaCha stream cipher. The ChaCha cipher is
Salsa20 with a few minor tweaks to further improve its strength, and in so doing, increase its
speed performance by about 5 percent. Unless you need Salsa20 for some reason, you should
probably choose ChaCha instead.

In April 2008 \textit{Salsa20/12} was named one of the winners in the EU eSTREAM competition.
Salsa20 was originally submitted by Daniel Bernstein with 20 rounds of strength but the
12-round reduced-round version was deemed to have sufficient strength and declared a winner.
Even the 8-round reduced-round version, Salsa20/8, has withstood attack.

For more information about Salsa20 see \url{https://en.wikipedia.org/wiki/Salsa20}.

Supported key size: 16 or 32 bytes (128 or 256 bits).

You can initialize Salsa20 with 64bit \textit{nonce} + 64bit \textit{counter}:
\begin{verbatim}
salsa20_state st;
ulong64 counter = 0;
err = salsa20_setup(&st, key, key_len, rounds);
err = salsa20_ivctr64(&st, nonce, 8, initial_64bit_ctr);
err = salsa20_ivctr64(&st, nonce, 8, counter);
\end{verbatim}

The \textit{salsa20\_setup} takes the number of rounds as a parameter -- choose 20 (the default)
if you are not sure. As always never ever use the same key + nonce pair more than once.
To initialize \textit{XSalsa20} for the recommended 20 rounds with a 256-bit
key (32 bytes) and a 192-bit nonce (24 bytes), use:

For the actual encryption or decryption you have to call:
\begin{verbatim}
salsa20_state st;
err = xsalsa20_setup(&st, key, key_len, nonce, nonce_len, rounds);
\end{verbatim}

Both \textit{Salsa20} and \textit{XSalsa20} use the following functions. To
encrypt or decrypt call:
\begin{verbatim}
err = salsa20_crypt(&st, in_buffer, in_len, out_buffer);
\end{verbatim}

If you just want a random stream of bytes initialize the cipher with a truly random \textit{key}
(32 bytes), a truly random \textit{nonce} (8 bytes) and zero initial counter. After that you can
get a stream of pseudo--random bytes via:
For a random keystream initialize the cipher with a truly random \textit{key}
and random \textit{nonce} after which you can get a stream of
pseudo--random bytes via:
\begin{verbatim}
err = salsa20_keystream(&st, out_buffer, out_len);
\end{verbatim}

When finished you should wipe the state:
Finally, when finished you should wipe the state.
\begin{verbatim}
err = salsa20_done(&st);
\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}

If you define \textit{LTC_XSALSA20} to include \textit{XSalsa20} in a minimal
\textit{libtomcrypt} library build, you must also define \textit{LTC_SALSA20}.
\vspace{1mm}

As always, never ever use the same key + nonce/IV pair more than once.
\vspace{1mm}

For more information about Salsa20 see
\url{https://en.wikipedia.org/wiki/Salsa20}.
\vspace{1mm}

For more information about XSalsa20 see
\url{https://cr.yp.to/snuffle/xsalsa-20081128.pdf}.
\vspace{1mm}

\mysection{Sosemanuk}

\textit{Sosemanuk}, along with Salsa20, HC-128, and Rabbit, was named one of the winners in
Expand Down
8 changes: 8 additions & 0 deletions libtomcrypt_VS2008.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -2634,6 +2634,14 @@
RelativePath="src\stream\salsa20\salsa20_test.c"
>
</File>
<File
RelativePath="src\stream\salsa20\xsalsa20_setup.c"
>
</File>
<File
RelativePath="src\stream\salsa20\xsalsa20_test.c"
>
</File>
</Filter>
<Filter
Name="sober128"
Expand Down
1 change: 1 addition & 0 deletions makefile.mingw
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ src/stream/rabbit/rabbit.o src/stream/rc4/rc4_stream.o src/stream/rc4/rc4_test.o
src/stream/salsa20/salsa20_crypt.o src/stream/salsa20/salsa20_done.o \
src/stream/salsa20/salsa20_ivctr64.o src/stream/salsa20/salsa20_keystream.o \
src/stream/salsa20/salsa20_setup.o src/stream/salsa20/salsa20_test.o \
src/stream/salsa20/xsalsa20_setup.o src/stream/salsa20/xsalsa20_test.o \
src/stream/sober128/sober128_stream.o src/stream/sober128/sober128_test.o \
src/stream/sosemanuk/sosemanuk.o src/stream/sosemanuk/sosemanuk_test.o

Expand Down
1 change: 1 addition & 0 deletions makefile.msvc
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ src/stream/rabbit/rabbit.obj src/stream/rc4/rc4_stream.obj src/stream/rc4/rc4_te
src/stream/salsa20/salsa20_crypt.obj src/stream/salsa20/salsa20_done.obj \
src/stream/salsa20/salsa20_ivctr64.obj src/stream/salsa20/salsa20_keystream.obj \
src/stream/salsa20/salsa20_setup.obj src/stream/salsa20/salsa20_test.obj \
src/stream/salsa20/xsalsa20_setup.obj src/stream/salsa20/xsalsa20_test.obj \
src/stream/sober128/sober128_stream.obj src/stream/sober128/sober128_test.obj \
src/stream/sosemanuk/sosemanuk.obj src/stream/sosemanuk/sosemanuk_test.obj

Expand Down
1 change: 1 addition & 0 deletions makefile.unix
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ src/stream/rabbit/rabbit.o src/stream/rc4/rc4_stream.o src/stream/rc4/rc4_test.o
src/stream/salsa20/salsa20_crypt.o src/stream/salsa20/salsa20_done.o \
src/stream/salsa20/salsa20_ivctr64.o src/stream/salsa20/salsa20_keystream.o \
src/stream/salsa20/salsa20_setup.o src/stream/salsa20/salsa20_test.o \
src/stream/salsa20/xsalsa20_setup.o src/stream/salsa20/xsalsa20_test.o \
src/stream/sober128/sober128_stream.o src/stream/sober128/sober128_test.o \
src/stream/sosemanuk/sosemanuk.o src/stream/sosemanuk/sosemanuk_test.o

Expand Down
1 change: 1 addition & 0 deletions makefile_include.mk
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ src/stream/rabbit/rabbit.o src/stream/rc4/rc4_stream.o src/stream/rc4/rc4_test.o
src/stream/salsa20/salsa20_crypt.o src/stream/salsa20/salsa20_done.o \
src/stream/salsa20/salsa20_ivctr64.o src/stream/salsa20/salsa20_keystream.o \
src/stream/salsa20/salsa20_setup.o src/stream/salsa20/salsa20_test.o \
src/stream/salsa20/xsalsa20_setup.o src/stream/salsa20/xsalsa20_test.o \
src/stream/sober128/sober128_stream.o src/stream/sober128/sober128_test.o \
src/stream/sosemanuk/sosemanuk.o src/stream/sosemanuk/sosemanuk_test.o

Expand Down
9 changes: 9 additions & 0 deletions src/headers/tomcrypt_cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,15 @@ int salsa20_test(void);

#endif /* LTC_SALSA20 */

#ifdef LTC_XSALSA20

int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we use xsalsa20_state here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my comment below

const unsigned char *nonce, unsigned long noncelen,
int rounds);
int xsalsa20_test(void);

#endif /* LTC_XSALSA20 */

#ifdef LTC_SOSEMANUK

typedef struct {
Expand Down
5 changes: 5 additions & 0 deletions src/headers/tomcrypt_custom.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@
/* stream ciphers */
#define LTC_CHACHA
#define LTC_SALSA20
#define LTC_XSALSA20
#define LTC_SOSEMANUK
#define LTC_RABBIT
#define LTC_RC4_STREAM
Expand Down Expand Up @@ -589,6 +590,10 @@
#error LTC_CHACHA20_PRNG requires LTC_CHACHA
#endif

#if defined(LTC_XSALSA20) && !defined(LTC_SALSA20)
#error LTC_XSALSA20 requires LTC_SALSA20
#endif

#if defined(LTC_RC4) && !defined(LTC_RC4_STREAM)
#error LTC_RC4 requires LTC_RC4_STREAM
#endif
Expand Down
3 changes: 3 additions & 0 deletions src/misc/crypt/crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ const char *crypt_build_settings =
#if defined(LTC_SALSA20)
" Salsa20\n"
#endif
#if defined(LTC_XSALSA20)
" XSalsa20\n"
#endif
#if defined(LTC_SOSEMANUK)
" Sosemanuk\n"
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/stream/salsa20/salsa20_crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inle
LTC_ARGCHK(st != NULL);
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(st->ivlen == 8);
LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24);

if (st->ksleft > 0) {
j = MIN(st->ksleft, inlen);
Expand Down
137 changes: 137 additions & 0 deletions src/stream/salsa20/xsalsa20_setup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/* 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.
*/

/* The implementation is based on:
* "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf
* "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf
* and salsa20-ref.c version 20051118
* Public domain from D. J. Bernstein
*/

#include "tomcrypt.h"

#ifdef LTC_XSALSA20

static const char * const constants = "expand 32-byte k";

#define QUARTERROUND(a,b,c,d) \
x[b] ^= (ROL((x[a] + x[d]), 7)); \
x[c] ^= (ROL((x[b] + x[a]), 9)); \
x[d] ^= (ROL((x[c] + x[b]), 13)); \
x[a] ^= (ROL((x[d] + x[c]), 18));

/* use modified salsa20 doubleround (no final addition as in salsa20) */
static void _xsalsa20_doubleround(ulong32 *x, int rounds)
{
int i = 0;

for (i = rounds; i > 0; i -= 2) {
/* columnround */
QUARTERROUND( 0, 4, 8,12)
QUARTERROUND( 5, 9,13, 1)
QUARTERROUND(10,14, 2, 6)
QUARTERROUND(15, 3, 7,11)
/* rowround */
QUARTERROUND( 0, 1, 2, 3)
QUARTERROUND( 5, 6, 7, 4)
QUARTERROUND(10,11, 8, 9)
QUARTERROUND(15,12,13,14)
}
}

#undef QUARTERROUND

/**
Initialize an XSalsa20 context
@param st [out] The destination of the XSalsa20 state
@param key The secret key
@param keylen The length of the secret key, must be 32 (octets)
@param nonce The nonce
@param noncelen The length of the nonce, must be 24 (octets)
@param rounds Number of rounds (must be evenly divisible by 2, default is 20)
@return CRYPT_OK if successful
*/
int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen,
const unsigned char *nonce, unsigned long noncelen,
int 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 */
unsigned char subkey[32];
int i = 0;

LTC_ARGCHK(st != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(keylen == 32);
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 */

/* load the state to "hash" the key */
LOAD32L(x[ 0], constants + 0);
LOAD32L(x[ 5], constants + 4);
LOAD32L(x[10], constants + 8);
LOAD32L(x[15], constants + 12);
LOAD32L(x[ 1], key + 0);
LOAD32L(x[ 2], key + 4);
LOAD32L(x[ 3], key + 8);
LOAD32L(x[ 4], key + 12);
LOAD32L(x[11], key + 16);
LOAD32L(x[12], key + 20);
LOAD32L(x[13], key + 24);
LOAD32L(x[14], key + 28);
LOAD32L(x[ 6], nonce + 0);
LOAD32L(x[ 7], nonce + 4);
LOAD32L(x[ 8], nonce + 8);
LOAD32L(x[ 9], nonce + 12);

/* use modified salsa20 doubleround (no final addition) */
_xsalsa20_doubleround(x, rounds);

/* extract the subkey */
for (i = 0; i < 8; ++i) {
STORE32L(x[sti[i]], subkey + 4 * i);
}

/* load the final initial state */
LOAD32L(st->input[ 0], constants + 0);
LOAD32L(st->input[ 5], constants + 4);
LOAD32L(st->input[10], constants + 8);
LOAD32L(st->input[15], constants + 12);
LOAD32L(st->input[ 1], subkey + 0);
LOAD32L(st->input[ 2], subkey + 4);
LOAD32L(st->input[ 3], subkey + 8);
LOAD32L(st->input[ 4], subkey + 12);
LOAD32L(st->input[11], subkey + 16);
LOAD32L(st->input[12], subkey + 20);
LOAD32L(st->input[13], subkey + 24);
LOAD32L(st->input[14], subkey + 28);
LOAD32L(st->input[ 6], &(nonce[16]) + 0);
LOAD32L(st->input[ 7], &(nonce[16]) + 4);
st->input[ 8] = 0;
st->input[ 9] = 0;
st->rounds = rounds;
st->ksleft = 0;
st->ivlen = 24; /* set switch to say nonce/IV has been loaded */

#ifdef LTC_CLEAN_STACK
zeromem(x, sizeof(x));
zeromem(subkey, sizeof(subkey));
#endif

return CRYPT_OK;
}


#endif

/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */
Loading