Browse Source

add Sosemanuk

Larry Bugbee 7 years ago
parent
commit
108ddf5b50

+ 48 - 1
doc/crypt.tex

@@ -1339,11 +1339,58 @@ get a stream of pseudo--random bytes via:
 err = salsa20_keystream(&st, out_buffer, out_len);
 \end{verbatim}
 
-At the end you have to terminate the state:
+When finished you should wipe the state:
 \begin{verbatim}
 err = salsa20_done(&st);
 \end{verbatim}
 
+\mysection{Sosemanuk}
+
+\textit{Sosemanuk}, along with Salsa20, HC-128, and Rabbit, was named one of the winners in
+the EU eSTREAM competition.  Sosemanuk is a stream cipher that borrows heavily from SNOW,
+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.
+
+See \url{http://www.ecrypt.eu.org/stream/p3ciphers/sosemanuk/sosemanuk_p3.pdf} for more
+information.
+
+You begin initializing Sosemanuk by creating a key context using a 128- to 256-bit key.
+\begin{verbatim}
+sosemanuk_key_context kc;
+err = sosemanuk_schedule(&kc, key, key_len);
+\end{verbatim}
+
+Use the key context to create a run context and finish initialization with a 128-bit iv.
+\begin{verbatim}
+sosemanuk_run_context rc;
+err = sosemanuk_init(&rc, &kc, iv, iv_len);
+\end{verbatim}
+
+For the actual encryption or decryption, call:
+\begin{verbatim}
+err = sosemanuk_crypt(&rc, 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{iv} (16 bytes). After that you can
+get a stream of pseudo--random bytes via:
+\begin{verbatim}
+err = sosemanuk_keystream(&rc, out_buffer, out_len);
+\end{verbatim}
+
+When finished you should wipe the key and run contexts:
+\begin{verbatim}
+err = sosemanuk_done(&kc, &rc);
+\end{verbatim}
+
+To do multiple encryptions and decryptions with the same key, you can reset the algorithm
+using sosemanuk_init() if you saved the key context and did not wipe it with sosemanuk_done().
+You will want to use a different iv but you do not need to re-run sosemanuk_schedule() again.
+
 \mysection{RC4}
 
 For more information about RC4 see \url{https://en.wikipedia.org/wiki/RC4}.

+ 6 - 4
src/headers/tomcrypt_cfg.h

@@ -51,12 +51,14 @@ LTC_EXPORT int   LTC_CALL XSTRCMP(const char *s1, const char *s2);
 #endif
 
 /* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */
-#if defined(__HP_cc) || defined(__xlc__)
-   #define LTC_INLINE
-#elif defined(_MSC_VER)
+#if defined(__GNUC__) || defined(__xlc__)
+   #define LTC_INLINE __inline__
+#elif defined(_MSC_VER) || defined(__HP_cc)
    #define LTC_INLINE __inline
-#else
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    #define LTC_INLINE inline
+#else
+   #define LTC_INLINE
 #endif
 
 /* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */

+ 28 - 0
src/headers/tomcrypt_cipher.h

@@ -1031,6 +1031,34 @@ int salsa20_test(void);
 
 #endif /* LTC_SALSA20 */
 
+
+
+#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;
+} sosemanuk_state;
+
+int sosemanuk_setup(sosemanuk_state *ss, unsigned char *key, unsigned long keylen);
+int sosemanuk_setiv(sosemanuk_state *ss, 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_test(void);
+
+#endif /* LTC_SOSEMANUK */
+
+
+
 #ifdef LTC_RC4_STREAM
 
 typedef struct {

+ 1 - 0
src/headers/tomcrypt_custom.h

@@ -208,6 +208,7 @@
 /* stream ciphers */
 #define LTC_CHACHA
 #define LTC_SALSA20
+#define LTC_SOSEMANUK
 #define LTC_RC4_STREAM
 #define LTC_SOBER128_STREAM
 

+ 3 - 0
src/misc/crypt/crypt.c

@@ -135,6 +135,9 @@ const char *crypt_build_settings =
 #if defined(LTC_SALSA20)
    "   Salsa20\n"
 #endif
+#if defined(LTC_SOSEMANUK)
+   "   Sosemanuk\n"
+#endif
 #if defined(LTC_RC4_STREAM)
    "   RC4\n"
 #endif

+ 3 - 0
src/misc/crypt/crypt_sizes.c

@@ -180,6 +180,9 @@ static const crypt_size _crypt_sizes[] = {
 #ifdef LTC_SALSA20
     _SZ_STRINGIFY_T(salsa20_state),
 #endif
+#ifdef LTC_SOSEMANUK
+    _SZ_STRINGIFY_T(sosemanuk_state),
+#endif
 #ifdef LTC_RC4_STREAM
     _SZ_STRINGIFY_T(rc4_state),
 #endif

+ 819 - 0
src/stream/sosemanuk/sosemanuk.c

@@ -0,0 +1,819 @@
+/* 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.
+ */
+
+/*
+ * This LTC implementation was adapted from:
+ *    http://www.ecrypt.eu.org/stream/e2-sosemanuk.html
+ */
+
+/*
+ * SOSEMANUK reference implementation.
+ *
+ * This code is supposed to run on any conforming C implementation (C90
+ * or later).
+ *
+ * (c) 2005 X-CRYPT project. This software is provided 'as-is', without
+ * any express or implied warranty. In no event will the authors be held
+ * liable for any damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to no restriction.
+ *
+ * Technical remarks and questions can be addressed to
+ * <[email protected]>
+ */
+
+#include "tomcrypt.h"
+
+#ifdef LTC_SOSEMANUK
+
+/* ======================================================================== */
+
+/*
+ * We want (and sometimes need) to perform explicit truncations to 32 bits.
+ */
+#define T32(x)   ((x) & (ulong32)0xFFFFFFFF)
+
+/*
+ * Some of our functions will be tagged as "inline" to help the compiler
+ * optimize things. We use "inline" only if the compiler is advanced
+ * enough to understand it; C99 compilers, and pre-C99 versions of gcc,
+ * understand enough "inline" for our purposes.
+ */
+
+/* ======================================================================== */
+
+/*
+ * Serpent S-boxes, implemented in bitslice mode. These circuits have
+ * been published by Dag Arne Osvik ("Speeding up Serpent", published in
+ * the 3rd AES Candidate Conference) and work on five 32-bit registers:
+ * the four inputs, and a fifth scratch register. There are meant to be
+ * quite fast on Pentium-class processors. These are not the fastest
+ * published, but they are "fast enough" and they are unencumbered as
+ * far as intellectual property is concerned (note: these are rewritten
+ * from the article itself, and hence are not covered by the GPL on
+ * Dag's code, which was not used here).
+ *
+ * The output bits are permuted. Here is the correspondance:
+ *   S0:  1420
+ *   S1:  2031
+ *   S2:  2314
+ *   S3:  1234
+ *   S4:  1403
+ *   S5:  1302
+ *   S6:  0142
+ *   S7:  4310
+ * (for instance, the output of S0 is in "r1, r4, r2, r0").
+ */
+
+#define S0(r0, r1, r2, r3, r4)   do { \
+        r3 ^= r0;  r4  = r1; \
+        r1 &= r3;  r4 ^= r2; \
+        r1 ^= r0;  r0 |= r3; \
+        r0 ^= r4;  r4 ^= r3; \
+        r3 ^= r2;  r2 |= r1; \
+        r2 ^= r4;  r4 = ~r4; \
+        r4 |= r1;  r1 ^= r3; \
+        r1 ^= r4;  r3 |= r0; \
+        r1 ^= r3;  r4 ^= r3; \
+    } while (0)
+
+#define S1(r0, r1, r2, r3, r4)   do { \
+        r0 = ~r0;  r2 = ~r2; \
+        r4  = r0;  r0 &= r1; \
+        r2 ^= r0;  r0 |= r3; \
+        r3 ^= r2;  r1 ^= r0; \
+        r0 ^= r4;  r4 |= r1; \
+        r1 ^= r3;  r2 |= r0; \
+        r2 &= r4;  r0 ^= r1; \
+        r1 &= r2; \
+        r1 ^= r0;  r0 &= r2; \
+        r0 ^= r4; \
+    } while (0)
+
+#define S2(r0, r1, r2, r3, r4)   do { \
+        r4  = r0;  r0 &= r2; \
+        r0 ^= r3;  r2 ^= r1; \
+        r2 ^= r0;  r3 |= r4; \
+        r3 ^= r1;  r4 ^= r2; \
+        r1  = r3;  r3 |= r4; \
+        r3 ^= r0;  r0 &= r1; \
+        r4 ^= r0;  r1 ^= r3; \
+        r1 ^= r4;  r4 = ~r4; \
+    } while (0)
+
+#define S3(r0, r1, r2, r3, r4)   do { \
+        r4  = r0;  r0 |= r3; \
+        r3 ^= r1;  r1 &= r4; \
+        r4 ^= r2;  r2 ^= r3; \
+        r3 &= r0;  r4 |= r1; \
+        r3 ^= r4;  r0 ^= r1; \
+        r4 &= r0;  r1 ^= r3; \
+        r4 ^= r2;  r1 |= r0; \
+        r1 ^= r2;  r0 ^= r3; \
+        r2  = r1;  r1 |= r3; \
+        r1 ^= r0; \
+    } while (0)
+
+#define S4(r0, r1, r2, r3, r4)   do { \
+        r1 ^= r3;  r3 = ~r3; \
+        r2 ^= r3;  r3 ^= r0; \
+        r4  = r1;  r1 &= r3; \
+        r1 ^= r2;  r4 ^= r3; \
+        r0 ^= r4;  r2 &= r4; \
+        r2 ^= r0;  r0 &= r1; \
+        r3 ^= r0;  r4 |= r1; \
+        r4 ^= r0;  r0 |= r3; \
+        r0 ^= r2;  r2 &= r3; \
+        r0 = ~r0;  r4 ^= r2; \
+    } while (0)
+
+#define S5(r0, r1, r2, r3, r4)   do { \
+        r0 ^= r1;  r1 ^= r3; \
+        r3 = ~r3;  r4  = r1; \
+        r1 &= r0;  r2 ^= r3; \
+        r1 ^= r2;  r2 |= r4; \
+        r4 ^= r3;  r3 &= r1; \
+        r3 ^= r0;  r4 ^= r1; \
+        r4 ^= r2;  r2 ^= r0; \
+        r0 &= r3;  r2 = ~r2; \
+        r0 ^= r4;  r4 |= r3; \
+        r2 ^= r4; \
+    } while (0)
+
+#define S6(r0, r1, r2, r3, r4)   do { \
+        r2 = ~r2;  r4  = r3; \
+        r3 &= r0;  r0 ^= r4; \
+        r3 ^= r2;  r2 |= r4; \
+        r1 ^= r3;  r2 ^= r0; \
+        r0 |= r1;  r2 ^= r1; \
+        r4 ^= r0;  r0 |= r3; \
+        r0 ^= r2;  r4 ^= r3; \
+        r4 ^= r0;  r3 = ~r3; \
+        r2 &= r4; \
+        r2 ^= r3; \
+    } while (0)
+
+#define S7(r0, r1, r2, r3, r4)   do { \
+        r4  = r1;  r1 |= r2; \
+        r1 ^= r3;  r4 ^= r2; \
+        r2 ^= r1;  r3 |= r4; \
+        r3 &= r0;  r4 ^= r2; \
+        r3 ^= r1;  r1 |= r4; \
+        r1 ^= r0;  r0 |= r4; \
+        r0 ^= r2;  r1 ^= r4; \
+        r2 ^= r1;  r1 &= r0; \
+        r1 ^= r4;  r2 = ~r2; \
+        r2 |= r0; \
+        r4 ^= r2; \
+    } while (0)
+
+/*
+ * The Serpent linear transform.
+ */
+#define SERPENT_LT(x0, x1, x2, x3)  do { \
+        x0 = ROLc(x0, 13); \
+        x2 = ROLc(x2, 3); \
+        x1 = x1 ^ x0 ^ x2; \
+        x3 = x3 ^ x2 ^ T32(x0 << 3); \
+        x1 = ROLc(x1, 1); \
+        x3 = ROLc(x3, 7); \
+        x0 = x0 ^ x1 ^ x3; \
+        x2 = x2 ^ x3 ^ T32(x1 << 7); \
+        x0 = ROLc(x0, 5); \
+        x2 = ROLc(x2, 22); \
+    } while (0)
+
+/* ======================================================================== */
+
+/*
+ * Key schedule: initialize the key context structure with the provided
+ * secret key. The secret key is an array of 1 to 32 bytes.
+ * @param ss       The Sosemanuk state
+ * @param key      Key
+ * @param keylen   Length of key
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_setup(sosemanuk_state *ss, unsigned char *key, unsigned long keylen)
+{
+    /*
+     * This key schedule is actually a truncated Serpent key schedule.
+     * The key-derived words (w_i) are computed within the eight
+     * local variables w0 to w7, which are reused again and again.
+     */
+
+#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3)   do { \
+        ulong32 r0, r1, r2, r3, r4; \
+        r0 = w ## o0; \
+        r1 = w ## o1; \
+        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; \
+    } while (0)
+
+#define SKS0    SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0)
+#define SKS1    SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1)
+#define SKS2    SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4)
+#define SKS3    SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4)
+#define SKS4    SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3)
+#define SKS5    SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2)
+#define SKS6    SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2)
+#define SKS7    SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0)
+
+#define WUP(wi, wi5, wi3, wi1, cc)   do { \
+        ulong32 tt = (wi) ^ (wi5) ^ (wi3) \
+            ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \
+        (wi) = ROLc(tt, 11); \
+    } while (0)
+
+#define WUP0(cc)   do { \
+        WUP(w0, w3, w5, w7, cc); \
+        WUP(w1, w4, w6, w0, cc + 1); \
+        WUP(w2, w5, w7, w1, cc + 2); \
+        WUP(w3, w6, w0, w2, cc + 3); \
+    } while (0)
+
+#define WUP1(cc)   do { \
+        WUP(w4, w7, w1, w3, cc); \
+        WUP(w5, w0, w2, w4, cc + 1); \
+        WUP(w6, w1, w3, w5, cc + 2); \
+        WUP(w7, w2, w4, w6, cc + 3); \
+    } while (0)
+
+    unsigned char wbuf[32];
+    ulong32 w0, w1, w2, w3, w4, w5, w6, w7;
+    int i = 0;
+
+   LTC_ARGCHK(ss  != NULL);
+   LTC_ARGCHK(key != NULL);
+
+    /*
+     * The key is copied into the wbuf[] buffer and padded to 256 bits
+     * as described in the Serpent specification.
+     */
+    if (keylen == 0 || keylen > 32) {
+        fprintf(stderr, "invalid key size: %lu\n",
+            (unsigned long)keylen);
+        exit(EXIT_FAILURE);
+    }
+    XMEMCPY(wbuf, key, keylen);
+    if (keylen < 32) {
+        wbuf[keylen] = 0x01;
+        if (keylen < 31)
+            XMEMSET(wbuf + keylen + 1, 0, 31 - keylen);
+    }
+
+    LOAD32L(w0, wbuf);
+    LOAD32L(w1, wbuf + 4);
+    LOAD32L(w2, wbuf + 8);
+    LOAD32L(w3, wbuf + 12);
+    LOAD32L(w4, wbuf + 16);
+    LOAD32L(w5, wbuf + 20);
+    LOAD32L(w6, wbuf + 24);
+    LOAD32L(w7, wbuf + 28);
+
+    WUP0(0);   SKS3;
+    WUP1(4);   SKS2;
+    WUP0(8);   SKS1;
+    WUP1(12);  SKS0;
+    WUP0(16);  SKS7;
+    WUP1(20);  SKS6;
+    WUP0(24);  SKS5;
+    WUP1(28);  SKS4;
+    WUP0(32);  SKS3;
+    WUP1(36);  SKS2;
+    WUP0(40);  SKS1;
+    WUP1(44);  SKS0;
+    WUP0(48);  SKS7;
+    WUP1(52);  SKS6;
+    WUP0(56);  SKS5;
+    WUP1(60);  SKS4;
+    WUP0(64);  SKS3;
+    WUP1(68);  SKS2;
+    WUP0(72);  SKS1;
+    WUP1(76);  SKS0;
+    WUP0(80);  SKS7;
+    WUP1(84);  SKS6;
+    WUP0(88);  SKS5;
+    WUP1(92);  SKS4;
+    WUP0(96);  SKS3;
+
+#undef SKS
+#undef SKS0
+#undef SKS1
+#undef SKS2
+#undef SKS3
+#undef SKS4
+#undef SKS5
+#undef SKS6
+#undef SKS7
+#undef WUP
+#undef WUP0
+#undef WUP1
+
+    /*
+     * Initialize with a zero-value iv to ensure state is correct in the
+     * event user fails to call setiv().
+     */
+    return sosemanuk_setiv(ss, NULL, 0);
+}
+
+
+/*
+ * Cipher initialization: the cipher internal state is initialized, using
+ * the provided key context and IV. The IV length is up to 16 bytes. If
+ * "ivlen" is 0 (no IV), then the "iv" parameter can be NULL.
+ * @param ss       The Sosemanuk state
+ * @param iv       Initialization vector
+ * @param ivlen    Length of iv
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_setiv(sosemanuk_state *ss, 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]; \
+    } while (0)
+
+    /*
+     * One Serpent round.
+     *   zc = current subkey counter
+     *   S = S-box macro for this round
+     *   i0 to i4 = input register numbers (the fifth is a scratch register)
+     *   o0 to o3 = output register numbers
+     */
+#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3)  do { \
+        KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \
+        S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \
+        SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \
+    } while (0)
+
+    /*
+     * Last Serpent round. Contrary to the "true" Serpent, we keep
+     * the linear transformation for that last round.
+     */
+#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3)  do { \
+        KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \
+        S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \
+        SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \
+        KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \
+    } while (0)
+
+    ulong32 r0, r1, r2, r3, r4;
+    unsigned char ivtmp[16] = {0};
+
+    LTC_ARGCHK(ss != NULL);
+    LTC_ARGCHK(ivlen >= 0 && ivlen <= 16);
+    LTC_ARGCHK(iv != NULL || ivlen == 0);
+
+    if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen);
+
+    /*
+     * Decode IV into four 32-bit words (little-endian).
+     */
+    LOAD32L(r0, ivtmp);
+    LOAD32L(r1, ivtmp + 4);
+    LOAD32L(r2, ivtmp + 8);
+    LOAD32L(r3, ivtmp + 12);
+
+    /*
+     * Encrypt IV with Serpent24. Some values are extracted from the
+     * output of the twelfth, eighteenth and twenty-fourth rounds.
+     */
+    FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0);
+    FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4);
+    FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3);
+    FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2);
+    FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2);
+    FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4);
+    FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1);
+    FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0);
+    FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4);
+    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;
+
+    FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2);
+    FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3);
+    FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1);
+    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;
+
+    FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4);
+    FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2);
+    FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2);
+    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;
+
+    ss->ptr = sizeof(ss->buf);
+
+#undef KA
+#undef FSS
+#undef FSF
+
+    return CRYPT_OK;
+}
+
+/*
+ * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24]
+ */
+static ulong32 mul_a[] = {
+    0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835,
+    0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679,
+    0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD,
+    0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1,
+    0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC,
+    0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0,
+    0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534,
+    0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78,
+    0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE,
+    0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2,
+    0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636,
+    0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A,
+    0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37,
+    0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B,
+    0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF,
+    0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3,
+    0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA,
+    0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6,
+    0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032,
+    0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E,
+    0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33,
+    0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F,
+    0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB,
+    0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7,
+    0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31,
+    0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D,
+    0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9,
+    0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5,
+    0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8,
+    0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4,
+    0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330,
+    0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C,
+    0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2,
+    0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE,
+    0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A,
+    0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276,
+    0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B,
+    0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77,
+    0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3,
+    0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF,
+    0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239,
+    0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75,
+    0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1,
+    0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED,
+    0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0,
+    0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC,
+    0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38,
+    0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174,
+    0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D,
+    0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71,
+    0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5,
+    0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9,
+    0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4,
+    0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8,
+    0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C,
+    0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770,
+    0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6,
+    0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA,
+    0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E,
+    0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472,
+    0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F,
+    0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973,
+    0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7,
+    0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB
+};
+
+/*
+ * Multiplication by 1/alpha: 1/alpha * x = (x >> 8) ^ mul_ia[x & 0xFF]
+ */
+static ulong32 mul_ia[] = {
+    0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE,
+    0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998,
+    0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32,
+    0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254,
+    0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF,
+    0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9,
+    0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403,
+    0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65,
+    0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C,
+    0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA,
+    0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550,
+    0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36,
+    0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD,
+    0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB,
+    0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61,
+    0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307,
+    0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A,
+    0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C,
+    0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6,
+    0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790,
+    0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B,
+    0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D,
+    0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7,
+    0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1,
+    0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58,
+    0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E,
+    0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094,
+    0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2,
+    0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469,
+    0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F,
+    0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5,
+    0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3,
+    0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF,
+    0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9,
+    0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813,
+    0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175,
+    0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE,
+    0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588,
+    0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722,
+    0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44,
+    0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD,
+    0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB,
+    0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671,
+    0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17,
+    0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C,
+    0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA,
+    0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940,
+    0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026,
+    0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B,
+    0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D,
+    0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7,
+    0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1,
+    0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A,
+    0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C,
+    0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6,
+    0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80,
+    0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879,
+    0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F,
+    0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5,
+    0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3,
+    0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748,
+    0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E,
+    0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84,
+    0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2
+};
+
+
+/*
+ * 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)
+{
+    /*
+     * MUL_A(x) computes alpha * x (in F_{2^32}).
+     * MUL_G(x) computes 1/alpha * x (in F_{2^32}).
+     */
+#define MUL_A(x)    (T32((x) << 8) ^ mul_a[(x) >> 24])
+#define MUL_G(x)    (((x) >> 8) ^ mul_ia[(x) & 0xFF])
+
+    /*
+     * This macro computes the special multiplexer, which chooses
+     * between "x" and "x xor y", depending on the least significant
+     * bit of the control word. We use the C "?:" selection operator
+     * (which most compilers know how to optimise) except for Alpha,
+     * where the manual sign extension seems to perform equally well
+     * with DEC/Compaq/HP compiler, and much better with gcc.
+     */
+#ifdef __alpha
+#define XMUX(c, x, y)   ((((signed int)((c) << 31) >> 31) & (y)) ^ (x))
+#else
+#define XMUX(c, x, y)   (((c) & 0x1) ? ((x) ^ (y)) : (x))
+#endif
+
+    /*
+     * FSM() updates the finite state machine.
+     */
+#define FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9)   do { \
+        ulong32 tt, or1; \
+        tt = XMUX(r1, s ## x1, s ## x8); \
+        or1 = r1; \
+        r1 = T32(r2 + tt); \
+        tt = T32(or1 * 0x54655307); \
+        r2 = ROLc(tt, 7); \
+    } while (0)
+
+    /*
+     * LRU updates the shift register; the dropped value is stored
+     * in variable "dd".
+     */
+#define LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd)   do { \
+        dd = s ## x0; \
+        s ## x0 = MUL_A(s ## x0) ^ MUL_G(s ## x3) ^ s ## x9; \
+    } while (0)
+
+    /*
+     * CC1 stores into variable "ee" the next intermediate word
+     * (combination of the new states of the LFSR and the FSM).
+     */
+#define CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee)   do { \
+        ee = T32(s ## x9 + r1) ^ r2; \
+    } while (0)
+
+    /*
+     * STEP computes one internal round. "dd" receives the "s_t"
+     * value (dropped from the LFSR) and "ee" gets the value computed
+     * from the LFSR and FSM.
+     */
+#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd, ee)   do { \
+        FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9); \
+        LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd); \
+        CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee); \
+    } while (0)
+
+    /*
+     * Apply one Serpent round (with the provided S-box macro), XOR
+     * the result with the "v" values, and encode the result into
+     * the destination buffer, at the provided offset. The "x*"
+     * arguments encode the output permutation of the "S" macro.
+     */
+#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); \
+    } 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 u0, u1, u2, u3, u4;
+    ulong32 v0, v1, v2, v3;
+
+    STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v0, u0);
+    STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v1, u1);
+    STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v2, u2);
+    STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v3, u3);
+    SRD(S2, 2, 3, 1, 4, 0);
+    STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v0, u0);
+    STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v1, u1);
+    STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v2, u2);
+    STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v3, u3);
+    SRD(S2, 2, 3, 1, 4, 16);
+    STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v0, u0);
+    STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v1, u1);
+    STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v2, u2);
+    STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v3, u3);
+    SRD(S2, 2, 3, 1, 4, 32);
+    STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v0, u0);
+    STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v1, u1);
+    STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v2, u2);
+    STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v3, u3);
+    SRD(S2, 2, 3, 1, 4, 48);
+    STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v0, u0);
+    STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v1, u1);
+    STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v2, u2);
+    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;
+}
+
+/*
+ * Combine buffers in1[] and in2[] by XOR, result in out[]. The length
+ * is "datalen" (in bytes). Partial overlap of out[] with either in1[]
+ * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2)
+ * is allowed.
+ */
+static LTC_INLINE void _xorbuf(const unsigned char *in1, const unsigned char *in2,
+    unsigned char *out, unsigned long datalen)
+{
+    while (datalen -- > 0)
+        *out ++ = *in1 ++ ^ *in2 ++;
+}
+
+
+/*
+ * Cipher operation, as a stream cipher: data is read from the "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 in       Data in
+ * @param out      Data out
+ * @param datalen  Length of data
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_crypt(sosemanuk_state *ss,
+                        const unsigned char *in, unsigned long datalen, unsigned char *out)
+{
+    LTC_ARGCHK(ss  != NULL);
+    LTC_ARGCHK(in  != NULL);
+    LTC_ARGCHK(out != NULL);
+
+    if (ss->ptr < (sizeof(ss->buf))) {
+        unsigned long rlen = (sizeof(ss->buf)) - ss->ptr;
+
+        if (rlen > datalen)
+            rlen = datalen;
+        _xorbuf(ss->buf + ss->ptr, in, out, rlen);
+        in += rlen;
+        out += rlen;
+        datalen -= rlen;
+        ss->ptr += rlen;
+    }
+    while (datalen > 0) {
+        _sosemanuk_internal(ss);
+        if (datalen >= sizeof(ss->buf)) {
+            _xorbuf(ss->buf, in, out, sizeof(ss->buf));
+            in += sizeof(ss->buf);
+            out += sizeof(ss->buf);
+            datalen -= sizeof(ss->buf);
+        } else {
+            _xorbuf(ss->buf, in, out, datalen);
+            ss->ptr = datalen;
+            datalen = 0;
+        }
+    }
+    return CRYPT_OK;
+}
+
+
+/*
+ * 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 out      Data out
+ * @param outlen   Length of output
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_keystream(sosemanuk_state *ss, 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);
+}
+
+
+/*
+ * Terminate and clear Sosemanuk key context
+ * @param kc      The Sosemanuk key context
+ * @return CRYPT_OK on success
+ */
+int sosemanuk_done(sosemanuk_state *ss)
+{
+   LTC_ARGCHK(ss != NULL);
+   XMEMSET(ss, 0, sizeof(sosemanuk_state));
+   return CRYPT_OK;
+}
+
+
+#endif
+
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */

