|
|
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 - b; ! 96: } else { ! 97: return 1 - a; ! 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, 203: * t16 and t32. x is modified, and must me a side-effect-free lvalue. 204: * y may be anything, but unlike x, must be strictly 16 bits even if 205: * low16() is #defined. 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), \ 213: t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \ 214: t16 = t32>>16, x = (x-t16) + (x<t16) ) 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.