~ubuntu-branches/ubuntu/utopic/dropbear/utopic-proposed

« back to all changes in this revision

Viewing changes to libtomcrypt/sober128.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Johnston
  • Date: 2005-12-08 19:20:21 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051208192021-nyp9rwnt77nsg6ty
Tags: 0.47-1
* New upstream release.
* SECURITY: Fix incorrect buffer sizing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2
 
 *
3
 
 * LibTomCrypt is a library that provides various cryptographic
4
 
 * algorithms in a highly modular and flexible manner.
5
 
 *
6
 
 * The library is free for all purposes without any express
7
 
 * guarantee it works.
8
 
 *
9
 
 * Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
10
 
 */
11
 
#include "mycrypt.h"
12
 
 
13
 
/* Implementation of SOBER-128 by Tom St Denis.
14
 
 * Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
15
 
 */
16
 
 
17
 
#ifdef SOBER128
18
 
 
19
 
#include "sober128tab.c"
20
 
 
21
 
const struct _prng_descriptor sober128_desc = 
22
 
{
23
 
   "sober128", 64,
24
 
    &sober128_start,
25
 
    &sober128_add_entropy,
26
 
    &sober128_ready,
27
 
    &sober128_read,
28
 
    &sober128_done,
29
 
    &sober128_export,
30
 
    &sober128_import,
31
 
    &sober128_test
32
 
};
33
 
 
34
 
/* don't change these... */
35
 
#define N                        17
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 */
40
 
 
41
 
#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
42
 
 
43
 
static ulong32 BYTE2WORD(unsigned char *b)
44
 
{
45
 
   ulong32 t;
46
 
   LOAD32L(t, b);
47
 
   return t;
48
 
}
49
 
 
50
 
#define WORD2BYTE(w, b) STORE32L(b, w)
51
 
 
52
 
static void XORWORD(ulong32 w, unsigned char *b)
53
 
{
54
 
   ulong32 t;
55
 
   LOAD32L(t, b);
56
 
   t ^= w;
57
 
   STORE32L(t, b);
58
 
}
59
 
 
60
 
/* give correct offset for the current position of the register,
61
 
 * where logically R[0] is at position "zero".
62
 
 */
63
 
#define OFF(zero, i) (((zero)+(i)) % N)
64
 
 
65
 
/* step the LFSR */
66
 
/* After stepping, "zero" moves right one place */
67
 
#define STEP(R,z) \
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];
69
 
 
70
 
static void cycle(ulong32 *R)
71
 
{
72
 
    ulong32 t;
73
 
    int     i;
74
 
 
75
 
    STEP(R,0);
76
 
    t = R[0];
77
 
    for (i = 1; i < N; ++i) {
78
 
        R[i-1] = R[i];
79
 
    }
80
 
    R[N-1] = t;
81
 
}
82
 
 
83
 
/* Return a non-linear function of some parts of the register.
84
 
 */
85
 
#define NLFUNC(c,z) \
86
 
{ \
87
 
    t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
88
 
    t ^= Sbox[(t >> 24) & 0xFF]; \
89
 
    t = ROR(t, 8); \
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)]; \
93
 
}
94
 
 
95
 
static ulong32 nltap(struct sober128_prng *c)
96
 
{
97
 
    ulong32 t;
98
 
    NLFUNC(c, 0);
99
 
    return t;
100
 
}
101
 
 
102
 
/* initialise to known state
103
 
 */
104
 
int sober128_start(prng_state *prng)
105
 
{
106
 
    int                   i;
107
 
    struct sober128_prng *c;
108
 
 
109
 
    _ARGCHK(prng != NULL);
110
 
 
111
 
    c = &(prng->sober128);
112
 
    
113
 
    /* Register initialised to Fibonacci numbers */
114
 
    c->R[0] = 1;
115
 
    c->R[1] = 1;
116
 
    for (i = 2; i < N; ++i) {
117
 
       c->R[i] = c->R[i-1] + c->R[i-2];
118
 
    }
119
 
    c->konst = INITKONST;
120
 
 
121
 
    /* next add_entropy will be the key */
122
 
    c->flag  = 1;
123
 
    c->set   = 0;
124
 
 
125
 
    return CRYPT_OK;
126
 
}
127
 
 
128
 
/* Save the current register state
129
 
 */
130
 
static void s128_savestate(struct sober128_prng *c)
131
 
{
132
 
    int i;
133
 
    for (i = 0; i < N; ++i) {
134
 
        c->initR[i] = c->R[i];
135
 
    }
136
 
}
137
 
 
138
 
/* initialise to previously saved register state
139
 
 */
140
 
static void s128_reloadstate(struct sober128_prng *c)
141
 
{
142
 
    int i;
143
 
 
144
 
    for (i = 0; i < N; ++i) {
145
 
        c->R[i] = c->initR[i];
146
 
    }
147
 
}
148
 
 
149
 
