|
|
1.1.1.5 root 1: /*
1.1.1.6 root 2: * idea.c - C source code for IDEA block cipher.
3: * IDEA (International Data Encryption Algorithm), formerly known as
4: * IPES (Improved Proposed Encryption Standard).
5: * Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
6: * This implementation modified and derived from original C code
7: * developed by Xuejia Lai.
8: * Zero-based indexing added, names changed from IPES to IDEA.
9: * CFB functions added. Random number routines added.
1.1.1.5 root 10: *
1.1.1.6 root 11: * Extensively optimized and restructured by Colin Plumb.
1.1.1.5 root 12: *
1.1.1.6 root 13: * There are two adjustments that can be made to this code to
14: * speed it up. Defaults may be used for PCs. Only the -DIDEA32
15: * pays off significantly if selectively set or not set.
16: * Experiment to see what works best for your machine.
1.1.1.5 root 17: *
1.1.1.6 root 18: * Multiplication: default is inline, -DAVOID_JUMPS uses a
19: * different version that does not do any conditional
20: * jumps (a few percent worse on a SPARC), while
21: * -DSMALL_CACHE takes it out of line to stay
22: * within a small on-chip code cache.
23: * Variables: normally, 16-bit variables are used, but some
24: * machines (notably RISCs) do not have 16-bit registers,
25: * so they do a great deal of masking. -DIDEA32 uses "int"
26: * register variables and masks explicitly only where
27: * necessary. On a SPARC, for example, this boosts
28: * performace by 30%.
1.1.1.5 root 29: *
1.1.1.6 root 30: * The IDEA(tm) block cipher is covered by patents held by ETH and a
31: * Swiss company called Ascom-Tech AG. The Swiss patent number is
32: * PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and
33: * the U.S. patent number is US005214703. IDEA(tm) is a trademark of
34: * Ascom-Tech AG. There is no license fee required for noncommercial
35: * use. Commercial users may obtain licensing details from Dieter
36: * Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn,
37: * Switzerland, Tel +41 65 242885, Fax +41 65 235761.
1.1.1.5 root 38: *
1.1.1.6 root 39: * The IDEA block cipher uses a 64-bit block size, and a 128-bit key
40: * size. It breaks the 64-bit cipher block into four 16-bit words
41: * because all of the primitive inner operations are done with 16-bit
42: * arithmetic. It likewise breaks the 128-bit cipher key into eight
43: * 16-bit words.
1.1.1.5 root 44: *
1.1.1.6 root 45: * For further information on the IDEA cipher, see the book:
46: * Xuejia Lai, "On the Design and Security of Block Ciphers",
47: * ETH Series on Information Processing (ed. J.L. Massey) Vol 1,
48: * Hartung-Gorre Verlag, Konstanz, Switzerland, 1992. ISBN
49: * 3-89191-573-X.
1.1.1.5 root 50: *
1.1.1.6 root 51: * This code runs on arrays of bytes by taking pairs in big-endian
52: * order to make the 16-bit words that IDEA uses internally. This
53: * produces the same result regardless of the byte order of the
54: * native CPU.
1.1.1.5 root 55: */
56:
57: #include "idea.h"
58: #include "randpool.h"
59:
1.1.1.6 root 60: #ifdef IDEA32 /* Use >16-bit temporaries */
1.1.1.5 root 61: #define low16(x) ((x) & 0xFFFF)
62: typedef unsigned int uint16; /* at LEAST 16 bits, maybe more */
63: #else
1.1.1.6 root 64: #define low16(x) (x) /* this is only ever applied to uint16's */
1.1.1.5 root 65: typedef word16 uint16;
66: #endif
67:
68: #ifdef _GNUC_
69: /* __const__ simply means there are no side effects for this function,
70: * which is useful info for the gcc optimizer
71: */
72: #define CONST __const__
73: #else
74: #define CONST
75: #endif
76:
77: /*
1.1.1.6 root 78: * Multiplication, modulo (2**16)+1
1.1.1.5 root 79: * Note that this code is structured on the assumption that
80: * untaken branches are cheaper than taken branches, and the
81: * compiler doesn't schedule branches.
82: */
83: #ifdef SMALL_CACHE
84: CONST static uint16
1.1.1.6 root 85: mul(register uint16 a, register uint16 b)
1.1.1.5 root 86: {
1.1.1.6 root 87: register word32 p;
1.1.1.5 root 88:
1.1.1.6 root 89: p = (word32) a *b;
90: if (p) {
91: b = low16(p);
92: a = p >> 16;
93: return (b - a) + (b < a);
94: } else if (a) {
95: return 1 - a;
1.1.1.7 ! root 96: } else {
! 97: return 1 - b;
1.1.1.6 root 98: }
99: } /* mul */
100: #endif /* SMALL_CACHE */
1.1.1.5 root 101:
102: /*
103: * Compute the multiplicative inverse of x, modulo 65537, using Euclid's
104: * algorithm. It is unrolled twice to avoid swapping the registers each
105: * iteration, and some subtracts of t have been changed to adds.
106: */
107: CONST static uint16
1.1.1.6 root 108: mulInv(uint16 x)
1.1.1.5 root 109: {
1.1.1.6 root 110: uint16 t0, t1;
111: uint16 q, y;
1.1.1.5 root 112:
1.1.1.6 root 113: if (x <= 1)
114: return x; /* 0 and 1 are self-inverse */
115: t1 = 0x10001L / x; /* Since x >= 2, this fits into 16 bits */
116: y = 0x10001L % x;
117: if (y == 1)
118: return low16(1 - t1);
119: t0 = 1;
120: do {
121: q = x / y;
122: x = x % y;
123: t0 += q * t1;
124: if (x == 1)
125: return t0;
126: q = y / x;
127: y = y % x;
128: t1 += q * t0;
129: } while (y != 1);
130: return low16(1 - t1);
131: } /* mukInv */
1.1.1.5 root 132:
133: /*
134: * Expand a 128-bit user key to a working encryption key EK
135: */
1.1.1.6 root 136: static void ideaExpandKey(byte const *userkey, word16 * EK)
1.1.1.5 root 137: {
1.1.1.6 root 138: int i, j;
1.1.1.5 root 139:
1.1.1.6 root 140: for (j = 0; j < 8; j++) {
141: EK[j] = (userkey[0] << 8) + userkey[1];
142: userkey += 2;
143: }
144: for (i = 0; j < IDEAKEYLEN; j++) {
145: i++;
146: EK[i + 7] = EK[i & 7] << 9 | EK[i + 1 & 7] >> 7;
147: EK += i & 8;
148: i &= 7;
149: }
150: } /* ideaExpandKey */
1.1.1.5 root 151:
152: /*
153: * Compute IDEA decryption key DK from an expanded IDEA encryption key EK
154: * Note that the input and output may be the same. Thus, the key is
155: * inverted into an internal buffer, and then copied to the output.
156: */
1.1.1.6 root 157: static void ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN])
1.1.1.5 root 158: {
1.1.1.6 root 159: int i;
160: uint16 t1, t2, t3;
161: word16 temp[IDEAKEYLEN];
162: word16 *p = temp + IDEAKEYLEN;
163:
164: t1 = mulInv(*EK++);
165: t2 = -*EK++;
166: t3 = -*EK++;
167: *--p = mulInv(*EK++);
168: *--p = t3;
169: *--p = t2;
170: *--p = t1;
1.1.1.5 root 171:
1.1.1.6 root 172: for (i = 0; i < IDEAROUNDS - 1; i++) {
1.1.1.5 root 173: t1 = *EK++;
174: *--p = *EK++;
175: *--p = t1;
176:
177: t1 = mulInv(*EK++);
178: t2 = -*EK++;
179: t3 = -*EK++;
180: *--p = mulInv(*EK++);
181: *--p = t2;
1.1.1.6 root 182: *--p = t3;
1.1.1.5 root 183: *--p = t1;
1.1.1.6 root 184: }
185: t1 = *EK++;
186: *--p = *EK++;
187: *--p = t1;
188:
189: t1 = mulInv(*EK++);
190: t2 = -*EK++;
191: t3 = -*EK++;
192: *--p = mulInv(*EK++);
193: *--p = t3;
194: *--p = t2;
195: *--p = t1;
1.1.1.5 root 196: /* Copy and destroy temp copy */
1.1.1.6 root 197: memcpy(DK, temp, sizeof(temp));
198: burn(temp);
199: } /* ideaInvertKey */
1.1.1.5 root 200:
201: /*
202: * MUL(x,y) computes x = x*y, modulo 0x10001. Requires two temps,
1.1.1.7 ! root 203: * t16 and t32. x is modified, and must be a side-effect-free lvalue.
! 204: * y may be anything, but unlike x, must be strictly less than 65536
! 205: * even if low16() is #defined.
1.1.1.5 root 206: * All of these are equivalent - see which is faster on your machine
207: */
208: #ifdef SMALL_CACHE
209: #define MUL(x,y) (x = mul(low16(x),y))
1.1.1.6 root 210: #else /* !SMALL_CACHE */
1.1.1.5 root 211: #ifdef AVOID_JUMPS
212: #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \
1.1.1.7 ! root 213: t32 = (word32)x*t16 + x + t16, x = low16(t32), \
! 214: t16 = t32>>16, x = (x-t16) + (x<t16) + 1)
1.1.1.6 root 215: #else /* !AVOID_JUMPS (default) */
1.1.1.5 root 216: #define MUL(x,y) \
217: ((t16 = (y)) ? \
218: (x=low16(x)) ? \
219: t32 = (word32)x*t16, \
220: x = low16(t32), \
221: t16 = t32>>16, \
222: x = (x-t16)+(x<t16) \
223: : \
224: (x = 1-t16) \
225: : \
226: (x = 1-x))
227: #endif
228: #endif
229:
1.1.1.6 root 230: /* IDEA encryption/decryption algorithm */
1.1.1.5 root 231: /* Note that in and out can be the same buffer */
1.1.1.6 root 232: static void ideaCipher(byte const inbuf[8], byte outbuf[8],
233: word16 const *key)
1.1.1.5 root 234: {
1.1.1.6 root 235: register uint16 x1, x2, x3, x4, s2, s3;
236: word16 *in, *out;
1.1.1.5 root 237: #ifndef SMALL_CACHE
1.1.1.6 root 238: register uint16 t16; /* Temporaries needed by MUL macro */
239: register word32 t32;
1.1.1.5 root 240: #endif
1.1.1.6 root 241: int r = IDEAROUNDS;
1.1.1.5 root 242:
1.1.1.6 root 243: in = (word16 *) inbuf;
244: x1 = *in++;
245: x2 = *in++;
246: x3 = *in++;
247: x4 = *in;
1.1.1.5 root 248: #ifndef HIGHFIRST
1.1.1.6 root 249: x1 = (x1 >> 8) | (x1 << 8);
250: x2 = (x2 >> 8) | (x2 << 8);
251: x3 = (x3 >> 8) | (x3 << 8);
252: x4 = (x4 >> 8) | (x4 << 8);
1.1.1.5 root 253: #endif
1.1.1.6 root 254: do {
1.1.1.5 root 255: MUL(x1, *key++);
256: x2 += *key++;
1.1.1.6 root 257: x3 += *key++;
258: MUL(x4, *key++);
259:
260: s3 = x3;
261: x3 ^= x1;
262: MUL(x3, *key++);
263: s2 = x2;
264: x2 ^= x4;
265: x2 += x3;
266: MUL(x2, *key++);
267: x3 += x2;
268:
269: x1 ^= x2;
270: x4 ^= x3;
271:
272: x2 ^= s3;
273: x3 ^= s2;
274: } while (--r);
275: MUL(x1, *key++);
276: x3 += *key++;
277: x2 += *key++;
278: MUL(x4, *key);
1.1.1.5 root 279:
1.1.1.6 root 280: out = (word16 *) outbuf;
1.1.1.5 root 281: #ifdef HIGHFIRST
1.1.1.6 root 282: *out++ = x1;
283: *out++ = x3;
284: *out++ = x2;
285: *out = x4;
286: #else /* !HIGHFIRST */
287: x1 = low16(x1);
288: x2 = low16(x2);
289: x3 = low16(x3);
290: x4 = low16(x4);
291: *out++ = (x1 >> 8) | (x1 << 8);
292: *out++ = (x3 >> 8) | (x3 << 8);
293: *out++ = (x2 >> 8) | (x2 << 8);
294: *out = (x4 >> 8) | (x4 << 8);
1.1.1.5 root 295: #endif
1.1.1.6 root 296: } /* ideaCipher */
1.1.1.5 root 297:
298: /*-------------------------------------------------------------*/
299:
300: #ifdef TEST
301:
302: #include <stdio.h>
303: #include <time.h>
304: /*
305: * This is the number of Kbytes of test data to encrypt.
306: * It defaults to 1 MByte.
307: */
308: #ifndef BLOCKS
309: #ifndef KBYTES
310: #define KBYTES 1024
311: #endif
312: #define BLOCKS (64*KBYTES)
313: #endif
314:
1.1.1.6 root 315: int main(void)
316: { /* Test driver for IDEA cipher */
317: int i, j, k;
318: byte userkey[16];
319: word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN];
320: byte XX[8], YY[8], ZZ[8];
321: clock_t start, end;
322: long l;
323:
324: /* Make a sample user key for testing... */
325: for (i = 0; i < 16; i++)
326: userkey[i] = i + 1;
327:
328: /* Compute encryption subkeys from user key... */
329: ideaExpandKey(userkey, EK);
330: printf("\nEncryption key subblocks: ");
331: for (j = 0; j < IDEAROUNDS + 1; j++) {
332: printf("\nround %d: ", j + 1);
333: if (j < IDEAROUNDS)
334: for (i = 0; i < 6; i++)
335: printf(" %6u", EK[j * 6 + i]);
336: else
337: for (i = 0; i < 4; i++)
338: printf(" %6u", EK[j * 6 + i]);
339: }
340:
341: /* Compute decryption subkeys from encryption subkeys... */
342: ideaInvertKey(EK, DK);
343: printf("\nDecryption key subblocks: ");
344: for (j = 0; j < IDEAROUNDS + 1; j++) {
345: printf("\nround %d: ", j + 1);
346: if (j < IDEAROUNDS)
347: for (i = 0; i < 6; i++)
348: printf(" %6u", DK[j * 6 + i]);
349: else
350: for (i = 0; i < 4; i++)
351: printf(" %6u", DK[j * 6 + i]);
352: }
353:
354: /* Make a sample plaintext pattern for testing... */
355: for (k = 0; k < 8; k++)
356: XX[k] = k;
357:
358: printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS * 16, BLOCKS);
359: fflush(stdout);
360: start = clock();
361: memcpy(YY, XX, 8);
362: for (l = 0; l < BLOCKS; l++)
363: ideaCipher(YY, YY, EK); /* repeated encryption */
364: memcpy(ZZ, YY, 8);
365: for (l = 0; l < BLOCKS; l++)
366: ideaCipher(ZZ, ZZ, DK); /* repeated decryption */
367: end = clock() - start;
368: l = end / (CLOCKS_PER_SEC / 1000) + 1;
369: i = l / 1000;
370: j = l % 1000;
371: l = (16 * BLOCKS * (CLOCKS_PER_SEC / 1000)) / (end / 1000);
372: printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
373:
374: printf("\nX %3u %3u %3u %3u %3u %3u %3u %3u\n",
375: XX[0], XX[1], XX[2], XX[3], XX[4], XX[5], XX[6], XX[7]);
376: printf("\nY %3u %3u %3u %3u %3u %3u %3u %3u\n",
377: YY[0], YY[1], YY[2], YY[3], YY[4], YY[5], YY[6], YY[7]);
378: printf("\nZ %3u %3u %3u %3u %3u %3u %3u %3u\n",
379: ZZ[0], ZZ[1], ZZ[2], ZZ[3], ZZ[4], ZZ[5], ZZ[6], ZZ[7]);
380:
381: /* Now decrypted ZZ should be same as original XX */
382: for (k = 0; k < 8; k++)
383: if (XX[k] != ZZ[k]) {
384: printf("\n\07Error! Noninvertable encryption.\n");
385: exit(-1); /* error exit */
386: }
387: printf("\nNormal exit.\n");
388: return 0; /* normal exit */
389: } /* main */
1.1.1.5 root 390:
1.1.1.6 root 391: #endif /* TEST */
1.1.1.5 root 392:
393:
394: /*************************************************************************/
395:
1.1.1.6 root 396: void ideaCfbReinit(struct IdeaCfbContext *context, byte const *iv)
1.1.1.5 root 397: {
1.1.1.6 root 398: if (iv)
399: memcpy(context->iv, iv, 8);
400: else
401: fill0(context->iv, 8);
402: context->bufleft = 0;
1.1.1.5 root 403: }
404:
1.1.1.6 root 405: void ideaCfbInit(struct IdeaCfbContext *context, byte const key[16])
1.1.1.5 root 406: {
1.1.1.6 root 407: ideaExpandKey(key, context->key);
408: ideaCfbReinit(context, 0);
1.1.1.5 root 409: }
410:
1.1.1.6 root 411: void ideaCfbDestroy(struct IdeaCfbContext *context)
1.1.1.5 root 412: {
1.1.1.6 root 413: burn(*context);
1.1.1.5 root 414: }
415:
416: /*
417: * Okay, explanation time:
418: * Phil invented a unique way of doing CFB that's sensitive to semantic
419: * boundaries within the data being encrypted. One way to phrase
420: * CFB en/decryption is to say that you XOR the current 8 bytes with
421: * IDEA(previous 8 bytes of ciphertext). Normally, you repeat this
422: * at 8-byte intervals, but Phil decided to resync things on the
423: * boundaries between elements in the stream being encrypted.
424: *
425: * That is, the last 4 bytes of a 12-byte field are en/decrypted using
426: * the first 4 bytes of IDEA(previous 8 bytes of ciphertext), but then
427: * the last 4 bytes of that IDEA computation are thrown away, and the
428: * first 8 bytes of the next field are en/decrypted using
429: * IDEA(last 8 bytes of ciphertext). This is equivalent to using a
430: * shorter feedback length (if you're familiar with the general CFB
431: * technique) briefly, and doesn't weaken the cipher any (using shorter
432: * CFB lengths makes it stronger, actually), it just makes it a bit unusual.
433: *
434: * Anyway, to accomodate this behaviour, every time we do an IDEA
435: * encrpytion of 8 bytes of ciphertext to get 8 bytes of XOR mask,
436: * we remember the ciphertext. Then if we have to resync things
437: * after having processed, say, 2 bytes, we refill the iv buffer
438: * with the last 6 bytes of the old ciphertext followed by the
439: * 2 bytes of new ciphertext stored in the front of the iv buffer.
440: */
1.1.1.6 root 441: void ideaCfbSync(struct IdeaCfbContext *context)
1.1.1.5 root 442: {
1.1.1.6 root 443: int bufleft = context->bufleft;
1.1.1.5 root 444:
1.1.1.6 root 445: if (bufleft) {
446: memmove(context->iv + bufleft, context->iv, 8 - bufleft);
447: memcpy(context->iv, context->oldcipher + 8 - bufleft, bufleft);
448: context->bufleft = 0;
449: }
1.1.1.5 root 450: }
451:
452: /*
453: * Encrypt a buffer of data, using IDEA in CFB mode.
454: * There are more compact ways of writing this, but this is
455: * written for speed.
456: */
1.1.1.6 root 457: void ideaCfbEncrypt(struct IdeaCfbContext *context, byte const *src,
458: byte * dest, int count)
459: {
460: int bufleft = context->bufleft;
461: byte *bufptr = context->iv + 8 - bufleft;
462:
463: /* If there are no more bytes to encrypt that there are bytes
464: * in the buffer, XOR them in and return.
465: */
466: if (count <= bufleft) {
467: context->bufleft = bufleft - count;
468: while (count--) {
469: *dest++ = *bufptr++ ^= *src++;
470: }
471: return;
472: }
473: count -= bufleft;
474: /* Encrypt the first bufleft (0 to 7) bytes of the input by XOR
475: * with the last bufleft bytes in the iv buffer.
476: */
477: while (bufleft--) {
478: *dest++ = (*bufptr++ ^= *src++);
479: }
480: /* Encrypt middle blocks of the input by cranking the cipher,
481: * XORing 8-byte blocks, and repeating until the count
482: * is 8 or less.
483: */
484: while (count > 8) {
1.1.1.5 root 485: bufptr = context->iv;
486: memcpy(context->oldcipher, bufptr, 8);
487: ideaCipher(bufptr, bufptr, context->key);
1.1.1.6 root 488: bufleft = 8;
489: count -= 8;
490: do {
491: *dest++ = (*bufptr++ ^= *src++);
492: } while (--bufleft);
493: }
494: /* Do the last 1 to 8 bytes */
495: bufptr = context->iv;
496: memcpy(context->oldcipher, bufptr, 8);
497: ideaCipher(bufptr, bufptr, context->key);
498: context->bufleft = 8 - count;
499: do {
500: *dest++ = (*bufptr++ ^= *src++);
501: } while (--count);
1.1.1.5 root 502: }
503:
504:
505: /*
506: * Decrypt a buffer of data, using IDEA in CFB mode.
507: * There are more compact ways of writing this, but this is
508: * written for speed.
509: */
1.1.1.6 root 510: void ideaCfbDecrypt(struct IdeaCfbContext *context, byte const *src,
511: byte * dest, int count)
512: {
513: int bufleft = context->bufleft;
514: static byte *bufptr;
515: byte t;
516:
517: bufptr = context->iv + (8 - bufleft);
518: if (count <= bufleft) {
519: context->bufleft = bufleft - count;
520: while (count--) {
521: t = *bufptr;
522: *dest++ = t ^ (*bufptr++ = *src++);
523: }
524: return;
525: }
526: count -= bufleft;
527: while (bufleft--) {
528: t = *bufptr;
529: *dest++ = t ^ (*bufptr++ = *src++);
530: }
531: while (count > 8) {
1.1.1.5 root 532: bufptr = context->iv;
533: memcpy(context->oldcipher, bufptr, 8);
534: ideaCipher(bufptr, bufptr, context->key);
1.1.1.6 root 535: bufleft = 8;
536: count -= 8;
1.1.1.5 root 537: do {
1.1.1.6 root 538: t = *bufptr;
539: *dest++ = t ^ (*bufptr++ = *src++);
540: } while (--bufleft);
541: }
542: bufptr = context->iv;
543: memcpy(context->oldcipher, bufptr, 8);
544: ideaCipher(bufptr, bufptr, context->key);
545: context->bufleft = 8 - count;
546: do {
547: t = *bufptr;
548: *dest++ = t ^ (*bufptr++ = *src++);
549: } while (--count);
1.1.1.5 root 550: }
551:
552: /********************************************************************/
553:
554: /*
555: * Cryptographically strong pseudo-random-number generator.
556: * The design is from Appendix C of ANSI X9.17, "Financial
557: * Institution Key Management (Wholesale)", with IDEA
558: * substituted for the DES.
559: */
560:
561: /*
562: * Initialize a cryptographic random-number generator.
563: * key and seed should be arbitrary.
564: */
1.1.1.6 root 565: void ideaRandInit(struct IdeaRandContext *context, byte const key[16],
566: byte const seed[8])
1.1.1.5 root 567: {
1.1.1.6 root 568: int i;
1.1.1.5 root 569:
1.1.1.6 root 570: ideaExpandKey(key, context->key);
571: context->bufleft = 0;
572: memcpy(context->internalbuf, seed, 8);
1.1.1.5 root 573: }
574:
575:
576: /*
577: * Read out the RNG's state.
578: */
1.1.1.6 root 579: void ideaRandState(struct IdeaRandContext *context, byte key[16], byte seed[8])
1.1.1.5 root 580: {
1.1.1.6 root 581: int i;
1.1.1.5 root 582:
1.1.1.6 root 583: memcpy(seed, context->internalbuf, 8);
584: for (i = 0; i < 8; i++) {
585: key[2 * i] = context->key[i] >> 8;
586: key[2 * i + 1] = context->key[i];
587: }
1.1.1.5 root 588:
589: }
590:
591: /*
592: * Encrypt the RNG's state with the given CFB encryptor.
593: */
1.1.1.6 root 594: void ideaRandWash(struct IdeaRandContext *context, struct IdeaCfbContext *cfb)
1.1.1.5 root 595: {
1.1.1.6 root 596: byte keyseed[16 + 8];
597: int i;
1.1.1.5 root 598:
1.1.1.6 root 599: ideaRandState(context, keyseed, keyseed + 16);
600: ideaCfbEncrypt(cfb, keyseed, keyseed, 16 + 8);
601: ideaRandInit(context, keyseed, keyseed + 16);
1.1.1.5 root 602:
1.1.1.6 root 603: memset(keyseed, 0, 16 + 8);
1.1.1.5 root 604: }
605:
606: /*
607: * Cryptographic pseudo-random-number generator, used for generating
608: * session keys.
609: */
610: byte
611: ideaRandByte(struct IdeaRandContext *c)
612: {
1.1.1.6 root 613: int i;
1.1.1.5 root 614:
1.1.1.6 root 615: if (!c->bufleft) {
616: byte timestamp[8];
617:
618: /* Get some true-random noise to help */
619: randPoolGetBytes(timestamp, sizeof(timestamp));
620:
621: /* Compute next 8 bytes of output */
622: for (i = 0; i < 8; i++)
623: c->outbuf[i] = c->internalbuf[i] ^ timestamp[i];
624: ideaCipher(c->outbuf, c->outbuf, c->key);
625: /* Compute new seed vector */
626: for (i = 0; i < 8; i++)
627: c->internalbuf[i] = c->outbuf[i] ^ timestamp[i];
628: ideaCipher(c->internalbuf, c->internalbuf, c->key);
629: burn(timestamp);
630: c->bufleft = 8;
631: }
632: return c->outbuf[--c->bufleft];
1.1.1.5 root 633: }
634:
635: /* end of idea.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.