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@iahu.ca, http://libtomcrypt.org
13
/* Implementation of SOBER-128 by Tom St Denis.
14
* Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
19
#include "sober128tab.c"
21
const struct _prng_descriptor sober128_desc =
25
&sober128_add_entropy,
34
/* don't change these... */
36
#define FOLD N /* how many iterations of folding to do */
37
#define INITKONST 0x6996c53a /* value of KONST to use during key loading */
38
#define KEYP 15 /* where to insert key words */
39
#define FOLDP 4 /* where to insert non-linear feedback */
41
#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
43
static ulong32 BYTE2WORD(unsigned char *b)
50
#define WORD2BYTE(w, b) STORE32L(b, w)
52
static void XORWORD(ulong32 w, unsigned char *b)
60
/* give correct offset for the current position of the register,
61
* where logically R[0] is at position "zero".
63
#define OFF(zero, i) (((zero)+(i)) % N)
66
/* After stepping, "zero" moves right one place */
68
R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
70
static void cycle(ulong32 *R)
77
for (i = 1; i < N; ++i) {
83
/* Return a non-linear function of some parts of the register.
87
t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
88
t ^= Sbox[(t >> 24) & 0xFF]; \
90
t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
91
t ^= Sbox[(t >> 24) & 0xFF]; \
92
t = t + c->R[OFF(z,13)]; \
95
static ulong32 nltap(struct sober128_prng *c)
102
/* initialise to known state
104
int sober128_start(prng_state *prng)
107
struct sober128_prng *c;
109
_ARGCHK(prng != NULL);
111
c = &(prng->sober128);
113
/* Register initialised to Fibonacci numbers */
116
for (i = 2; i < N; ++i) {
117
c->R[i] = c->R[i-1] + c->R[i-2];
119
c->konst = INITKONST;
121
/* next add_entropy will be the key */
128
/* Save the current register state
130
static void s128_savestate(struct sober128_prng *c)
133
for (i = 0; i < N; ++i) {
134
c->initR[i] = c->R[i];
138
/* initialise to previously saved register state
140
static void s128_reloadstate(struct sober128_prng *c)
144
for (i = 0; i < N; ++i) {
145
c->R[i] = c->initR[i];
149
/* Initialise "konst"
151
static void s128_genkonst(struct sober128_prng *c)
158
} while ((newkonst & 0xFF000000) == 0);
162
/* Load key material into the register
170
/* nonlinear diffusion of register for key */
171
#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
172
static void s128_diffuse(struct sober128_prng *c)
175
/* relies on FOLD == N == 17! */
195
int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
197
struct sober128_prng *c;
200
_ARGCHK(buf != NULL);
201
_ARGCHK(prng != NULL);
202
c = &(prng->sober128);
205
/* this is the first call to the add_entropy so this input is the key */
206
/* len must be multiple of 4 bytes */
207
if ((len & 3) != 0) {
208
return CRYPT_INVALID_KEYSIZE;
211
for (i = 0; i < len; i += 4) {
212
k = BYTE2WORD((unsigned char *)&buf[i]);
218
/* also fold in the length of the key */
230
/* ok we are adding an IV then... */
233
/* len must be multiple of 4 bytes */
234
if ((len & 3) != 0) {
235
return CRYPT_INVALID_KEYSIZE;
238
for (i = 0; i < len; i += 4) {
239
k = BYTE2WORD((unsigned char *)&buf[i]);
245
/* also fold in the length of the key */
256
int sober128_ready(prng_state *prng)
258
return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR;
261
/* XOR pseudo-random bytes into buffer
263
#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, buf+(z*4));
265
unsigned long sober128_read(unsigned char *buf, unsigned long nbytes, prng_state *prng)
267
struct sober128_prng *c;
270
_ARGCHK(buf != NULL);
271
_ARGCHK(prng != NULL);
273
c = &(prng->sober128);
277
/* handle any previously buffered bytes */
278
while (c->nbuf != 0 && nbytes != 0) {
279
*buf++ ^= c->sbuf & 0xFF;
286
/* do lots at a time, if there's enough to do */
287
while (nbytes >= N*4) {
310
/* do small or odd size buffers the slow way */
311
while (4 <= nbytes) {
319
/* handle any trailing bytes */
324
while (c->nbuf != 0 && nbytes != 0) {
325
*buf++ ^= c->sbuf & 0xFF;
335
int sober128_done(prng_state *prng)
337
_ARGCHK(prng != NULL);
341
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
343
_ARGCHK(outlen != NULL);
344
_ARGCHK(out != NULL);
345
_ARGCHK(prng != NULL);
348
return CRYPT_BUFFER_OVERFLOW;
351
if (sober128_read(out, 64, prng) != 64) {
352
return CRYPT_ERROR_READPRNG;
359
int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
363
_ARGCHK(prng != NULL);
366
return CRYPT_INVALID_ARG;
369
if ((err = sober128_start(prng)) != CRYPT_OK) {
372
if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) {
375
return sober128_ready(prng);
378
int sober128_test(void)
383
static const struct {
384
int keylen, ivlen, len;
385
unsigned char key[16], iv[4], out[20];
392
{ 't', 'e', 's', 't', ' ', 'k', 'e', 'y',
393
' ', '1', '2', '8', 'b', 'i', 't', 's' },
396
{ 0x00, 0x00, 0x00, 0x0 },
398
/* expected output */
399
{ 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d,
400
0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2,
401
0x40, 0x37, 0x8b, 0xbb }
406
unsigned char dst[20];
409
for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
410
if ((err = sober128_start(&prng)) != CRYPT_OK) {
413
if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) {
417
if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) {
422
if ((err = sober128_ready(&prng)) != CRYPT_OK) {
425
memset(dst, 0, tests[x].len);
426
if (sober128_read(dst, tests[x].len, &prng) != (unsigned long)tests[x].len) {
427
return CRYPT_ERROR_READPRNG;
429
sober128_done(&prng);
430
if (memcmp(dst, tests[x].out, tests[x].len)) {
432
printf("\n\nSOBER128 failed, I got:\n");
433
for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]);
436
return CRYPT_FAIL_TESTVECTOR;