+ 84 - 0
src/stream/sosemanuk/sosemanuk_test.c

@@ -0,0 +1,84 @@
+/* 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.h"
+
+#ifdef LTC_SOSEMANUK
+int sosemanuk_test(void)
+{
+#ifndef LTC_TEST
+   return CRYPT_NOP;
+#else
+   sosemanuk_state ss;
+   int err;
+   unsigned char out[1000];
+
+   {
+       unsigned char k[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                              0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
+       unsigned char n[]  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       unsigned char ct[] = { 0x7e, 0xfe, 0x2e, 0x6f, 0x8f, 0x77, 0x15, 0x72, 0x6a, 0x88, 0x14, 0xa6, 0x56, 0x88, 0x29, 0x9a,
+                              0x86, 0x32, 0x7f, 0x14, 0xd6, 0xb1, 0x94, 0x90, 0x25, 0xbc, 0x73, 0xfd, 0x02, 0x6c, 0x6a, 0xb8,
+                              0xda, 0x8e, 0x7f, 0x61, 0x70, 0x81, 0xe3, 0xbb, 0x99, 0xaf, 0x19, 0x9f, 0x20, 0x45 };
+       char pt[]          = "Kilroy was here, and there. ...and everywhere!";    /* len = 46 bytes */
+       unsigned long len;
+       len = strlen(pt);
+       /* crypt piece by piece */
+       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,       5,       out))      != CRYPT_OK) return err;
+       if ((err = sosemanuk_crypt(&ss, (unsigned char*)pt +  5, 25,       out +  5)) != CRYPT_OK) return err;
+       if ((err = sosemanuk_crypt(&ss, (unsigned char*)pt + 30, 10,       out + 30)) != CRYPT_OK) return err;
+       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() */
+       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;
+       if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV2", 1))       return CRYPT_FAIL_TESTVECTOR;
+
+   }
+   {
+       /* keystream
+        * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=210&view=auto
+        * Set 6, vector 0
+        *                key = 0053A6F94C9FF24598EB3E91E4378ADD
+        *                      3083D6297CCF2275C81B6EC11467BA0D
+        *                 IV = 0D74DB42A91077DE45AC137AE148AF16
+        *      stream[0..63] = 55EB8D174C2E0351E5A53C90E84740EB
+        *                      0F5A24AAFEC8E0C9F9D2CE48B2ADB0A3
+        *                      4D2E8C4E016102607368FFA43A0F9155
+        *                      0706E3548AD9E5EA15A53EB6F0EDE9DC
+        *
+        */
+
+       unsigned char k3[]  = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD,
+                               0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D };
+       unsigned char n3[]  = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC, 0x13, 0x7A, 0xE1, 0x48, 0xAF, 0x16 };
+       unsigned char ct3[] = { 0x55, 0xEB, 0x8D, 0x17, 0x4C, 0x2E, 0x03, 0x51, 0xE5, 0xA5, 0x3C, 0x90, 0xE8, 0x47, 0x40, 0xEB,
+                               0x0F, 0x5A, 0x24, 0xAA, 0xFE, 0xC8, 0xE0, 0xC9, 0xF9, 0xD2, 0xCE, 0x48, 0xB2, 0xAD, 0xB0, 0xA3,
+                               0x4D, 0x2E, 0x8C, 0x4E, 0x01, 0x61, 0x02, 0x60, 0x73, 0x68, 0xFF, 0xA4, 0x3A, 0x0F, 0x91, 0x55,
+                               0x07, 0x06, 0xE3, 0x54, 0x8A, 0xD9, 0xE5, 0xEA, 0x15, 0xA5, 0x3E, 0xB6, 0xF0, 0xED, 0xE9, 0xDC };
+       if ((err = sosemanuk_setup(&ss, k3, sizeof(k3)))      != CRYPT_OK)     return err;
+       if ((err = sosemanuk_setiv(&ss, n3, sizeof(n3)))      != CRYPT_OK)     return err;
+       if ((err = sosemanuk_keystream(&ss, out, 64))         != CRYPT_OK)     return err;
+       if ((err = sosemanuk_done(&ss))                       != CRYPT_OK)     return err;
+       if (compare_testvector(out, 64, ct3, sizeof(ct3), "SOSEMANUK-TV3", 1)) return CRYPT_FAIL_TESTVECTOR;
+   }
+
+   return CRYPT_OK;
+#endif
+}
+
+#endif
+
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */

+ 3 - 0
tests/cipher_hash_test.c

@@ -26,6 +26,9 @@ int cipher_hash_test(void)
 #ifdef LTC_SALSA20
    DO(salsa20_test());
 #endif
+#ifdef LTC_SOSEMANUK
+   DO(sosemanuk_test());
+#endif
 #ifdef LTC_RC4_STREAM
    DO(rc4_stream_test());
 #endif