/* Initialise "konst"
150
 
 */
151
 
static void s128_genkonst(struct sober128_prng *c)
152
 
{
153
 
    ulong32 newkonst;
154
 
 
155
 
    do {
156
 
       cycle(c->R);
157
 
       newkonst = nltap(c);
158
 
    } while ((newkonst & 0xFF000000) == 0);
159
 
    c->konst = newkonst;
160
 
}
161
 
 
162
 
/* Load key material into the register
163
 
 */
164
 
#define ADDKEY(k) \
165
 
   c->R[KEYP] += (k);
166
 
 
167
 
#define XORNL(nl) \
168
 
   c->R[FOLDP] ^= (nl);
169
 
 
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)
173
 
{
174
 
    ulong32 t;
175
 
    /* relies on FOLD == N == 17! */
176
 
    DROUND(0);
177
 
    DROUND(1);
178
 
    DROUND(2);
179
 
    DROUND(3);
180
 
    DROUND(4);
181
 
    DROUND(5);
182
 
    DROUND(6);
183
 
    DROUND(7);
184
 
    DROUND(8);
185
 
    DROUND(9);
186
 
    DROUND(10);
187
 
    DROUND(11);
188
 
    DROUND(12);
189
 
    DROUND(13);
190
 
    DROUND(14);
191
 
    DROUND(15);
192
 
    DROUND(16);
193
 
}
194
 
 
195
 
int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
196
 
{
197
 
    struct sober128_prng *c;
198
 
    ulong32               i, k;
199
 
 
200
 
    _ARGCHK(buf != NULL);
201
 
    _ARGCHK(prng != NULL);
202
 
    c = &(prng->sober128);
203
 
 
204
 
    if (c->flag == 1) {
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;
209
 
       }
210
 
    
211
 
       for (i = 0; i < len; i += 4) {
212
 
           k = BYTE2WORD((unsigned char *)&buf[i]);
213
 
          ADDKEY(k);
214
 
          cycle(c->R);
215
 
          XORNL(nltap(c));
216
 
       }
217
 
 
218
 
       /* also fold in the length of the key */
219
 
       ADDKEY(len);
220
 
 
221
 
       /* now diffuse */
222
 
       s128_diffuse(c);
223
 
 
224
 
       s128_genkonst(c);
225
 
       s128_savestate(c);
226
 
       c->nbuf = 0;
227
 
       c->flag = 0;       
228
 
       c->set  = 1;
229
 
    } else {
230
 
       /* ok we are adding an IV then... */
231
 
       s128_reloadstate(c);
232
 
 
233
 
       /* len must be multiple of 4 bytes */
234
 
       if ((len & 3) != 0) {
235
 
          return CRYPT_INVALID_KEYSIZE;
236
 
       }
237
 
    
238
 
       for (i = 0; i < len; i += 4) {
239
 
           k = BYTE2WORD((unsigned char *)&buf[i]);
240
 
          ADDKEY(k);
241
 
          cycle(c->R);
242
 
          XORNL(nltap(c));
243
 
       }
244
 
 
245
 
       /* also fold in the length of the key */
246
 
       ADDKEY(len);
247
 
 
248
 
       /* now diffuse */
249
 
       s128_diffuse(c);
250
 
       c->nbuf = 0;
251
 
    }
252
 
 
253
 
    return CRYPT_OK;
254
 
}
255
 
 
256
 
int sober128_ready(prng_state *prng)
257
 
{
258
 
   return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR;
259
 
}
260
 
 
261
 
/* XOR pseudo-random bytes into buffer
262
 
 */
263
 
#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, buf+(z*4));
264
 
 
265
 
unsigned long sober128_read(unsigned char *buf, unsigned long nbytes, prng_state *prng)
266
 
