home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / utilities / cli / pgp2 / src / c / idea < prev    next >
Encoding:
Text File  |  1995-06-07  |  17.5 KB  |  653 lines

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