home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Security / Security.zip / idea-v11.zip / idea_cmd.c < prev    next >
C/C++ Source or Header  |  1994-09-29  |  31KB  |  932 lines

  1. /******************************************************************************/
  2. /*                                                                            */
  3. /* I N T E R N A T I O N A L  D A T A  E N C R Y P T I O N  A L G O R I T H M */
  4. /*                                                                            */
  5. /*                     A S   A   U S E R   C O M M A N D                      */
  6. /*                                                                            */
  7. /******************************************************************************/
  8. /* Author:       Richard De Moliner (demoliner@isi.ee.ethz.ch)                */
  9. /*               Signal and Information Processing Laboratory                 */
  10. /*               Swiss Federal Institute of Technology                        */
  11. /*               CH-8092 Zuerich, Switzerland                                 */
  12. /* Created:      April 23, 1992                                               */
  13. /* Changes:      November 16, 1993 (support of ANSI-C and C++)                */
  14. /* System:       SUN SPARCstation, SUN acc ANSI-C-Compiler, SUN-OS 4.1.3      */
  15. /******************************************************************************/
  16.  
  17. #ifdef RASTERFILE
  18. #include <rasterfile.h>
  19. #endif
  20.  
  21. #ifdef TIME
  22. #include <time.h>
  23. #ifndef CLK_TCK
  24. #define CLK_TCK        1000000
  25. #endif
  26. #endif
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include "idea.h"
  32.  
  33. #define TRUE                 1 /* boolean constant for true                   */
  34. #define FALSE                0 /* boolean constant for false                  */
  35. #define nofTestData     163840 /* number of blocks encrypted in time test     */
  36.  
  37. #define nomode               0 /* no mode is specified                        */
  38. #define ecb                  1 /* electronic code book mode                   */
  39. #define cbc                  2 /* cipher block chaining mode                  */
  40. #define cfb                  3 /* ciphertext feedback mode                    */
  41. #define ofb                  4 /* output feedback mode                        */
  42. #define tan                  5 /* tandem DM-scheme for hashing                */
  43. #define abr                  6 /* abreast DM-scheme for hashing               */
  44. #define eol              0x100 /* end of line character                       */
  45. #define colon            0x101 /* character ':'                               */
  46. #define error            0x102 /* unknown character                           */
  47. #define maxInterleave     1024 /* maximal interleave factor + 1               */
  48. #define nofChar ('~' - '!' +1) /* number of different printable characters    */
  49. #define maxBufLen (Idea_dataSize * 1024) /* size of input and output buffer   */
  50.  
  51. Idea_UserKey userKey;          /* user selected 128 bit key                   */
  52. Idea_Key key;                  /* expanded key with 832 bits                  */
  53. Idea_Data state[maxInterleave];/* state informations for interleaving modes   */
  54. Idea_Data hashLow;             /* lower 64 bits of hash value                 */
  55. Idea_Data hashHigh;            /* higher 64 bits of hash value                */
  56.  
  57. u_int32 inputLen    = 0;       /* current number of bytes read from 'inFile'  */
  58. int interleave      = 0;       /* current interleave factor                   */
  59. int time_0          = 0;       /* time for interleaving modes                 */
  60. int time_N          = 0;       /* time-interleave for interleaving modes      */
  61. int mode            = nomode;  /* current mode                                */
  62.  
  63. int optEncrypt      = FALSE;   /* encrypt option 'e'                          */
  64. int optDecrypt      = FALSE;   /* decrypt option 'd'                          */
  65. int optHash         = FALSE;   /* hash option 'h'                             */
  66. int optCopyHash     = FALSE;   /* copy and hash option 'H'                    */
  67. int optKeyHexString = FALSE;   /* key as hex-string option 'K'                */
  68. int optKeyString    = FALSE;   /* key as string option 'k'                    */
  69. int optRas          = FALSE;   /* raster file option 'r'                      */
  70. int optTime         = FALSE;   /* measure time option 'T'                     */
  71.  
  72. int inBufLen        = maxBufLen; /* current length of data in 'inBuf'         */
  73. int inBufPos        = maxBufLen; /* current read position of 'inBuf'          */
  74. int outBufLen       = 0;       /* current write position of 'outBuf'          */
  75. u_int8 inBuf[maxBufLen];       /* buffer for file read                        */
  76. u_int8 outBuf[maxBufLen];      /* buffer for file write                       */
  77.  
  78. FILE *inFile;                  /* file with input data (plain or ciphertext)  */
  79. FILE *outFile;                 /* file for output data (plain or ciphertext)  */
  80. FILE *hashFile;                /* 128 bit hash value is written to this file  */
  81.  
  82. /******************************************************************************/
  83. /* initialize global variables                                                */
  84.  
  85. #ifdef ANSI_C
  86.   void Init(void)
  87. #else
  88.   Init()
  89. #endif
  90.  
  91. { int i, pos;
  92.  
  93.   for (i = Idea_userKeyLen - 1; i >= 0 ; i--) userKey[i] = 0;
  94.   for (pos = maxInterleave - 1; pos >= 0 ; pos--)
  95.     for (i = Idea_dataLen - 1; i >= 0; i--)
  96.       state[pos][i] = 0;
  97. } /* Init */
  98.  
  99. /******************************************************************************/
  100. /*                          E R R O R - H A N D L I N G                       */
  101. /******************************************************************************/
  102. /* write usage error message and terminate program                            */
  103.  
  104. #ifdef ANSI_C
  105.   void UsageError(int num)
  106. #else
  107.   UsageError(num)
  108.   int num;
  109. #endif
  110.  
  111. {
  112. #ifdef RASTERFILE
  113. fprintf(stderr, "(%d)\n\
  114. Usage:   idea [ -e | -d ] [ -r ] [ -ecb | -cbcN | -cfbN | -ofbN ]\n\
  115.               ( -k keyString | -K keyHexString )                 \n\
  116.               [ inputFile [ outputFile ] ]                       \n\
  117.          idea [ -h | -H ] [ -tan | -abr ]                        \n\
  118.               [ -k keyString | -K keyHexString ]                 \n\
  119.               [ inputFile [ [ outputFile ] hashvalFile ] ]       \n\
  120.          idea -T                                                 \n\
  121. \nExample: idea -Hk \"k e y\" infile | idea -cbc8 -K 123:9a::eF - outfile\n\
  122. \n", num);
  123. #else
  124. fprintf(stderr, "(%d)\n\
  125. Usage:   idea [ -e | -d ] [ -ecb | -cbcN | -cfbN | -ofbN ]       \n\
  126.               ( -k keyString | -K keyHexString )                 \n\
  127.               [ inputFile [ outputFile ] ]                       \n\
  128.          idea [ -h | -H ] [ -tan | -abr ]                        \n\
  129.               [ -k keyString | -K keyHexString ]                 \n\
  130.               [ inputFile [ [ outputFile ] hashvalFile ] ]       \n\
  131. \nExample: idea -Hk \"k e y\" infile | idea -cbc8 -K 123:9a::eF - outfile\n\
  132. \n", num);
  133. #endif
  134.   exit(-1);
  135. } /* UsageError */
  136.  
  137. /******************************************************************************/
  138. /* write error message and terminate program                                  */
  139.  
  140. #ifdef ANSI_C
  141.   void Error(int num, char *str)
  142. #else
  143.   Error(num, str)
  144.   int num;
  145.   char *str;
  146. #endif
  147.  
  148. {  fprintf(stderr, "error %d in idea: %s\n", num, str); exit(-1); } /* Error */
  149.  
  150. /******************************************************************************/
  151. /* write system error message and terminate program                           */
  152.  
  153. #ifdef ANSI_C
  154.   void PError(char *str)
  155. #else
  156.   PError(str)
  157.   char *str;
  158. #endif
  159.  
  160. { perror(str); exit(-1); } /* PError */
  161.  
  162. /******************************************************************************/
  163. /*                          D E C R Y P T I O N  /  E N C R Y P T I O N       */
  164. /******************************************************************************/
  165. /* read one data-block from 'inFile'                                          */
  166.  
  167. #ifdef ANSI_C
  168.   int GetData(Idea_Data data)
  169. #else
  170.   int GetData(data)
  171.   Idea_Data data;
  172. #endif
  173.  
  174. { register int i, len;
  175.   register u_int16 h;
  176.   register u_int8 *inPtr;
  177.  
  178.   if (inBufPos >= inBufLen) {
  179.     if (inBufLen != maxBufLen) return 0;
  180.     inBufLen = fread(inBuf, 1, maxBufLen, inFile);
  181.     inBufPos = 0;
  182.     if (inBufLen == 0) return 0;
  183.     if (inBufLen % Idea_dataSize != 0)
  184.       for (i = inBufLen; i % Idea_dataSize != 0; i++) inBuf[i] = 0;
  185.   }
  186.   inPtr = &inBuf[inBufPos];
  187.   for (i = 0; i < Idea_dataLen; i++) {
  188.     h = ((u_int16)*inPtr++ & 0xFF) << 8;
  189.     data[i] = h | (u_int16)*inPtr++ & 0xFF;
  190.   }
  191.   inBufPos += Idea_dataSize;
  192.   if (inBufPos <= inBufLen) len = Idea_dataSize;
  193.   else len = inBufLen + Idea_dataSize - inBufPos;
  194.   inputLen += len;
  195.   return len;
  196. } /* GetData */
  197.  
  198. /******************************************************************************/
  199. /* write one data-block to 'outFile'                                          */
  200.  
  201. #ifdef ANSI_C
  202.   void PutData(Idea_Data data, int len)
  203. #else
  204.   PutData(data, len)
  205.   Idea_Data data;
  206.   int len;
  207. #endif
  208.  
  209. { register int i;
  210.   register u_int16 h;
  211.   register u_int8 *outPtr;
  212.  
  213.   outPtr = &outBuf[outBufLen];
  214.   for (i = 0; i < Idea_dataLen; i++) {
  215.     h = data[i];
  216.     *outPtr++ = h >> 8 & 0xFF;
  217.     *outPtr++ = h & 0xFF;
  218.   }
  219.   outBufLen += len;
  220.   if (outBufLen >= maxBufLen) {
  221.     fwrite(outBuf, 1, maxBufLen, outFile);
  222.     outBufLen = 0;
  223.   }
  224. } /* PutData */
  225.  
  226. /******************************************************************************/
  227. /* write last block to 'outFile' and close 'outFile'                          */
  228.  
  229. #ifdef ANSI_C
  230.   void CloseOutput(void)
  231. #else
  232.   CloseOutput()
  233. #endif
  234.  
  235. { if (outBufLen > 0) {
  236.     fwrite(outBuf, 1, outBufLen, outFile);
  237.     outBufLen = 0;
  238.   }
  239.   fclose(outFile);
  240. } /* CloseOutput */
  241.  
  242. /******************************************************************************/
  243. /* increment time_0 and time_N                                                */
  244.  
  245. #ifdef ANSI_C
  246.   void IncTime(void)
  247. #else
  248.   IncTime()
  249. #endif
  250.  
  251. { time_0 = (time_0 + 1) % maxInterleave;
  252.   time_N = (time_N + 1) % maxInterleave;
  253. } /* IncTime */
  254.  
  255. /******************************************************************************/
  256. /* encrypt one data-block                                                     */
  257.  
  258. #ifdef ANSI_C
  259.   void EncryptData(Idea_Data data)
  260. #else
  261.   EncryptData(data)
  262.   Idea_Data data;
  263. #endif
  264.  
  265. { int i;
  266.  
  267.   switch (mode) {
  268.     case ecb:
  269.       Idea_Crypt(data, data, key);
  270.       break;
  271.     case cbc:
  272.       for (i = Idea_dataLen - 1; i >= 0; i--) data[i] ^= state[time_N][i];
  273.       Idea_Crypt(data, data, key);
  274.       for (i = Idea_dataLen - 1; i >= 0; i--) state[time_0][i] = data[i];
  275.       IncTime();
  276.       break;
  277.     case cfb:
  278.       Idea_Crypt(state[time_N], state[time_0], key);
  279.       for (i = Idea_dataLen - 1; i >= 0; i--)
  280.         data[i] = state[time_0][i] ^= data[i];
  281.       IncTime();
  282.       break;
  283.     case ofb:
  284.       Idea_Crypt(state[time_N], state[time_0], key);
  285.       for (i = Idea_dataLen - 1; i >= 0; i--) data[i] ^= state[time_0][i];
  286.       IncTime();
  287.       break;
  288.     default: break;
  289.   }
  290. } /* EncryptData */
  291.  
  292. /******************************************************************************/
  293. /* decrypt one data-block                                                     */
  294.  
  295. #ifdef ANSI_C
  296.   void DecryptData(Idea_Data data)
  297. #else
  298.   DecryptData(data)
  299.   Idea_Data data;
  300. #endif
  301.  
  302. { int i;
  303.  
  304.   switch (mode) {
  305.     case ecb:
  306.       Idea_Crypt(data, data, key);
  307.       break;
  308.     case cbc:
  309.       for (i = Idea_dataLen - 1; i >= 0; i--) state[time_0][i] = data[i];
  310.       Idea_Crypt(data, data, key);
  311.       for (i = Idea_dataLen - 1; i >= 0; i--) data[i] ^= state[time_N][i];
  312.       IncTime();
  313.       break;
  314.     case cfb:
  315.       for (i = Idea_dataLen - 1; i >= 0; i--) state[time_0][i] = data[i];
  316.       Idea_Crypt(state[time_N], data, key);
  317.       for (i = Idea_dataLen - 1; i >= 0; i--) data[i] ^= state[time_0][i];
  318.       IncTime();
  319.       break;
  320.     case ofb:
  321.       Idea_Crypt(state[time_N], state[time_0], key);
  322.       for (i = Idea_dataLen - 1; i >= 0; i--) data[i] ^= state[time_0][i];
  323.       IncTime();
  324.       break;
  325.     default: break;
  326.   }
  327. } /* DecryptData */
  328.  
  329. /******************************************************************************/
  330. /* hash one data-block                                                        */
  331.  
  332. #ifdef ANSI_C
  333.   void HashData(Idea_Data data)
  334. #else
  335.   HashData(data)
  336.   Idea_Data data;
  337. #endif
  338.  
  339. { int i;
  340.   Idea_UserKey userKey;
  341.   Idea_Key key;
  342.   Idea_Data w;
  343.  
  344.   for (i = Idea_dataLen - 1; i >= 0; i--) { 
  345.     userKey[i] = hashLow[i];
  346.     userKey[i + Idea_dataLen] = data[i]; 
  347.   }
  348.   Idea_ExpandUserKey(userKey, key);
  349.   Idea_Crypt(hashHigh, w, key);
  350.   if (mode == abr) {
  351.     for (i = Idea_dataLen - 1; i >= 0; i--) { 
  352.       userKey[i] = data[i];
  353.       userKey[i + Idea_dataLen] = hashHigh[i]; 
  354.       hashHigh[i] ^= w[i];
  355.       w[i] = hashLow[i] ^ 0xFFFF;
  356.     }
  357.   }
  358.   else { /* mode == tan */
  359.     for (i = Idea_dataLen - 1; i >= 0; i--) {
  360.       hashHigh[i] ^= w[i];
  361.       userKey[i] = data[i];
  362.       userKey[i + Idea_dataLen] = w[i];
  363.       w[i] = hashLow[i];
  364.     }
  365.   }
  366.   Idea_ExpandUserKey(userKey, key);
  367.   Idea_Crypt(w, w, key);
  368.   for (i = Idea_dataLen - 1; i >= 0; i--) hashLow[i] ^= w[i];
  369. } /* HashData */
  370.  
  371. /******************************************************************************/
  372. /* write the hash value to 'hashFile'                                         */
  373.  
  374. #ifdef ANSI_C
  375.   void WriteHashValue(void)
  376. #else
  377.   WriteHashValue()
  378. #endif
  379.  
  380. { int i;
  381.  
  382.   for (i = 0; i < Idea_dataLen; i++) fprintf(hashFile, "%04X", hashHigh[i]);
  383.   for (i = 0; i < Idea_dataLen; i++) fprintf(hashFile, "%04X", hashLow[i]);
  384. } /* WriteHashValue */
  385.  
  386. /******************************************************************************/
  387. /* store integer 'value' in 'data'                                            */
  388.  
  389. #ifdef ANSI_C
  390.   void PlainLenToData(u_int32 value, Idea_Data data)
  391. #else
  392.   PlainLenToData(value, data)
  393.   u_int32 value;
  394.   Idea_Data data;
  395. #endif
  396.  
  397. { data[3] = (u_int16)(value << 3 & 0xFFFF);
  398.   data[2] = (u_int16)(value >> 13 & 0xFFFF);
  399.   data[1] = (u_int16)(value >> 29 & 0x0007);
  400.   data[0] = 0;
  401. } /* PlainLenToData */
  402.  
  403. /******************************************************************************/
  404. /* extract integer 'value' from 'data'                                        */
  405.  
  406. #ifdef ANSI_C
  407.   void DataToPlainLen(Idea_Data data, u_int32 *value)
  408. #else
  409.   DataToPlainLen(data, value)
  410.   Idea_Data data;
  411.   u_int32 *value;
  412. #endif
  413.  
  414. { if (data[0] || data[1] > 7 || data[3] & 7)
  415.     Error(0, "input is not a valid cryptogram");
  416.   *value = (u_int32)data[3] >> 3 & 0x1FFF |
  417.            (u_int32)data[2] << 13 |
  418.            (u_int32)data[1] << 29;
  419. } /* DataToPlainLen */
  420.  
  421. /******************************************************************************/
  422. /* copy head and color-map of rasterfile from 'inFile' to 'outFile'           */
  423.  
  424. #ifdef ANSI_C
  425.   void CopyHeadOfRasFile(void)
  426. #else
  427.   CopyHeadOfRasFile()
  428. #endif
  429.  
  430. {
  431. #ifdef RASTERFILE
  432.   struct rasterfile header;
  433.   int mapLen, len;
  434.  
  435.   if (fread(&header, sizeof header, 1, inFile) != 1)
  436.     PError("read header from rasterfile");
  437.   if (header.ras_magic != RAS_MAGIC)
  438.     Error(1, "input is not a rasterfile");
  439.   if (fwrite(&header, sizeof header, 1, outFile) != 1)
  440.     PError("write header to rasterfile");
  441.   len = maxBufLen;
  442.   for (mapLen = header.ras_maplength; mapLen > 0; mapLen -= len){
  443.     if (mapLen < maxBufLen) len = mapLen;
  444.     if (fread(inBuf, len, 1, inFile) != 1) PError("read map from rasterfile");
  445.     if (fwrite(inBuf, len, 1, outFile) != 1) PError("write map to rasterfile");
  446.   }
  447. #endif
  448. } /* CopyHeadOfRasFile */
  449.  
  450. /******************************************************************************/
  451. /* encrypt / decrypt complete data-stream or compute hash value of data-stream*/
  452.  
  453. #ifdef ANSI_C
  454.   void CryptData(void)
  455. #else
  456.   CryptData()
  457. #endif
  458.  
  459. { int t, i;
  460.   u_int32 len;
  461.   Idea_Data dat[4];
  462.   Idea_Data data;
  463.  
  464.   if (optRas) {
  465.     CopyHeadOfRasFile();
  466.     if (optEncrypt) /* encrypt rasterfile */
  467.       while ((len = GetData(data)) == Idea_dataSize) {
  468.         EncryptData(data); 
  469.         PutData(data, Idea_dataSize); 
  470.       } 
  471.     else /* decrypt rasterfile */
  472.       while ((len = GetData(data)) == Idea_dataSize) {
  473.         DecryptData(data); 
  474.         PutData(data, Idea_dataSize); 
  475.       } 
  476.     if (len) PutData(data, len);
  477.     CloseOutput();
  478.   }
  479.   else if (optEncrypt) { /* encrypt data */
  480.     while ((len = GetData(data)) == Idea_dataSize) {
  481.       EncryptData(data); 
  482.       PutData(data, Idea_dataSize); 
  483.     }
  484.     if (len) { EncryptData(data); PutData(data, Idea_dataSize); }
  485.     PlainLenToData(inputLen, data);
  486.     EncryptData(data);
  487.     PutData(data, Idea_dataSize);
  488.     CloseOutput();
  489.   }
  490.   else if (optDecrypt) { /* decrypt data */
  491.     if ((len = GetData(dat[0])) != Idea_dataSize) {
  492.       if (len) Error(2, "input is not a valid cryptogram");
  493.       else Error(3, "there are no data to decrypt");
  494.     }
  495.     DecryptData(dat[0]);
  496.     if ((len = GetData(dat[1])) != Idea_dataSize) {
  497.       if (len) Error(4, "input is not a valid cryptogram");
  498.       DataToPlainLen(dat[0], &len);
  499.       if (len) Error(5, "input is not a valid cryptogram");
  500.     }
  501.     else {
  502.       DecryptData(dat[1]);
  503.       t = 2;
  504.       while ((len = GetData(dat[t])) == Idea_dataSize) {
  505.         DecryptData(dat[t]);
  506.         PutData(dat[(t + 2) & 3], Idea_dataSize);
  507.         t = (t + 1) & 3;
  508.       }
  509.       if (len) Error(6, "input is not a valid cryptogram");
  510.       DataToPlainLen(dat[(t + 3) & 3], &len);
  511.       len += 2 * Idea_dataSize;
  512.       if (inputLen < len && len <= inputLen + Idea_dataSize) {
  513.         len -= inputLen;
  514.         PutData(dat[(t + 2) & 3], len);
  515.       }
  516.       else Error(7, "input is not a valid cryptogram");
  517.     }
  518.     CloseOutput();
  519.   }
  520.   else { /* compute hash value */
  521.     for (i = Idea_dataLen - 1; i >= 0; i--) {
  522.       hashHigh[i] = userKey[i];
  523.       hashLow[i] = userKey[i + Idea_dataLen];
  524.     }
  525.     if (optCopyHash) { 
  526.       while ((len = GetData(data)) == Idea_dataSize) {
  527.         HashData(data); 
  528.         PutData(data, Idea_dataSize); 
  529.       }
  530.       if (len) { HashData(data); PutData(data, len); }
  531.       PlainLenToData(inputLen, data);
  532.       HashData(data);
  533.       CloseOutput();
  534.     }
  535.     else { /* optHash */
  536.       while ((len = GetData(data)) == Idea_dataSize) HashData(data); 
  537.       if (len) HashData(data);
  538.       PlainLenToData(inputLen, data);
  539.       HashData(data);
  540.     }
  541.     WriteHashValue();
  542.   }
  543. } /* CryptData */
  544.  
  545. /******************************************************************************/
  546. /* measure the time to encrypt 'nofTestData' data-blocks                      */
  547.  
  548. #ifdef ANSI_C
  549.   void TimeTest(void)
  550. #else
  551.   TimeTest()
  552. #endif
  553.  
  554. {
  555. #ifdef TIME
  556.   clock_t startTime, endTime;
  557.   float size, duration;
  558.   Idea_Data data;
  559.   Idea_Key key;
  560.   int i;
  561.  
  562.   for (i = 0; i < Idea_dataLen; i++) data[i] = 7 * Idea_dataLen - i;
  563.   for (i = 0; i < Idea_keyLen; i++) key[i] = 2 * Idea_keyLen - i;
  564.   for (i = Idea_keyLen - Idea_dataLen; i >= 0; i -= Idea_dataLen)
  565.     Idea_Crypt(&key[i], &key[i], key);
  566.   if ((startTime = clock()) == -1) PError("start timer");
  567.   for (i = nofTestData; i != 0; i--) Idea_Crypt(data, data, key);
  568.   if ((endTime = clock()) == -1) PError("stop timer");
  569.   size = (float)nofTestData * (float)Idea_dataSize / 131072.0;
  570.   duration = (float)(endTime - startTime) / (float)CLK_TCK;
  571.   fprintf(stderr, 
  572.     "time needed to encrypt %4.1f MBit of data was %4.1f seconds (%6.3f Mb/s)\n"
  573.     , size, duration, size / duration);
  574. #endif
  575. } /* TimeTest */
  576.  
  577. /******************************************************************************/
  578. /*                          I N I T I A L I Z A T I O N                       */
  579. /******************************************************************************/
  580. /* set option to TRUE                                                         */
  581.  
  582. #ifdef ANSI_C
  583.   void SetOption(int *option)
  584. #else
  585.   SetOption(option)
  586.   int *option;
  587. #endif
  588.  
  589. { if (*option) UsageError(10);
  590.   *option = TRUE;
  591. } /* SetOption */
  592.  
  593. /******************************************************************************/
  594. /* set encryption / decryption mode                                           */
  595.  
  596. #ifdef ANSI_C
  597.   void SetMode(int newMode, char **str)
  598. #else
  599.   SetMode(newMode, str)
  600.   int newMode;
  601.   char **str;
  602. #endif
  603.  
  604. { if (mode != nomode) UsageError(11);
  605.   mode = newMode;
  606.   (*str)++; (*str)++;
  607.   if (newMode == cbc || newMode == cfb || newMode == ofb) {
  608.     if ('0' <= **str && **str <= '9') {
  609.       interleave = 0;
  610.       do {
  611.         interleave = 10 * interleave + (**str - '0');
  612.         if (interleave >= maxInterleave)
  613.           Error(12, "interleave factor is too large");
  614.         (*str)++;
  615.       } while ('0' <= **str && **str <= '9');
  616.       if (interleave == 0) Error(13, "interleave factor is zero");
  617.     }
  618.     else interleave = 1;
  619.   }
  620. } /* SetMode */
  621.  
  622. /******************************************************************************/
  623. /* read options from string 'str'                                             */
  624.  
  625. #ifdef ANSI_C
  626.   void ReadOptions(char *str, int *readKeyString, int *readKeyHexString)
  627. #else
  628.   ReadOptions(str, readKeyString, readKeyHexString)
  629.   char *str;
  630.   int *readKeyString;
  631.   int *readKeyHexString;
  632. #endif
  633.  
  634. { char ch;
  635.  
  636.   str++;
  637.   *readKeyString = *readKeyHexString = FALSE;
  638.   while((ch = *str++) != '\0') {
  639.     switch (ch) {
  640.       case 'a':
  641.         if (str[0] == 'b' && str[1] == 'r') SetMode(abr, &str);
  642.         else UsageError(14);
  643.         break;
  644.       case 'c':
  645.         if (str[0] == 'b' && str[1] == 'c') SetMode(cbc, &str);
  646.         else if (str[0] == 'f' && str[1] == 'b') SetMode(cfb, &str);
  647.         else UsageError(15);
  648.         break;
  649.       case 'd': SetOption(&optDecrypt); break;
  650.       case 'e': 
  651.         if (str[0] == 'c' && str[1] == 'b') SetMode(ecb, &str);
  652.         else SetOption(&optEncrypt);
  653.         break;
  654.       case 'h': SetOption(&optHash); break;
  655.       case 'H': SetOption(&optCopyHash); break;
  656.       case 'o':
  657.         if (str[0] == 'f' && str[1] == 'b') SetMode(ofb, &str);
  658.         else UsageError(16);
  659.         break;
  660.       case 'k': SetOption(&optKeyString); *readKeyString = TRUE; break;
  661.       case 'K': SetOption(&optKeyHexString); *readKeyHexString = TRUE; break;
  662.       case 't':
  663.         if (str[0] == 'a' && str[1] == 'n') SetMode(tan, &str);
  664.         else UsageError(17);
  665.         break;
  666. #ifdef TIME
  667.       case 'T': SetOption(&optTime); break;
  668. #endif
  669. #ifdef RASTERFILE
  670.       case 'r': SetOption(&optRas); break;
  671. #endif
  672.       default: UsageError(18); break;
  673.     }
  674.   }
  675. } /* ReadOptions */
  676.  
  677. /******************************************************************************/
  678. /* check if options are unique and set default options                        */
  679.  
  680. #ifdef ANSI_C
  681.   void AdjustOptions(void)
  682. #else
  683.   AdjustOptions()
  684. #endif
  685.  
  686. { if (optTime) {
  687.     if (optDecrypt || optEncrypt || optHash || optCopyHash || optKeyString ||
  688.         optKeyHexString || optRas || mode != nomode) UsageError(20);
  689.   }
  690.   else {
  691.     if (optDecrypt && optEncrypt) UsageError(21);
  692.     if (optHash && optCopyHash) UsageError(22);
  693.     if (optKeyString && optKeyHexString) UsageError(23);
  694.     if (!optDecrypt && !optEncrypt && !optHash && !optCopyHash)
  695.       if (mode == tan || mode == abr) SetOption(&optHash);
  696.       else SetOption(&optEncrypt);
  697.     if (optHash || optCopyHash) {
  698.       if (optDecrypt || optEncrypt) UsageError(24);
  699.       if (optRas) UsageError(25);
  700.       if (mode == nomode) mode = tan;
  701.       else if (mode != tan && mode != abr) UsageError(26);
  702.     }
  703.     else {
  704.       if (mode == nomode) { mode = cbc; interleave = 1; }
  705.       else if (mode != ecb && mode != cbc && mode != cfb && mode != ofb)
  706.         UsageError(27);
  707.       if (!optKeyString && !optKeyHexString) UsageError(28);
  708.     }
  709.     time_0 = interleave;
  710.     time_N = 0;
  711.   }
  712. } /* AdjustOptions */
  713.  
  714. /******************************************************************************/
  715. /* convert a hex-digit into an integer                                        */
  716.  
  717. #ifdef ANSI_C
  718.   u_int32 HexToInt(char ch)
  719. #else
  720.   u_int32 HexToInt(ch)
  721.   char ch;
  722. #endif
  723.  
  724. { if ('0' <= ch && ch <= '9') return ch - '0';
  725.   else if ('a' <= ch  && ch <= 'f') return 10 + (ch - 'a');
  726.   else if ('A' <= ch && ch <= 'F') return 10 + (ch - 'A');
  727.   else if (ch == ':') return colon;
  728.   else if (ch == '\0') return eol;
  729.   else return error;
  730. } /* HexToInt */
  731.  
  732. /******************************************************************************/
  733. /* convert a character into an integer                                        */
  734.  
  735. #ifdef ANSI_C
  736.   u_int32 CharToInt(char ch)
  737. #else
  738.   u_int32 CharToInt(ch)
  739.   char ch;
  740. #endif
  741.  
  742. { if ('!' <= ch && ch <= '~') return ch - '!';
  743.   else if (ch == '\0') return eol;
  744.   else return error;
  745. } /* CharToInt */
  746.  
  747. /******************************************************************************/
  748. /* initializes key and initial values                                         */
  749.  
  750. #ifdef ANSI_C
  751.   void ReadKeyHexString(char *str)
  752. #else
  753.   ReadKeyHexString(str)
  754.   char *str;
  755. #endif
  756.  
  757. { int pos, i;
  758.   u_int32 val;
  759.  
  760.   while ((val = HexToInt(*str++)) < eol) {
  761.     for (i = Idea_userKeyLen - 1; i >= 0; i--) {
  762.       val |= (u_int32)userKey[i] << 4;
  763.       userKey[i] = (u_int16)(val & 0xFFFF);
  764.       val >>= 16;
  765.     }
  766.     if (val) Error(29, "key value is too large");
  767.   }
  768.   for (pos = 0; val == colon && pos < maxInterleave; pos++) {
  769.     while ((val = HexToInt(*str++)) < eol) {
  770.       for (i = Idea_dataLen - 1; i >= 0; i--) {
  771.         val |= (u_int32)state[pos][i] << 4;
  772.         state[pos][i] = (u_int16)(val & 0xFFFF);
  773.         val >>= 16;
  774.       }
  775.       if (val) Error(30, "initial value is too large");
  776.     }
  777.   }
  778.   if (val == colon) Error(31, "too many initial values specified");
  779.   if (val != eol) Error(32, "wrong character in initialization string");
  780. } /* ReadKeyHexString */
  781.  
  782. /******************************************************************************/
  783. /* initialize key and initial values                                          */
  784.  
  785. #ifdef ANSI_C
  786.   void ReadKeyString(char *str)
  787. #else
  788.   ReadKeyString(str)
  789.   char *str;
  790. #endif
  791.  
  792. { int i;
  793.   u_int32 val;
  794.  
  795.   while ((val = CharToInt(*str++)) < eol) {
  796.     for (i = Idea_userKeyLen - 1; i >= 0; i--) {
  797.       val += (u_int32)userKey[i] * nofChar;
  798.       userKey[i] = (u_int16)(val & 0xFFFF);
  799.       val >>= 16;
  800.     }
  801.   }
  802.   if (val != eol) Error(32, "wrong character in key string");
  803. } /* ReadKeyString */
  804.  
  805. /******************************************************************************/
  806. /* show current state informations                                            */
  807.  
  808. #ifdef ANSI_C
  809.   void ShowState(void)
  810. #else
  811.   ShowState()
  812. #endif
  813.  
  814. { int i, j;
  815.  
  816.   fprintf(stderr, "Mode = {");
  817.   switch (mode) {
  818.     case ecb: fprintf(stderr, "ecb"); break;
  819.     case cbc: fprintf(stderr, "cbc"); break;
  820.     case cfb: fprintf(stderr, "cfb"); break;
  821.     case ofb: fprintf(stderr, "ofb"); break;
  822.     case tan: fprintf(stderr, "tan"); break;
  823.     case abr: fprintf(stderr, "abr"); break;
  824.     case nomode: fprintf(stderr, "nomode"); break;
  825.     default: fprintf(stderr, "!!!wrong mode!!!"); break;
  826.   }
  827.   if (interleave > 0) fprintf(stderr, "%d", interleave);
  828.   if (optEncrypt) fprintf(stderr, ", encrypt");
  829.   if (optDecrypt) fprintf(stderr, ", decrypt");
  830.   if (optHash) fprintf(stderr, ", hash");
  831.   if (optCopyHash) fprintf(stderr, ", copy and hash");
  832.   if (optKeyString) fprintf(stderr, ", key string");
  833.   if (optKeyHexString) fprintf(stderr, ", key hex string");
  834.   if (optRas) fprintf(stderr, ", raster file");
  835.   if (optTime) fprintf(stderr, ", time test");
  836.   fprintf(stderr, "}\n\nKey:\n");
  837.   for (i = 0; i < Idea_keyLen; i++) {
  838.     fprintf(stderr, "%7u<%4x>", key[i], key[i]);
  839.     if ((i % 6) == 5) fprintf(stderr, "\n");
  840.   }
  841.   fprintf(stderr, "\n\nInitial values:");
  842.   for (i = 0; i < interleave; i++) {
  843.     fprintf(stderr, "\n  x[N -%2d] =", i + 1);
  844.     for (j = 0; j < Idea_dataLen; j++)
  845.       fprintf(stderr, "%7u<%4x>", state[i][j], state[i][j]);
  846.   }
  847.   fprintf(stderr, "\n");
  848. } /* ShowState */
  849.  
  850. /******************************************************************************/
  851. /*                          M A I N - P R O C E D U R E                       */
  852. /******************************************************************************/
  853. #ifdef ANSI_C
  854.   int main(int argc, char *argv[])
  855. #else
  856.   int main(argc, argv)
  857.   int argc;
  858.   char *argv[];
  859. #endif
  860.  
  861. { int readKeyString, readKeyHexString;
  862.  
  863. #ifdef __EMX__
  864.     _wildcard(&argc, &argv);
  865. #endif
  866.  
  867.   Init();
  868.   argv++; argc--;
  869.   while (argc > 0 && argv[0][0] == '-' && argv[0][1] != '\0') {
  870.     ReadOptions(*argv++, &readKeyString, &readKeyHexString); argc--;
  871.     if (readKeyString || readKeyHexString) {
  872.       if (argc <= 0)  Error(36, "missing key on command line");
  873.       else if (readKeyString) { ReadKeyString(*argv++); argc--; }
  874.       else { ReadKeyHexString(*argv++); argc--; }
  875.     }
  876.   }
  877.   AdjustOptions();
  878.   if (optTime && argc > 0 || optCopyHash && argc > 3 || 
  879.       !optCopyHash && argc > 2) Error(37, "too many parameters");
  880.   if (optTime)
  881.     TimeTest();
  882.   else {
  883.     if (argc > 1 && strcmp(argv[0], argv[1]) == 0)
  884.       Error(38, "source and destination are identical");
  885.     if (argc > 2 && strcmp(argv[0], argv[2]) == 0)
  886.       Error(39, "source and destination are identical");
  887.     if (argc > 2 && strcmp(argv[1], argv[2]) == 0)
  888.       Error(40, "destinations are identical");
  889.     inFile = stdin;
  890.     outFile = hashFile = stdout;
  891.     if (argc > 0) {
  892.       if (strcmp(*argv, "-") == 0) { argv++; argc--; }
  893.       else {
  894.         inFile = fopen(*argv++, "rb"); argc--;
  895.         if (inFile == NULL) PError(*--argv);
  896.       }
  897.     }
  898.     if (optCopyHash) {
  899.       if (argc > 1) {
  900.         outFile = fopen(*argv++, "wb"); argc--;
  901.         if (outFile == NULL) PError(*--argv);
  902.       }
  903.       if (argc > 0) {
  904.         hashFile = fopen(*argv++, "wb"); argc--;
  905.         if (hashFile == NULL) PError(*--argv);
  906.       }
  907.       else hashFile = stderr;
  908.     }
  909.     else if (optHash) {
  910.       if (argc > 0) {
  911.         hashFile = fopen(*argv++, "wb"); argc--;
  912.         if (hashFile == NULL) PError(*--argv);
  913.       }
  914.     }
  915.     else {
  916.       if (argc > 0) {
  917.         outFile = fopen(*argv++, "wb"); argc--;
  918.         if (outFile == NULL) PError(*--argv);
  919.       }
  920.     }
  921.     if (argc > 0) Error(41, "too many parameters");
  922.     Idea_ExpandUserKey(userKey, key);
  923.     if (optDecrypt && (mode == ecb || mode == cbc)) Idea_InvertKey(key, key);
  924. #ifdef DEBUG
  925.     ShowState();
  926. #else
  927.     CryptData();
  928. #endif
  929.   }
  930.   return 0;
  931. }
  932.