1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
12 @file sober128_stream.c
13 Implementation of SOBER-128 by Tom St Denis.
14 Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
19 #define __LTC_SOBER128TAB_C__
20 #include "sober128tab.c"
22 /* don't change these... */
24 #define FOLD N /* how many iterations of folding to do */
25 #define INITKONST 0x6996c53a /* value of KONST to use during key loading */
26 #define KEYP 15 /* where to insert key words */
27 #define FOLDP 4 /* where to insert non-linear feedback */
29 #define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
31 static ulong32 BYTE2WORD(unsigned char *b)
38 static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out)
46 /* give correct offset for the current position of the register,
47 * where logically R[0] is at position "zero".
49 #define OFF(zero, i) (((zero)+(i)) % N)
52 /* After stepping, "zero" moves right one place */
54 R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
56 static void cycle(ulong32 *R)
63 for (i = 1; i < N; ++i) {
69 /* Return a non-linear function of some parts of the register.
73 t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
74 t ^= Sbox[(t >> 24) & 0xFF]; \
76 t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
77 t ^= Sbox[(t >> 24) & 0xFF]; \
78 t = t + c->R[OFF(z,13)]; \
81 static ulong32 nltap(sober128_state *c)
88 /* Save the current register state
90 static void s128_savestate(sober128_state *c)
93 for (i = 0; i < N; ++i) {
94 c->initR[i] = c->R[i];
98 /* initialise to previously saved register state
100 static void s128_reloadstate(sober128_state *c)
104 for (i = 0; i < N; ++i) {
105 c->R[i] = c->initR[i];
109 /* Initialise "konst"
111 static void s128_genkonst(sober128_state *c)
118 } while ((newkonst & 0xFF000000) == 0);
122 /* Load key material into the register
130 /* nonlinear diffusion of register for key */
131 #define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
132 static void s128_diffuse(sober128_state *c)
135 /* relies on FOLD == N == 17! */
156 Initialize an Sober128 context (only the key)
157 @param c [out] The destination of the Sober128 state
158 @param key The secret key
159 @param keylen The length of the secret key (octets)
160 @return CRYPT_OK if successful
162 int sober128_stream_setup(sober128_state *c, const unsigned char *key, unsigned long keylen)
166 LTC_ARGCHK(c != NULL);
167 LTC_ARGCHK(key != NULL);
168 LTC_ARGCHK(keylen > 0);
170 /* keylen must be multiple of 4 bytes */
171 if ((keylen & 3) != 0) {
172 return CRYPT_INVALID_KEYSIZE;
175 /* Register initialised to Fibonacci numbers */
178 for (i = 2; i < N; ++i) {
179 c->R[i] = c->R[i-1] + c->R[i-2];
181 c->konst = INITKONST;
183 for (i = 0; i < keylen; i += 4) {
184 k = BYTE2WORD((unsigned char *)&key[i]);
190 /* also fold in the length of the key */
203 Set IV to the Sober128 state
204 @param c The Sober12820 state
205 @param iv The IV data to add
206 @param ivlen The length of the IV (must be 12)
207 @return CRYPT_OK on success
209 int sober128_stream_setiv(sober128_state *c, const unsigned char *iv, unsigned long ivlen)
213 LTC_ARGCHK(c != NULL);
214 LTC_ARGCHK(iv != NULL);
215 LTC_ARGCHK(ivlen > 0);
217 /* ok we are adding an IV then... */
220 /* ivlen must be multiple of 4 bytes */
221 if ((ivlen & 3) != 0) {
222 return CRYPT_INVALID_KEYSIZE;
225 for (i = 0; i < ivlen; i += 4) {
226 k = BYTE2WORD((unsigned char *)&iv[i]);
232 /* also fold in the length of the key */
242 /* XOR pseudo-random bytes into buffer
244 #define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, in+(z*4), out+(z*4));
247 Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128
248 @param c The Sober128 state
249 @param in The plaintext (or ciphertext)
250 @param inlen The length of the input (octets)
251 @param out [out] The ciphertext (or plaintext), length inlen
252 @return CRYPT_OK if successful
254 int sober128_stream_crypt(sober128_state *c, const unsigned char *in, unsigned long inlen, unsigned char *out)
258 if (inlen == 0) return CRYPT_OK; /* nothing to do */
259 LTC_ARGCHK(out != NULL);
260 LTC_ARGCHK(c != NULL);
262 /* handle any previously buffered bytes */
263 while (c->nbuf != 0 && inlen != 0) {
264 *out++ = *in++ ^ (unsigned char)(c->sbuf & 0xFF);
270 #ifndef LTC_SMALL_CODE
271 /* do lots at a time, if there's enough to do */
272 while (inlen >= N*4) {
296 /* do small or odd size buffers the slow way */
306 /* handle any trailing bytes */
311 while (c->nbuf != 0 && inlen != 0) {
312 *out++ = *in++ ^ (unsigned char)(c->sbuf & 0xFF);
322 int sober128_stream_keystream(sober128_state *c, unsigned char *out, unsigned long outlen)
324 if (outlen == 0) return CRYPT_OK; /* nothing to do */
325 LTC_ARGCHK(out != NULL);
326 XMEMSET(out, 0, outlen);
327 return sober128_stream_crypt(c, out, outlen, out);
331 Terminate and clear Sober128 state
332 @param c The Sober128 state
333 @return CRYPT_OK on success
335 int sober128_stream_done(sober128_state *c)
337 LTC_ARGCHK(c != NULL);
338 XMEMSET(c, 0, sizeof(sober128_state));
344 /* ref: $Format:%D$ */
345 /* git commit: $Format:%H$ */
346 /* commit time: $Format:%ai$ */