{
267
 
   struct sober128_prng *c;
268
 
   ulong32               t, tlen;
269
 
 
270
 
   _ARGCHK(buf  != NULL);
271
 
   _ARGCHK(prng != NULL);
272
 
 
273
 
   c = &(prng->sober128);
274
 
   t = 0;
275
 
   tlen = nbytes;
276
 
   
277
 
   /* handle any previously buffered bytes */
278
 
   while (c->nbuf != 0 && nbytes != 0) {
279
 
      *buf++ ^= c->sbuf & 0xFF;
280
 
       c->sbuf >>= 8;
281
 
       c->nbuf -= 8;
282
 
       --nbytes;
283
 
   }
284
 
 
285
 
#ifndef SMALL_CODE
286
 
    /* do lots at a time, if there's enough to do */
287
 
    while (nbytes >= N*4) {
288
 
      SROUND(0);
289
 
      SROUND(1);
290
 
      SROUND(2);
291
 
      SROUND(3);
292
 
      SROUND(4);
293
 
      SROUND(5);
294
 
      SROUND(6);
295
 
      SROUND(7);
296
 
      SROUND(8);
297
 
      SROUND(9);
298
 
      SROUND(10);
299
 
      SROUND(11);
300
 
      SROUND(12);
301
 
      SROUND(13);
302
 
      SROUND(14);
303
 
      SROUND(15);
304
 
      SROUND(16);
305
 
      buf    += 4*N;
306
 
      nbytes -= 4*N;
307
 
    }
308
 
#endif
309
 
 
310
 
    /* do small or odd size buffers the slow way */
311
 
    while (4 <= nbytes) {
312
 
      cycle(c->R);
313
 
      t = nltap(c);
314
 
      XORWORD(t, buf);
315
 
      buf    += 4;
316
 
      nbytes -= 4;
317
 
    }
318
 
 
319
 
    /* handle any trailing bytes */
320
 
    if (nbytes != 0) {
321
 
      cycle(c->R);
322
 
      c->sbuf = nltap(c);
323
 
      c->nbuf = 32;
324
 
      while (c->nbuf != 0 && nbytes != 0) {
325
 
          *buf++ ^= c->sbuf & 0xFF;
326
 
          c->sbuf >>= 8;
327
 
          c->nbuf -= 8;
328
 
          --nbytes;
329
 
      }
330
 
    }
331
 
 
332
 
    return tlen;
333
 
}
334
 
 
335
 
int sober128_done(prng_state *prng)
336
 
{
337
 
   _ARGCHK(prng != NULL);
338
 
   return CRYPT_OK;
339
 
}
340
 
 
341
 
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng)
342
 
{
343
 
   _ARGCHK(outlen != NULL);
344
 
   _ARGCHK(out    != NULL);
345
 
   _ARGCHK(prng   != NULL);
346
 
 
347
 
   if (*outlen < 64) {
348
 
      return CRYPT_BUFFER_OVERFLOW;
349
 
   }
350
 
 
351
 
   if (sober128_read(out, 64, prng) != 64) {
352
 
      return CRYPT_ERROR_READPRNG;
353
 
   }
354
 
   *outlen = 64;
355
 
 
356
 
   return CRYPT_OK;
357
 
}
358
 
 
359
 
int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng)
360
 
{
361
 
   int err;
362
 
   _ARGCHK(in   != NULL);
363
 
   _ARGCHK(prng != NULL);
364
 
 
365
 
   if (inlen != 64) {
366
 
      return CRYPT_INVALID_ARG;
367
 
   }
368
 
   
369
 
   if ((err = sober128_start(prng)) != CRYPT_OK) {
370
 
      return err;
371
 
   }
372
 
   if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) {
373
 
      return err;
374
 
   }
375
 
   return sober128_ready(prng);
376
 
}
377
 
 
378
 
int sober128_test(void)
379
 
{
380
 
#ifndef LTC_TEST
381
 
   return CRYPT_NOP;
382
 
#else
383
 
   static const struct { 
384
 
     int keylen, ivlen, len;
385
 
     unsigned char key[16], iv[4], out[20];
386
 
   } tests[] = {
387
 
 
388
 
{
389
 
   16, 4, 20,
390
 
 
391
 
   /* key */
392
 
   { 't', 'e', 's', 't', ' ', 'k', 'e', 'y', 
393
 
     ' ', '1', '2', '8', 'b', 'i', 't', 's' },
394
 
 
395
 
   /* IV */
396
 
   { 0x00, 0x00, 0x00, 0x0 },
397
 
 
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 }
402
 
}
403
 
 
404
 
};
405
 
   prng_state    prng;
406
 
   unsigned char dst[20];
407
 
   int           err, x;
408
 
 
409
 
   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
410
 
       if ((err = sober128_start(&prng)) != CRYPT_OK) {
411
 
          return err;
412
 
       }
413
 
       if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) {
414
 
          return err;
415
 
       }
416
 
       /* add IV */
417
 
       if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) {
418
 
          return err;
419
 
       }
420
 
 
421
 
       /* ready up */
422
 
       if ((err = sober128_ready(&prng)) != CRYPT_OK) {
423
 
          return err;
424
 
       }
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;
428
 
       }
429
 
       sober128_done(&prng);
430
 
       if (memcmp(dst, tests[x].out, tests[x].len)) {
431
 
#if 0
432
 
          printf("\n\nSOBER128 failed, I got:\n"); 
433
 
          for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]);
434
 
          printf("\n");
435
 
#endif
436
 
          return CRYPT_FAIL_TESTVECTOR;
437
 
       }
438
 
   }
439
 
   return CRYPT_OK;
440
 
#endif
441
 
}
442
 
 
443
 
#endif
444