|
|
1.1.1.5 ! root 1: /* ! 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. ! 10: * ! 11: * Extensively optimized and restructured by Colin Plumb. ! 12: * ! 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. ! 17: * ! 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%. ! 29: * ! 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. ! 38: * ! 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. ! 44: * ! 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. ! 50: * ! 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. ! 55: */ ! 56: ! 57: #include "idea.h" ! 58: #include "randpool.h" ! 59: ! 60: #ifdef IDEA32 /* Use >16-bit temporaries */ ! 61: #define low16(x) ((x) & 0xFFFF) ! 62: typedef unsigned int uint16; /* at LEAST 16 bits, maybe more */ ! 63: #else ! 64: #define low16(x) (x) /* this is only ever applied to uint16's */ ! 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: /* ! 78: * Multiplication, modulo (2**16)+1 ! 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 ! 85: mul(register uint16 a, register uint16 b) ! 86: { ! 87: register word32 p; ! 88: ! 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-b; ! 96: } else { ! 97: return 1-a; ! 98: } ! 99: } /* mul */ ! 100: #endif /* SMALL_CACHE */ ! 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 ! 108: mulInv(uint16 x) ! 109: { ! 110: uint16 t0, t1; ! 111: uint16 q, y; ! 112: ! 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 */ ! 132: ! 133: /* ! 134: * Expand a 128-bit user key to a working encryption key EK ! 135: */ ! 136: static void ! 137: ideaExpandKey(byte const *userkey, word16 *EK) ! 138: { ! 139: int i,j; ! 140: ! 141: for (j=0; j<8; j++) { ! 142: EK[j] = (userkey[0]<<8) + userkey[1]; ! 143: userkey += 2; ! 144: } ! 145: for (i=0; j < IDEAKEYLEN; j++) { ! 146: i++; ! 147: EK[i+7] = EK[i & 7] << 9 | EK[i+1 & 7] >> 7; ! 148: EK += i & 8; ! 149: i &= 7; ! 150: } ! 151: } /* ideaExpandKey */ ! 152: ! 153: /* ! 154: * Compute IDEA decryption key DK from an expanded IDEA encryption key EK ! 155: * Note that the input and output may be the same. Thus, the key is ! 156: * inverted into an internal buffer, and then copied to the output. ! 157: */ ! 158: static void ! 159: ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN]) ! 160: { ! 161: int i; ! 162: uint16 t1, t2, t3; ! 163: word16 temp[IDEAKEYLEN]; ! 164: word16 *p = temp + IDEAKEYLEN; ! 165: ! 166: t1 = mulInv(*EK++); ! 167: t2 = -*EK++; ! 168: t3 = -*EK++; ! 169: *--p = mulInv(*EK++); ! 170: *--p = t3; ! 171: *--p = t2; ! 172: *--p = t1; ! 173: ! 174: for (i = 0; i < IDEAROUNDS-1; i++) { ! 175: t1 = *EK++; ! 176: *--p = *EK++; ! 177: *--p = t1; ! 178: ! 179: t1 = mulInv(*EK++); ! 180: t2 = -*EK++; ! 181: t3 = -*EK++; ! 182: *--p = mulInv(*EK++); ! 183: *--p = t2; ! 184: *--p = t3; ! 185: *--p = t1; ! 186: } ! 187: t1 = *EK++; ! 188: *--p = *EK++; ! 189: *--p = t1; ! 190: ! 191: t1 = mulInv(*EK++); ! 192: t2 = -*EK++; ! 193: t3 = -*EK++; ! 194: *--p = mulInv(*EK++); ! 195: *--p = t3; ! 196: *--p = t2; ! 197: *--p = t1; ! 198: /* Copy and destroy temp copy */ ! 199: memcpy(DK, temp, sizeof(temp)); ! 200: burn(temp); ! 201: } /* ideaInvertKey */ ! 202: ! 203: /* ! 204: * MUL(x,y) computes x = x*y, modulo 0x10001. Requires two temps, ! 205: * t16 and t32. x is modified, and must me a side-effect-free lvalue. ! 206: * y may be anything, but unlike x, must be strictly 16 bits even if ! 207: * low16() is #defined. ! 208: * All of these are equivalent - see which is faster on your machine ! 209: */ ! 210: #ifdef SMALL_CACHE ! 211: #define MUL(x,y) (x = mul(low16(x),y)) ! 212: #else /* !SMALL_CACHE */ ! 213: #ifdef AVOID_JUMPS ! 214: #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \ ! 215: t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \ ! 216: t16 = t32>>16, x = (x-t16) + (x<t16) ) ! 217: #else /* !AVOID_JUMPS (default) */ ! 218: #define MUL(x,y) \ ! 219: ((t16 = (y)) ? \ ! 220: (x=low16(x)) ? \ ! 221: t32 = (word32)x*t16, \ ! 222: x = low16(t32), \ ! 223: t16 = t32>>16, \ ! 224: x = (x-t16)+(x<t16) \ ! 225: : \ ! 226: (x = 1-t16) \ ! 227: : \ ! 228: (x = 1-x)) ! 229: #endif ! 230: #endif ! 231: ! 232: /* IDEA encryption/decryption algorithm */ ! 233: /* Note that in and out can be the same buffer */ ! 234: static void ! 235: ideaCipher(byte const (inbuf[8]), byte (outbuf[8]), word16 const *key) ! 236: { ! 237: register uint16 x1, x2, x3, x4, s2, s3; ! 238: word16 *in, *out; ! 239: #ifndef SMALL_CACHE ! 240: register uint16 t16; /* Temporaries needed by MUL macro */ ! 241: register word32 t32; ! 242: #endif ! 243: int r = IDEAROUNDS; ! 244: ! 245: in = (word16 *)inbuf; ! 246: x1 = *in++; x2 = *in++; ! 247: x3 = *in++; x4 = *in; ! 248: #ifndef HIGHFIRST ! 249: x1 = (x1>>8) | (x1<<8); ! 250: x2 = (x2>>8) | (x2<<8); ! 251: x3 = (x3>>8) | (x3<<8); ! 252: x4 = (x4>>8) | (x4<<8); ! 253: #endif ! 254: do { ! 255: MUL(x1,*key++); ! 256: x2 += *key++; ! 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; x4 ^= x3; ! 270: ! 271: x2 ^= s3; x3 ^= s2; ! 272: } while (--r); ! 273: MUL(x1, *key++); ! 274: x3 += *key++; ! 275: x2 += *key++; ! 276: MUL(x4, *key); ! 277: ! 278: out = (word16 *)outbuf; ! 279: #ifdef HIGHFIRST ! 280: *out++ = x1; ! 281: *out++ = x3; ! 282: *out++ = x2; ! 283: *out = x4; ! 284: #else /* !HIGHFIRST */ ! 285: x1 = low16(x1); ! 286: x2 = low16(x2); ! 287: x3 = low16(x3); ! 288: x4 = low16(x4); ! 289: *out++ = (x1>>8) | (x1<<8); ! 290: *out++ = (x3>>8) | (x3<<8); ! 291: *out++ = (x2>>8) | (x2<<8); ! 292: *out = (x4>>8) | (x4<<8); ! 293: #endif ! 294: } /* ideaCipher */ ! 295: ! 296: /*-------------------------------------------------------------*/ ! 297: ! 298: #ifdef TEST ! 299: ! 300: #include <stdio.h> ! 301: #include <time.h> ! 302: /* ! 303: * This is the number of Kbytes of test data to encrypt. ! 304: * It defaults to 1 MByte. ! 305: */ ! 306: #ifndef BLOCKS ! 307: #ifndef KBYTES ! 308: #define KBYTES 1024 ! 309: #endif ! 310: #define BLOCKS (64*KBYTES) ! 311: #endif ! 312: ! 313: int ! 314: main(void) ! 315: { /* Test driver for IDEA cipher */ ! 316: int i, j, k; ! 317: byte userkey[16]; ! 318: word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN]; ! 319: byte XX[8], YY[8], ZZ[8]; ! 320: clock_t start, end; ! 321: long l; ! 322: ! 323: /* Make a sample user key for testing... */ ! 324: for(i=0; i<16; i++) ! 325: userkey[i] = i+1; ! 326: ! 327: /* Compute encryption subkeys from user key... */ ! 328: ideaExpandKey(userkey, EK); ! 329: printf("\nEncryption key subblocks: "); ! 330: for (j=0; j<IDEAROUNDS+1; j++) { ! 331: printf("\nround %d: ", j+1); ! 332: if (j < IDEAROUNDS) ! 333: for(i=0; i<6; i++) ! 334: printf(" %6u", EK[j*6+i]); ! 335: else ! 336: for(i=0; i<4; i++) ! 337: printf(" %6u", EK[j*6+i]); ! 338: } ! 339: ! 340: /* Compute decryption subkeys from encryption subkeys... */ ! 341: ideaInvertKey(EK, DK); ! 342: printf("\nDecryption key subblocks: "); ! 343: for (j=0; j<IDEAROUNDS+1; j++) { ! 344: printf("\nround %d: ", j+1); ! 345: if (j < IDEAROUNDS) ! 346: for(i=0; i<6; i++) ! 347: printf(" %6u", DK[j*6+i]); ! 348: else ! 349: for(i=0; i<4; i++) ! 350: printf(" %6u", DK[j*6+i]); ! 351: } ! 352: ! 353: /* Make a sample plaintext pattern for testing... */ ! 354: for (k=0; k<8; k++) ! 355: XX[k] = k; ! 356: ! 357: printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS*16, BLOCKS); ! 358: fflush(stdout); ! 359: start = clock(); ! 360: memcpy(YY, XX, 8); ! 361: for (l = 0; l < BLOCKS; l++) ! 362: ideaCipher(YY, YY, EK); /* repeated encryption */ ! 363: memcpy(ZZ, YY, 8); ! 364: for (l = 0; l < BLOCKS; l++) ! 365: ideaCipher(ZZ, ZZ, DK); /* repeated decryption */ ! 366: end = clock() - start; ! 367: l = end / (CLOCKS_PER_SEC/1000) + 1; ! 368: i = l/1000; ! 369: j = l%1000; ! 370: l = (16 * BLOCKS * (CLOCKS_PER_SEC/1000)) / (end/1000); ! 371: printf("%d.%03d seconds = %ld bytes per second\n", i, j, l); ! 372: ! 373: printf("\nX %3u %3u %3u %3u %3u %3u %3u %3u\n", ! 374: XX[0], XX[1], XX[2], XX[3], XX[4], XX[5], XX[6], XX[7]); ! 375: printf("\nY %3u %3u %3u %3u %3u %3u %3u %3u\n", ! 376: YY[0], YY[1], YY[2], YY[3], YY[4], YY[5], YY[6], YY[7]); ! 377: printf("\nZ %3u %3u %3u %3u %3u %3u %3u %3u\n", ! 378: ZZ[0], ZZ[1], ZZ[2], ZZ[3], ZZ[4], ZZ[5], ZZ[6], ZZ[7]); ! 379: ! 380: /* Now decrypted ZZ should be same as original XX */ ! 381: for (k=0; k<8; k++) ! 382: if (XX[k] != ZZ[k]) { ! 383: printf("\n\07Error! Noninvertable encryption.\n"); ! 384: exit(-1); /* error exit */ ! 385: } ! 386: printf("\nNormal exit.\n"); ! 387: return 0; /* normal exit */ ! 388: } /* main */ ! 389: ! 390: #endif /* TEST */ ! 391: ! 392: ! 393: /*************************************************************************/ ! 394: ! 395: void ! 396: ideaCfbReinit(struct IdeaCfbContext *context, byte const *iv) ! 397: { ! 398: if (iv) ! 399: memcpy(context->iv, iv, 8); ! 400: else ! 401: fill0(context->iv, 8); ! 402: context->bufleft = 0; ! 403: } ! 404: ! 405: void ! 406: ideaCfbInit(struct IdeaCfbContext *context, byte const (key[16])) ! 407: { ! 408: ideaExpandKey(key, context->key); ! 409: ideaCfbReinit(context,0); ! 410: } ! 411: ! 412: void ! 413: ideaCfbDestroy(struct IdeaCfbContext *context) ! 414: { ! 415: burn(*context); ! 416: } ! 417: ! 418: /* ! 419: * Okay, explanation time: ! 420: * Phil invented a unique way of doing CFB that's sensitive to semantic ! 421: * boundaries within the data being encrypted. One way to phrase ! 422: * CFB en/decryption is to say that you XOR the current 8 bytes with ! 423: * IDEA(previous 8 bytes of ciphertext). Normally, you repeat this ! 424: * at 8-byte intervals, but Phil decided to resync things on the ! 425: * boundaries between elements in the stream being encrypted. ! 426: * ! 427: * That is, the last 4 bytes of a 12-byte field are en/decrypted using ! 428: * the first 4 bytes of IDEA(previous 8 bytes of ciphertext), but then ! 429: * the last 4 bytes of that IDEA computation are thrown away, and the ! 430: * first 8 bytes of the next field are en/decrypted using ! 431: * IDEA(last 8 bytes of ciphertext). This is equivalent to using a ! 432: * shorter feedback length (if you're familiar with the general CFB ! 433: * technique) briefly, and doesn't weaken the cipher any (using shorter ! 434: * CFB lengths makes it stronger, actually), it just makes it a bit unusual. ! 435: * ! 436: * Anyway, to accomodate this behaviour, every time we do an IDEA ! 437: * encrpytion of 8 bytes of ciphertext to get 8 bytes of XOR mask, ! 438: * we remember the ciphertext. Then if we have to resync things ! 439: * after having processed, say, 2 bytes, we refill the iv buffer ! 440: * with the last 6 bytes of the old ciphertext followed by the ! 441: * 2 bytes of new ciphertext stored in the front of the iv buffer. ! 442: */ ! 443: void ! 444: ideaCfbSync(struct IdeaCfbContext *context) ! 445: { ! 446: int bufleft = context->bufleft; ! 447: ! 448: if (bufleft) { ! 449: memmove(context->iv+bufleft, context->iv, 8-bufleft); ! 450: memcpy(context->iv, context->oldcipher+8-bufleft, bufleft); ! 451: context->bufleft = 0; ! 452: } ! 453: } ! 454: ! 455: /* ! 456: * Encrypt a buffer of data, using IDEA in CFB mode. ! 457: * There are more compact ways of writing this, but this is ! 458: * written for speed. ! 459: */ ! 460: void ! 461: ideaCfbEncrypt(struct IdeaCfbContext *context, byte const *src, ! 462: byte *dest, int count) ! 463: { ! 464: int bufleft = context->bufleft; ! 465: byte *bufptr = context->iv + 8-bufleft; ! 466: ! 467: /* If there are no more bytes to encrypt that there are bytes ! 468: * in the buffer, XOR them in and return. ! 469: */ ! 470: if (count <= bufleft) { ! 471: context->bufleft = bufleft - count; ! 472: while (count--) { ! 473: *dest++ = *bufptr++ ^= *src++; ! 474: } ! 475: return; ! 476: } ! 477: count -= bufleft; ! 478: /* Encrypt the first bufleft (0 to 7) bytes of the input by XOR ! 479: * with the last bufleft bytes in the iv buffer. ! 480: */ ! 481: while (bufleft--) { ! 482: *dest++ = (*bufptr++ ^= *src++); ! 483: } ! 484: /* Encrypt middle blocks of the input by cranking the cipher, ! 485: * XORing 8-byte blocks, and repeating until the count ! 486: * is 8 or less. ! 487: */ ! 488: while (count > 8) { ! 489: bufptr = context->iv; ! 490: memcpy(context->oldcipher, bufptr, 8); ! 491: ideaCipher(bufptr, bufptr, context->key); ! 492: bufleft = 8; ! 493: count -= 8; ! 494: do { ! 495: *dest++ = (*bufptr++ ^= *src++); ! 496: } while (--bufleft); ! 497: } ! 498: /* Do the last 1 to 8 bytes */ ! 499: bufptr = context->iv; ! 500: memcpy(context->oldcipher, bufptr, 8); ! 501: ideaCipher(bufptr, bufptr, context->key); ! 502: context->bufleft = 8-count; ! 503: do { ! 504: *dest++ = (*bufptr++ ^= *src++); ! 505: } while (--count); ! 506: } ! 507: ! 508: ! 509: /* ! 510: * Decrypt a buffer of data, using IDEA in CFB mode. ! 511: * There are more compact ways of writing this, but this is ! 512: * written for speed. ! 513: */ ! 514: void ! 515: ideaCfbDecrypt(struct IdeaCfbContext *context, byte const *src, ! 516: byte *dest, int count) ! 517: { ! 518: int bufleft = context->bufleft; ! 519: static byte *bufptr; ! 520: byte t; ! 521: ! 522: bufptr = context->iv + (8-bufleft); ! 523: if (count <= bufleft) { ! 524: context->bufleft = bufleft - count; ! 525: while (count--) { ! 526: t = *bufptr; ! 527: *dest++ = t ^ (*bufptr++ = *src++); ! 528: } ! 529: return; ! 530: } ! 531: count -= bufleft; ! 532: while (bufleft--) { ! 533: t = *bufptr; ! 534: *dest++ = t ^ (*bufptr++ = *src++); ! 535: } ! 536: while (count > 8) { ! 537: bufptr = context->iv; ! 538: memcpy(context->oldcipher, bufptr, 8); ! 539: ideaCipher(bufptr, bufptr, context->key); ! 540: bufleft = 8; ! 541: count -= 8; ! 542: do { ! 543: t = *bufptr; ! 544: *dest++ = t ^ (*bufptr++ = *src++); ! 545: } while (--bufleft); ! 546: } ! 547: bufptr = context->iv; ! 548: memcpy(context->oldcipher, bufptr, 8); ! 549: ideaCipher(bufptr, bufptr, context->key); ! 550: context->bufleft = 8-count; ! 551: do { ! 552: t = *bufptr; ! 553: *dest++ = t ^ (*bufptr++ = *src++); ! 554: } while (--count); ! 555: } ! 556: ! 557: /********************************************************************/ ! 558: ! 559: /* ! 560: * Cryptographically strong pseudo-random-number generator. ! 561: * The design is from Appendix C of ANSI X9.17, "Financial ! 562: * Institution Key Management (Wholesale)", with IDEA ! 563: * substituted for the DES. ! 564: */ ! 565: ! 566: /* ! 567: * Initialize a cryptographic random-number generator. ! 568: * key and seed should be arbitrary. ! 569: */ ! 570: void ! 571: ideaRandInit(struct IdeaRandContext *context, byte const (key[16]), ! 572: byte const (seed[8])) ! 573: { ! 574: int i; ! 575: ! 576: ideaExpandKey(key, context->key); ! 577: context->bufleft = 0; ! 578: memcpy(context->internalbuf, seed, 8); ! 579: } ! 580: ! 581: ! 582: /* ! 583: * Read out the RNG's state. ! 584: */ ! 585: void ! 586: ideaRandState(struct IdeaRandContext *context, byte key[16], byte seed[8]) ! 587: { ! 588: int i; ! 589: ! 590: memcpy(seed, context->internalbuf, 8); ! 591: for (i = 0; i < 8; i++) { ! 592: key[2*i] = context->key[i] >> 8; ! 593: key[2*i+1] = context->key[i]; ! 594: } ! 595: ! 596: } ! 597: ! 598: /* ! 599: * Encrypt the RNG's state with the given CFB encryptor. ! 600: */ ! 601: void ! 602: ideaRandWash(struct IdeaRandContext *context, struct IdeaCfbContext *cfb) ! 603: { ! 604: byte keyseed[16+8]; ! 605: int i; ! 606: ! 607: ideaRandState(context, keyseed, keyseed+16); ! 608: ideaCfbEncrypt(cfb, keyseed, keyseed, 16+8); ! 609: ideaRandInit(context, keyseed, keyseed+16); ! 610: ! 611: memset(keyseed, 0, 16+8); ! 612: } ! 613: ! 614: /* ! 615: * Cryptographic pseudo-random-number generator, used for generating ! 616: * session keys. ! 617: */ ! 618: byte ! 619: ideaRandByte(struct IdeaRandContext *c) ! 620: { ! 621: int i; ! 622: ! 623: if (!c->bufleft) { ! 624: byte timestamp[8]; ! 625: ! 626: /* Get some true-random noise to help */ ! 627: randPoolGetBytes(timestamp, sizeof(timestamp)); ! 628: ! 629: /* Compute next 8 bytes of output */ ! 630: for (i=0; i<8; i++) ! 631: c->outbuf[i] = c->internalbuf[i] ^ timestamp[i]; ! 632: ideaCipher(c->outbuf, c->outbuf, c->key); ! 633: /* Compute new seed vector */ ! 634: for (i=0; i<8; i++) ! 635: c->internalbuf[i] = c->outbuf[i] ^ timestamp[i]; ! 636: ideaCipher(c->internalbuf, c->internalbuf, c->key); ! 637: burn(timestamp); ! 638: c->bufleft = 8; ! 639: } ! 640: return c->outbuf[--c->bufleft]; ! 641: } ! 642: ! 643: /* end of idea.c */ ! 644:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.