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