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
9
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
15
Implementation of SOBER-128 by Tom St Denis.
16
Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
21
#include "sober128tab.c"
23
const struct ltc_prng_descriptor sober128_desc =
27
&sober128_add_entropy,
36
/* don't change these... */
38
#define FOLD N /* how many iterations of folding to do */
39
#define INITKONST 0x6996c53a /* value of KONST to use during key loading */
40
#define KEYP 15 /* where to insert key words */
41
#define FOLDP 4 /* where to insert non-linear feedback */
43
#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
45
static ulong32 BYTE2WORD(unsigned char *b)
52
#define WORD2BYTE(w, b) STORE32L(b, w)
54
static void XORWORD(ulong32 w, unsigned char *b)
62
/* give correct offset for the current position of the register,
63
* where logically R[0] is at position "zero".
65
#define OFF(zero, i) (((zero)+(i)) % N)
68
/* After stepping, "zero" moves right one place */
70
R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
72
static void cycle(ulong32 *R)
79
for (i = 1; i < N; ++i) {
85
/* Return a non-linear function of some parts of the register.
89
t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
90
t ^= Sbox[(t >> 24) & 0xFF]; \
92
t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
93
t ^= Sbox[(t >> 24) & 0xFF]; \
94
t = t + c->R[OFF(z,13)]; \
97
static ulong32 nltap(struct sober128_prng *c)
106
@param prng [out] The PRNG state to initialize
107
@return CRYPT_OK if successful
109
int sober128_start(prng_state *prng)
112
struct sober128_prng *c;
114
LTC_ARGCHK(prng != NULL);
116
c = &(prng->sober128);
118
/* Register initialised to Fibonacci numbers */
121
for (i = 2; i < N; ++i) {
122
c->R[i] = c->R[i-1] + c->R[i-2];
124
c->konst = INITKONST;
126
/* next add_entropy will be the key */
133
/* Save the current register state
135
static void s128_savestate(struct sober128_prng *c)
138
for (i = 0; i < N; ++i) {
139
c->initR[i] = c->R[i];
143
/* initialise to previously saved register state
145
static void s128_reloadstate(struct sober128_prng *c)
149
for (i = 0; i < N; ++i) {
150
c->R[i] = c->initR[i];
154
/* Initialise "konst"
156
static void s128_genkonst(struct sober128_prng *c)
163
} while ((newkonst & 0xFF000000) == 0);
167
/* Load key material into the register
175
/* nonlinear diffusion of register for key */
176
#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
177
static void s128_diffuse(struct sober128_prng *c)
180
/* relies on FOLD == N == 17! */
201
Add entropy to the PRNG state
202
@param in The data to add
203
@param inlen Length of the data to add
204
@param prng PRNG state to update
205
@return CRYPT_OK if successful
207
int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng)
209
struct sober128_prng *c;
212
LTC_ARGCHK(in != NULL);
213
LTC_ARGCHK(prng != NULL);
214
c = &(prng->sober128);
217
/* this is the first call to the add_entropy so this input is the key */
218
/* inlen must be multiple of 4 bytes */
219
if ((inlen & 3) != 0) {
220
return CRYPT_INVALID_KEYSIZE;
223
for (i = 0; i < inlen; i += 4) {
224
k = BYTE2WORD((unsigned char *)&in[i]);
230
/* also fold in the length of the key */
242
/* ok we are adding an IV then... */
245
/* inlen must be multiple of 4 bytes */
246
if ((inlen & 3) != 0) {
247
return CRYPT_INVALID_KEYSIZE;
250
for (i = 0; i < inlen; i += 4) {
251
k = BYTE2WORD((unsigned char *)&in[i]);
257
/* also fold in the length of the key */
269
Make the PRNG ready to read from
270
@param prng The PRNG to make active
271
@return CRYPT_OK if successful
273
int sober128_ready(prng_state *prng)
275
return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR;
278
/* XOR pseudo-random bytes into buffer
280
#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, out+(z*4));
284
@param out Destination
285
@param outlen Length of output
286
@param prng The active PRNG to read from
287
@return Number of octets read
289
unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng)
291
struct sober128_prng *c;
294
LTC_ARGCHK(out != NULL);
295
LTC_ARGCHK(prng != NULL);
297
c = &(prng->sober128);
301
/* handle any previously buffered bytes */
302
while (c->nbuf != 0 && outlen != 0) {
303
*out++ ^= c->sbuf & 0xFF;
309
#ifndef LTC_SMALL_CODE
310
/* do lots at a time, if there's enough to do */
311
while (outlen >= N*4) {
334
/* do small or odd size buffers the slow way */
335
while (4 <= outlen) {
343
/* handle any trailing bytes */
348
while (c->nbuf != 0 && outlen != 0) {
349
*out++ ^= c->sbuf & 0xFF;
361
@param prng The PRNG to terminate
362
@return CRYPT_OK if successful
364
int sober128_done(prng_state *prng)
366
LTC_ARGCHK(prng != NULL);
371
Export the PRNG state
372
@param out [out] Destination
373
@param outlen [in/out] Max size and resulting size of the state
374
@param prng The PRNG to export
375
@return CRYPT_OK if successful
377
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
379
LTC_ARGCHK(outlen != NULL);
380
LTC_ARGCHK(out != NULL);
381
LTC_ARGCHK(prng != NULL);
384
return CRYPT_BUFFER_OVERFLOW;
387
if (sober128_read(out, 64, prng) != 64) {
388
return CRYPT_ERROR_READPRNG;
397
@param in The PRNG state
398
@param inlen Size of the state
399
@param prng The PRNG to import
400
@return CRYPT_OK if successful
402
int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
405
LTC_ARGCHK(in != NULL);
406
LTC_ARGCHK(prng != NULL);
409
return CRYPT_INVALID_ARG;
412
if ((err = sober128_start(prng)) != CRYPT_OK) {
415
if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) {
418
return sober128_ready(prng);
423
@return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled
425
int sober128_test(void)
430
static const struct {
431
int keylen, ivlen, len;
432
unsigned char key[16], iv[4], out[20];
439
{ 't', 'e', 's', 't', ' ', 'k', 'e', 'y',
440
' ', '1', '2', '8', 'b', 'i', 't', 's' },
443
{ 0x00, 0x00, 0x00, 0x0 },
445
/* expected output */
446
{ 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d,
447
0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2,
448
0x40, 0x37, 0x8b, 0xbb }
453
unsigned char dst[20];
456
for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
457
if ((err = sober128_start(&prng)) != CRYPT_OK) {
460
if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) {
464
if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) {
469
if ((err = sober128_ready(&prng)) != CRYPT_OK) {
472
memset(dst, 0, tests[x].len);
473
if (sober128_read(dst, tests[x].len, &prng) != (unsigned long)tests[x].len) {
474
return CRYPT_ERROR_READPRNG;
476
sober128_done(&prng);
477
if (memcmp(dst, tests[x].out, tests[x].len)) {
479
printf("\n\nSOBER128 failed, I got:\n");
480
for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]);
483
return CRYPT_FAIL_TESTVECTOR;
493
/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sober128.c,v $ */
494
/* $Revision: 1.3 $ */
495
/* $Date: 2005/05/05 14:35:59 $ */