home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / h / hpack78s.zip / keycvt / idea.c next >
C/C++ Source or Header  |  1992-11-28  |  10KB  |  319 lines

  1. /*    idea.c - C source code for IDEA block cipher.
  2.     IDEA (International Data Encryption Algorithm), formerly known as
  3.     IPES (Improved Proposed Encryption Standard).
  4.     Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
  5.     This implementation modified and derived from original C code
  6.     developed by Xuejia Lai.  Last modified 8 July 92.
  7.  
  8.     Zero-based indexing added, names changed from IPES to IDEA.
  9.     CFB functions added.  Random number routines added.
  10.  
  11.     The IDEA(tm) block cipher is covered by a patent held by ETH and a
  12.     Swiss company called Ascom-Tech AG.  The Swiss patent number is
  13.     PCT/CH91/00117.  International patents are pending. IDEA(tm) is a
  14.     trademark of Ascom-Tech AG.  There is no license fee required for
  15.     noncommercial use.  Commercial users may obtain licensing details
  16.     from Dieter Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502
  17.     Solothurn, Switzerland, Tel +41 65 242885, Fax +41 65 235761.
  18.  
  19.     The IDEA block cipher uses a 64-bit block size, and a 128-bit key 
  20.     size.  It breaks the 64-bit cipher block into four 16-bit words
  21.     because all of the primitive inner operations are done with 16-bit 
  22.     arithmetic.  It likewise breaks the 128-bit cipher key into eight
  23.     16-bit words.
  24.  
  25.     For further information on the IDEA cipher, see these papers:
  26.     1)    Xuejia Lai, "Detailed Description and a Software Implementation of
  27.         the IPES Cipher", Institute for Signal and Information
  28.         Processing, ETH-Zentrum, Zurich, Switzerland, 1991
  29.     2)    Xuejia Lai, James L. Massey, Sean Murphy, "Markov Ciphers and
  30.         Differential Cryptanalysis", Advances in Cryptology- EUROCRYPT'91
  31.  
  32.     This code assumes that each pair of 8-bit bytes comprising a 16-bit
  33.     word in the key and in the cipher block are externally represented
  34.     with the Most Significant Byte (MSB) first, regardless of the
  35.     internal native byte order of the target CPU */
  36.  
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include "md5.h"
  40.  
  41. /* Defines to convert from HPACK -> PGP standard defines/typedefs */
  42.  
  43. #define word32        LONG
  44. #define word16        WORD
  45. #define boolean        BOOLEAN
  46. #define byte        BYTE
  47. #define byteptr        BYTE *
  48.  
  49. #ifdef BIG_ENDIAN
  50.   #define HIGHFIRST
  51. #endif /* BIG_ENDIAN */
  52.  
  53. #define IDEABLOCKSIZE    8
  54.  
  55. /* Not everything has a min() macro */
  56.  
  57. #ifndef min
  58.   #define min(a,b)    ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )    /* Lithp! */
  59. #endif /* !min */
  60.  
  61. /* #define lower16(x) ((word16)((x) & mask16)) */ /* unoptimized version */
  62. #define lower16(x)   ((word16)(x))    /* optimized version */
  63.  
  64. #define maxim        0x10001L
  65. #define fuyi         0x10000L    /* Why did Lai pick a name like this? */
  66. #define mask16       ((word16) 0xffff)
  67. #define ROUNDS       8        /* Don't change this value, should be 8 */
  68.  
  69. static void en_key_idea(word16 userkey[8], word16 Z[6][ROUNDS+1]);
  70. static void cipher_idea(word16 inblock[4], word16 outblock[4],
  71.          word16 Z[6][ROUNDS+1]);
  72.  
  73. /*    Multiplication, modulo (2**16)+1 */
  74. static word16 mul(register word16 a, register word16 b)
  75. {
  76.     register word32 q;
  77.     register long int p;
  78.     if (a==0)
  79.         p = maxim-b;
  80.     else 
  81.         if (b==0)
  82.             p = maxim-a;
  83.         else
  84.         {    q = (word32)a * (word32)b; 
  85.             p = (q & mask16) - (q>>16);
  86.             if (p<=0) 
  87.                 p = p+maxim;
  88.         }
  89.     return (lower16(p));
  90. }        /* mul */
  91.  
  92. /*    Compute IDEA encryption subkeys Z */
  93. static void en_key_idea(word16 userkey[8], word16 Z[6][ROUNDS+1])
  94. {
  95.     word16 S[54];
  96.     int i,j,r;
  97.     /*   shifts   */
  98.     for (i = 0; i<8; i++)
  99.         S[i] = userkey[i];
  100.     for (i = 8; i<54; i++)
  101.     {    if ((i+2)%8 == 0)  /* for S[14],S[22],...  */  
  102.             S[i] = lower16((S[i-7] << 9) ^ (S[i-14] >> 7)); 
  103.         else
  104.             if ((i+1)%8 == 0)  /* for S[15],S[23],...   */
  105.             S[i] = lower16((S[i-15] << 9) ^ (S[i-14] >> 7));
  106.         else
  107.             S[i] = lower16((S[i-7] << 9) ^ (S[i-6] >> 7));
  108.     }
  109.     /* get subkeys */
  110.     for (r=0; r<ROUNDS+1; r++)
  111.         for (j=0; j<6; j++)
  112.             Z[j][r] = S[6*r + j];
  113.  
  114.     /* clear sensitive key data from memory... */
  115.     for (i=0; i<54; i++) S[i] = 0;
  116. }        /* en_key_idea */
  117.  
  118. /*    IDEA encryption/decryption algorithm */
  119. static void cipher_idea(word16 inblock[4], word16 outblock[4],
  120.          register word16 Z[6][ROUNDS+1])
  121. {    /* Note that inblock and outblock can be the same buffer */
  122.     int r;
  123.     register word16 x1, x2, x3, x4, kk, t1, t2, a;
  124.     x1=inblock[0];
  125.     x2=inblock[1];
  126.     x3=inblock[2];
  127.     x4=inblock[3];
  128.     for (r=0; r<ROUNDS; r++)
  129.     {    x1 = mul(x1, Z[0][r]);
  130.         x4 = mul(x4, Z[3][r]);
  131.         x2 = lower16(x2 + Z[1][r]);
  132.         x3 = lower16(x3 + Z[2][r]);
  133.         kk = mul(Z[4][r], (x1^x3));
  134.         t1 = mul(Z[5][r], lower16(kk + (x2^x4)) );
  135.         t2 = lower16(kk + t1);
  136.         x1 = x1^t1;
  137.         x4 = x4^t2;
  138.         a  = x2^t2;
  139.         x2 = x3^t1;
  140.         x3 = a;
  141.     }
  142.     outblock[0] = mul(x1, Z[0][ROUNDS]);
  143.     outblock[3] = mul(x4, Z[3][ROUNDS]);
  144.     outblock[1] = lower16(x3 + Z[1][ROUNDS]);
  145.     outblock[2] = lower16(x2 + Z[2][ROUNDS]);
  146. }        /* cipher_idea */
  147.  
  148. /*************************************************************************/
  149.  
  150.  
  151. #define byteglue(lo,hi) ((((word16) hi) << 8) + (word16) lo)
  152.  
  153. /*
  154. **    xorbuf - change buffer via xor with random mask block
  155. **    Used for Cipher Feedback (CFB) or Cipher Block Chaining
  156. **    (CBC) modes of encryption.
  157. **    Can be applied for any block encryption algorithm,
  158. **    with any block size, such as the DES or the IDEA cipher.
  159. */
  160. static void xorbuf(register byteptr buf, register byteptr mask, register int count)
  161. /*    count must be > 0 */
  162. {    if (count) 
  163.         do
  164.             *buf++ ^= *mask++;
  165.         while (--count);
  166. }    /* xorbuf */
  167.  
  168.  
  169. /*
  170. **    cfbshift - shift bytes into IV for CFB input
  171. **    Used only for Cipher Feedback (CFB) mode of encryption.
  172. **    Can be applied for any block encryption algorithm with any
  173. **    block size, such as the DES or the IDEA cipher.
  174. */
  175. static void cfbshift(register byteptr iv, register byteptr buf, 
  176.         register int count, int blocksize)
  177. /*     iv is the initialization vector.
  178.     buf is the buffer pointer.
  179.     count is the number of bytes to shift in...must be > 0.
  180.     blocksize is 8 bytes for DES or IDEA ciphers.
  181. */
  182. {    int retained;
  183.     if (count)
  184.     {    retained = blocksize-count;    /* number bytes in iv to retain */
  185.         /* left-shift retained bytes of IV over by count bytes to make room */
  186.         while (retained--)
  187.         {    *iv = *(iv+count);
  188.             iv++;
  189.         }
  190.         /* now copy count bytes from buf to shifted tail of IV */
  191.         do    *iv++ = *buf++;
  192.         while (--count);
  193.     }
  194. }    /* cfbshift */
  195.  
  196. /* Key schedules for IDEA encryption and decryption */
  197. static word16 Z[6][ROUNDS+1];
  198. static word16 *iv_idea;        /* pointer to IV for CFB or CBC */
  199. static boolean cfb_dc_idea; /* TRUE iff CFB decrypting */
  200.  
  201. /* initkey_idea initializes IDEA for ECB mode operations */
  202. void initkey_idea(byte key[16])
  203. {
  204.     word16 userkey[8];    /* IDEA key is 16 bytes long */
  205.     int i;
  206.     /* Assume each pair of bytes comprising a word is ordered MSB-first. */
  207.     for (i=0; i<8; i++)
  208.     {    userkey[i] = byteglue(*(key+1),*key);
  209.         key++; key++;
  210.     }
  211.     en_key_idea(userkey,Z);
  212.     for (i=0; i<8; i++)    /* Erase dangerous traces */
  213.         userkey[i] = 0;
  214. }    /* initkey_idea */
  215.  
  216.  
  217. /*    Run a 64-bit block thru IDEA in ECB (Electronic Code Book) mode,
  218.     using the currently selected key schedule.
  219. */
  220. void idea_ecb(word16 *inbuf, word16 *outbuf)
  221. {
  222.     /* Assume each pair of bytes comprising a word is ordered MSB-first. */
  223. #ifndef HIGHFIRST    /* If this is a least-significant-byte-first CPU */
  224.     /* Invert the byte order for each 16-bit word for internal use. */
  225.     union {
  226.         word16 w[4];
  227.         byte b[8];
  228.     } inbuf2, outbuf2;
  229.     register byte *p;
  230.     p = (byte *) inbuf;
  231.     inbuf2.b[1] = *p++;
  232.     inbuf2.b[0] = *p++;
  233.     inbuf2.b[3] = *p++;
  234.     inbuf2.b[2] = *p++;
  235.     inbuf2.b[5] = *p++;
  236.     inbuf2.b[4] = *p++;
  237.     inbuf2.b[7] = *p++;
  238.     inbuf2.b[6] = *p++;
  239.     cipher_idea(inbuf2.w,outbuf2.w,Z);
  240.     /* Now invert the byte order for each 16-bit word for external use. */
  241.     p = (byte *) outbuf;
  242.     *p++ = outbuf2.b[1];
  243.     *p++ = outbuf2.b[0];
  244.     *p++ = outbuf2.b[3];
  245.     *p++ = outbuf2.b[2];
  246.     *p++ = outbuf2.b[5];
  247.     *p++ = outbuf2.b[4];
  248.     *p++ = outbuf2.b[7];
  249.     *p++ = outbuf2.b[6];
  250. #else    /* HIGHFIRST */
  251.     /* Byte order for internal and external representations is the same. */
  252.     cipher_idea(inbuf,outbuf,Z);
  253. #endif    /* HIGHFIRST */
  254. }    /* idea_ecb */
  255.  
  256.  
  257. /*
  258. **    initcfb - Initializes the IDEA key schedule tables via key,
  259. **    and initializes the Cipher Feedback mode IV.
  260. **    References context variables cfb_dc_idea and iv_idea.
  261. */
  262. void initcfb_idea(word16 iv0[4], byte key[16], boolean decryp)
  263. /*     iv0 is copied to global iv_idea, buffer will be destroyed by ideacfb.
  264.     key is pointer to key buffer.
  265.     decryp is TRUE if decrypting, FALSE if encrypting.
  266. */
  267. {    iv_idea = iv0;
  268.     cfb_dc_idea = decryp;
  269.     initkey_idea(key);
  270. } /* initcfb_idea */
  271.  
  272.  
  273. /*
  274. **    ideacfb - encipher a buffer with IDEA enciphering algorithm,
  275. **        using Cipher Feedback (CFB) mode.
  276. **
  277. **    Assumes initcfb_idea has already been called.
  278. **    References context variables cfb_dc_idea and iv_idea.
  279. */
  280. void ideacfb(byteptr buf, int count)
  281. /*    buf is input, output buffer, may be more than 1 block.
  282.     count is byte count of buffer.  May be > IDEABLOCKSIZE.
  283. */
  284. {    int chunksize;    /* smaller of count, IDEABLOCKSIZE */
  285.     word16 temp[IDEABLOCKSIZE/2];
  286.  
  287.     while ((chunksize = min(count,IDEABLOCKSIZE)) > 0)
  288.     {
  289.         idea_ecb(iv_idea,temp);  /* encrypt iv_idea, making temp. */
  290.  
  291.         if (cfb_dc_idea)    /* buf is ciphertext */
  292.             /* shift in ciphertext to IV... */
  293.             cfbshift((byte *)iv_idea,buf,chunksize,IDEABLOCKSIZE);
  294.  
  295.         /* convert buf via xor */
  296.         xorbuf(buf,(byte *)temp,chunksize); /* buf now has enciphered output */
  297.  
  298.         if (!cfb_dc_idea)    /* buf was plaintext, is now ciphertext */
  299.             /* shift in ciphertext to IV... */
  300.             cfbshift((byte *)iv_idea,buf,chunksize,IDEABLOCKSIZE);
  301.  
  302.         count -= chunksize;
  303.         buf += chunksize;
  304.     }
  305. } /* ideacfb */
  306.  
  307. /*
  308.     close_idea function erases all the key schedule information when
  309.     we are all done with a set of operations for a particular IDEA key
  310.     context.  This is to prevent any sensitive data from being left
  311.     around in memory.
  312. */
  313. void close_idea(void)    /* erase current key schedule tables */
  314. {    short r,j;
  315.     for (r=0; r<ROUNDS+1; r++)
  316.         for (j=0; j<6; j++)
  317.             Z[j][r] = 0;
  318. }    /* close_idea() */
  319.