home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / IDEA / IDEA.C next >
Text File  |  1996-09-22  |  15KB  |  629 lines

  1. #define OPTIMIZE /* Paulo Barreto <pbarreto@unisys.com.br> 1996.01.17 */
  2. /*
  3.  *    idea.c - C source code for IDEA block cipher.
  4.  *    IDEA (International Data Encryption Algorithm), formerly known as 
  5.  *    IPES (Improved Proposed Encryption Standard).
  6.  *    Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
  7.  *    This implementation modified and derived from original C code 
  8.  *    developed by Xuejia Lai.  
  9.  *    Zero-based indexing added, names changed from IPES to IDEA.
  10.  *    CFB functions added.  Random number routines added.
  11.  *
  12.  *    Extensively optimized and restructured by Colin Plumb.
  13.  *
  14.  *    There are two adjustments that can be made to this code to
  15.  *    speed it up.  Defaults may be used for PCs.  Only the -DIDEA32
  16.  *    pays off significantly if selectively set or not set.
  17.  *    Experiment to see what works best for your machine.
  18.  *
  19.  *    Multiplication: default is inline, -DAVOID_JUMPS uses a
  20.  *        different version that does not do any conditional
  21.  *        jumps (a few percent worse on a SPARC), while
  22.  *        -DSMALL_CACHE takes it out of line to stay
  23.  *        within a small on-chip code cache.
  24.  *    Variables: normally, 16-bit variables are used, but some
  25.  *        machines (notably RISCs) do not have 16-bit registers,
  26.  *        so they do a great deal of masking.  -DIDEA32 uses "int"
  27.  *        register variables and masks explicitly only where
  28.  *        necessary.  On a SPARC, for example, this boosts
  29.  *        performace by 30%.
  30.  *
  31.  *    The IDEA(tm) block cipher is covered by patents held by ETH and a
  32.  *    Swiss company called Ascom-Tech AG.  The Swiss patent number is
  33.  *    PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and
  34.  *    the U.S. patent number is US005214703.  IDEA(tm) is a trademark of
  35.  *    Ascom-Tech AG.  There is no license fee required for noncommercial
  36.  *    use.  Commercial users may obtain licensing details from Dieter
  37.  *    Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn,
  38.  *    Switzerland, Tel +41 65 242885, Fax +41 65 235761.
  39.  *
  40.  *    The IDEA block cipher uses a 64-bit block size, and a 128-bit key 
  41.  *    size.  It breaks the 64-bit cipher block into four 16-bit words
  42.  *    because all of the primitive inner operations are done with 16-bit
  43.  *    arithmetic.  It likewise breaks the 128-bit cipher key into eight 
  44.  *    16-bit words.
  45.  *
  46.  *    For further information on the IDEA cipher, see the book:
  47.  *      Xuejia Lai, "On the Design and Security of Block Ciphers",
  48.  *      ETH Series on Information Processing (ed. J.L. Massey) Vol 1,
  49.  *      Hartung-Gorre Verlag, Konstanz, Switzerland, 1992.  ISBN
  50.  *      3-89191-573-X.
  51.  *
  52.  *    This code runs on arrays of bytes by taking pairs in big-endian
  53.  *    order to make the 16-bit words that IDEA uses internally.  This
  54.  *    produces the same result regardless of the byte order of the
  55.  *    native CPU.
  56.  */
  57.  
  58. #include <string.h>
  59. #if defined( INC_ALL )
  60.   #include "crypt.h"
  61.   #include "idea.h"
  62. #elif defined( INC_CHILD )
  63.   #include "../crypt.h"
  64.   #include "idea.h"
  65. #else
  66.   #include "crypt.h"
  67.   #include "idea/idea.h"
  68. #endif /* Compiler-specific includes */
  69.  
  70. #ifdef BIG_ENDIAN        /* This code uses slightly different names */
  71.   #define HIGHFIRST
  72. #endif /* BIG_ENDIAN */
  73.  
  74. #ifdef IDEA32    /* Use >16-bit temporaries */
  75. #define low16(x) ((x) & 0xFFFF)
  76. typedef unsigned int uint16;    /* at LEAST 16 bits, maybe more */
  77. #else
  78. #define low16(x) (x)    /* this is only ever applied to uint16's */
  79. typedef word16 uint16;
  80. #endif
  81.  
  82. #ifdef _GNUC_
  83. /* __const__ simply means there are no side effects for this function,
  84.  * which is useful info for the gcc optimizer
  85.  */
  86. #define CONST __const__
  87. #else
  88. #define CONST
  89. #endif
  90.  
  91. /*
  92.  *    Multiplication, modulo (2**16)+1
  93.  * Note that this code is structured on the assumption that
  94.  * untaken branches are cheaper than taken branches, and the
  95.  * compiler doesn't schedule branches.
  96.  */
  97. #ifdef SMALL_CACHE
  98. CONST static uint16
  99. mul(register uint16 a, register uint16 b)
  100. {
  101.     register word32 p;
  102.  
  103.     p = (word32)a * b;
  104.     if (p) {
  105.         b = low16(p);
  106.         a = p>>16;
  107.         return (b - a) + (b < a);
  108.     } else if (a) {
  109.         return 1-b;
  110.     } else {
  111.         return 1-a;
  112.     }
  113. } /* mul */
  114. #endif /* SMALL_CACHE */
  115.  
  116. /*
  117.  * Compute the multiplicative inverse of x, modulo 65537, using Euclid's
  118.  * algorithm. It is unrolled twice to avoid swapping the registers each
  119.  * iteration, and some subtracts of t have been changed to adds.
  120.  */
  121. CONST static uint16
  122. mulInv(uint16 x)     
  123. {
  124.     uint16 t0, t1;
  125.     uint16 q, y;
  126.  
  127.     if (x <= 1)
  128.         return x;    /* 0 and 1 are self-inverse */
  129.     t1 = 0x10001L / x;    /* Since x >= 2, this fits into 16 bits */
  130.     y = 0x10001L % x;
  131.     if (y == 1)
  132.         return ( uint16 ) low16(1-t1);
  133.     t0 = 1;
  134.     do {
  135.         q = x / y;
  136.         x = x % y;
  137.         t0 += q * t1;
  138.         if (x == 1)
  139.             return t0;
  140.         q = y / x;
  141.         y = y % x;
  142.         t1 += q * t0;
  143.     } while (y != 1);
  144.     return ( uint16 ) low16(1-t1);
  145. } /* mukInv */
  146.  
  147. /*
  148.  * Expand a 128-bit user key to a working encryption key EK
  149.  */
  150. void
  151. ideaExpandKey(byte const *userkey, word16 *EK)
  152. {
  153.     int i,j;
  154.  
  155.     for (j=0; j<8; j++) {
  156.         EK[j] = (userkey[0]<<8) + userkey[1];
  157.         userkey += 2;
  158.     }
  159.     for (i=0; j < IDEAKEYLEN; j++) {
  160.         i++;
  161.         EK[i+7] = (EK[i & 7] << 9) | (EK[i+1 & 7] >> 7);
  162.         EK += i & 8;
  163.         i &= 7;
  164.     }
  165. } /* ideaExpandKey */
  166.  
  167. #define NEG(x) (- (int) (x))
  168.  
  169. /*
  170.  * Compute IDEA decryption key DK from an expanded IDEA encryption key EK
  171.  * Note that the input and output may be the same.  Thus, the key is
  172.  * inverted into an internal buffer, and then copied to the output.
  173.  */
  174. void
  175. #ifdef _DCC
  176. ideaInvertKey(word16 *EK, word16 DK[IDEAKEYLEN])
  177. #else
  178. ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN])
  179. #endif
  180. {
  181.     word16 temp[IDEAKEYLEN];
  182. #ifdef OPTIMIZE
  183.     register int k, p, r;
  184.  
  185.     p = IDEAKEYLEN;
  186.     temp [p-1] = mulInv (EK [3]);
  187.     temp [p-2] = NEG (EK [2]);
  188.     temp [p-3] = NEG (EK [1]);
  189.     temp [p-4] = mulInv (EK [0]);
  190.  
  191.     k = 4; p -= 4;
  192.     for (r = IDEAROUNDS - 1; r > 0; r--) {
  193.         temp [p-1] = EK [k+1];
  194.         temp [p-2] = EK [k];
  195.         temp [p-3] = mulInv (EK [k+5]);
  196.         temp [p-4] = NEG (EK [k+3]);
  197.         temp [p-5] = NEG (EK [k+4]);
  198.         temp [p-6] = mulInv (EK [k+2]);
  199.         k += 6; p -= 6;
  200.     }
  201.     temp [p-1] = EK [k+1];
  202.     temp [p-2] = EK [k];
  203.     temp [p-3] = mulInv (EK [k+5]);
  204.     temp [p-4] = NEG (EK [k+4]);
  205.     temp [p-5] = NEG (EK [k+3]);
  206.     temp [p-6] = mulInv (EK [k+2]);
  207. #else  /* !OPTIMIZE */
  208.     int i;
  209.     uint16 t1, t2, t3;
  210.     word16 *p = temp + IDEAKEYLEN;
  211.  
  212.     t1 = mulInv(*EK++);
  213.     t2 = - ( int ) *EK++;
  214.     t3 = - ( int ) *EK++;
  215.     *--p = mulInv(*EK++);
  216.     *--p = t3;
  217.     *--p = t2;
  218.     *--p = t1;
  219.  
  220.     for (i = 0; i < IDEAROUNDS-1; i++) {
  221.         t1 = *EK++;
  222.         *--p = *EK++;
  223.         *--p = t1;
  224.  
  225.         t1 = mulInv(*EK++);
  226.         t2 = - ( int ) *EK++;
  227.         t3 = - ( int ) *EK++;
  228.         *--p = mulInv(*EK++);
  229.         *--p = t2;
  230.         *--p = t3;
  231.         *--p = t1;
  232.     }
  233.     t1 = *EK++;
  234.     *--p = *EK++;
  235.     *--p = t1;
  236.  
  237.     t1 = mulInv(*EK++);
  238.     t2 = - ( int ) *EK++;
  239.     t3 = - ( int ) *EK++;
  240.     *--p = mulInv(*EK++);
  241.     *--p = t3;
  242.     *--p = t2;
  243.     *--p = t1;
  244. #endif /* ?OPTIMIZE */
  245. /* Copy and destroy temp copy */
  246.     memcpy(DK, temp, sizeof(temp));
  247.     burn(temp);
  248. } /* ideaInvertKey */
  249.  
  250. /*
  251.  * MUL(x,y) computes x = x*y, modulo 0x10001.  Requires two temps, 
  252.  * t16 and t32.  x is modified, and must me a side-effect-free lvalue.
  253.  * y may be anything, but unlike x, must be strictly 16 bits even if
  254.  * low16() is #defined.
  255.  * All of these are equivalent - see which is faster on your machine
  256.  */
  257. #ifdef SMALL_CACHE
  258. #define MUL(x,y) (x = mul(low16(x),y))
  259. #else /* !SMALL_CACHE */
  260. #ifdef AVOID_JUMPS
  261. #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \
  262.         t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \
  263.         t16 = t32>>16, x = (x-t16) + (x<t16) )
  264. #else /* !AVOID_JUMPS (default) */
  265. #define MUL(x,y) \
  266.     ((t16 = (y)) ? \
  267.         (x=low16(x)) ? \
  268.             t32 = (word32)x*t16, \
  269.             x = low16(t32), \
  270.             t16 = t32>>16, \
  271.             x = (x-t16)+(x<t16) \
  272.         : \
  273.             (x = 1-t16) \
  274.     : \
  275.         (x = 1-x))
  276. #endif
  277. #endif
  278.  
  279. /*    IDEA encryption/decryption algorithm */
  280. /* Note that in and out can be the same buffer */
  281. void
  282. #ifdef _DCC
  283. ideaCipher(byte (inbuf[8]), byte (outbuf[8]), word16 *key)
  284. #else
  285. ideaCipher(byte const (inbuf[8]), byte (outbuf[8]), word16 const *key)
  286. #endif
  287. {
  288.     register uint16 x1, x2, x3, x4, s2, s3;
  289.     word16 *in, *out;
  290. #ifndef SMALL_CACHE
  291.     register uint16 t16;    /* Temporaries needed by MUL macro */
  292.     register word32 t32;
  293. #endif
  294. #ifndef OPTIMIZE
  295.     int r = IDEAROUNDS;
  296. #endif /* ?OPTIMIZE */
  297.  
  298.     in = (word16 *)inbuf;
  299. #ifdef OPTIMIZE
  300.     x1 = in[0];  x2 = in[1];
  301.     x3 = in[2];  x4 = in[3];
  302. #else  /* !OPTIMIZE */
  303.     x1 = *in++;  x2 = *in++;
  304.     x3 = *in++;  x4 = *in;
  305. #endif /* ?OPTIMIZE */
  306. #ifndef HIGHFIRST
  307.     x1 = (x1>>8) | (x1<<8);
  308.     x2 = (x2>>8) | (x2<<8);
  309.     x3 = (x3>>8) | (x3<<8);
  310.     x4 = (x4>>8) | (x4<<8);
  311. #endif
  312.  
  313. #ifdef OPTIMIZE
  314.  
  315. /* round 1: */
  316.  
  317.         MUL(x1,key[0]);
  318.         x2 += key[1];
  319.         x3 += key[2];
  320.         MUL(x4, key[3]);
  321.  
  322.         s3 = x3;
  323.         x3 ^= x1;
  324.         MUL(x3, key[4]);
  325.         s2 = x2;
  326.         x2 ^= x4;
  327.         x2 += x3;
  328.         MUL(x2, key[5]);
  329.         x3 += x2;
  330.  
  331.         x1 ^= x2;  x4 ^= x3;
  332.         x2 ^= s3;  x3 ^= s2;
  333.  
  334. /* round 2: */
  335.  
  336.         MUL(x1,key[6]);
  337.         x2 += key[7];
  338.         x3 += key[8];
  339.         MUL(x4, key[9]);
  340.  
  341.         s3 = x3;
  342.         x3 ^= x1;
  343.         MUL(x3, key[10]);
  344.         s2 = x2;
  345.         x2 ^= x4;
  346.         x2 += x3;
  347.         MUL(x2, key[11]);
  348.         x3 += x2;
  349.  
  350.         x1 ^= x2;  x4 ^= x3;
  351.         x2 ^= s3;  x3 ^= s2;
  352.  
  353. /* round 3: */
  354.  
  355.         MUL(x1,key[12]);
  356.         x2 += key[13];
  357.         x3 += key[14];
  358.         MUL(x4, key[15]);
  359.  
  360.         s3 = x3;
  361.         x3 ^= x1;
  362.         MUL(x3, key[16]);
  363.         s2 = x2;
  364.         x2 ^= x4;
  365.         x2 += x3;
  366.         MUL(x2, key[17]);
  367.         x3 += x2;
  368.  
  369.         x1 ^= x2;  x4 ^= x3;
  370.         x2 ^= s3;  x3 ^= s2;
  371.  
  372. /* round 4: */
  373.  
  374.         MUL(x1,key[18]);
  375.         x2 += key[19];
  376.         x3 += key[20];
  377.         MUL(x4, key[21]);
  378.  
  379.         s3 = x3;
  380.         x3 ^= x1;
  381.         MUL(x3, key[22]);
  382.         s2 = x2;
  383.         x2 ^= x4;
  384.         x2 += x3;
  385.         MUL(x2, key[23]);
  386.         x3 += x2;
  387.  
  388.         x1 ^= x2;  x4 ^= x3;
  389.         x2 ^= s3;  x3 ^= s2;
  390.  
  391. /* round 5: */
  392.  
  393.         MUL(x1,key[24]);
  394.         x2 += key[25];
  395.         x3 += key[26];
  396.         MUL(x4, key[27]);
  397.  
  398.         s3 = x3;
  399.         x3 ^= x1;
  400.         MUL(x3, key[28]);
  401.         s2 = x2;
  402.         x2 ^= x4;
  403.         x2 += x3;
  404.         MUL(x2, key[29]);
  405.         x3 += x2;
  406.  
  407.         x1 ^= x2;  x4 ^= x3;
  408.         x2 ^= s3;  x3 ^= s2;
  409.  
  410. /* round 6: */
  411.  
  412.         MUL(x1,key[30]);
  413.         x2 += key[31];
  414.         x3 += key[32];
  415.         MUL(x4, key[33]);
  416.  
  417.         s3 = x3;
  418.         x3 ^= x1;
  419.         MUL(x3, key[34]);
  420.         s2 = x2;
  421.         x2 ^= x4;
  422.         x2 += x3;
  423.         MUL(x2, key[35]);
  424.         x3 += x2;
  425.  
  426.         x1 ^= x2;  x4 ^= x3;
  427.         x2 ^= s3;  x3 ^= s2;
  428.  
  429. /* round 7: */
  430.  
  431.         MUL(x1,key[36]);
  432.         x2 += key[37];
  433.         x3 += key[38];
  434.         MUL(x4, key[39]);
  435.  
  436.         s3 = x3;
  437.         x3 ^= x1;
  438.         MUL(x3, key[40]);
  439.         s2 = x2;
  440.         x2 ^= x4;
  441.         x2 += x3;
  442.         MUL(x2, key[41]);
  443.         x3 += x2;
  444.  
  445.         x1 ^= x2;  x4 ^= x3;
  446.         x2 ^= s3;  x3 ^= s2;
  447.  
  448. /* round 8: */
  449.  
  450.         MUL(x1,key[42]);
  451.         x2 += key[43];
  452.         x3 += key[44];
  453.         MUL(x4, key[45]);
  454.  
  455.         s3 = x3;
  456.         x3 ^= x1;
  457.         MUL(x3, key[46]);
  458.         s2 = x2;
  459.         x2 ^= x4;
  460.         x2 += x3;
  461.         MUL(x2, key[47]);
  462.         x3 += x2;
  463.  
  464.         x1 ^= x2;  x4 ^= x3;
  465.         x2 ^= s3;  x3 ^= s2;
  466.  
  467. /* final semiround: */
  468.  
  469.     MUL(x1, key[48]);
  470.     x3 += key[49];
  471.     x2 += key[50];
  472.     MUL(x4, key[51]);
  473.  
  474. #else  /* !OPTIMIZE */
  475.     do {
  476.         MUL(x1,*key++);
  477.         x2 += *key++;
  478.         x3 += *key++;
  479.         MUL(x4, *key++);
  480.  
  481.         s3 = x3;
  482.         x3 ^= x1;
  483.         MUL(x3, *key++);
  484.         s2 = x2;
  485.         x2 ^= x4;
  486.         x2 += x3;
  487.         MUL(x2, *key++);
  488.         x3 += x2;
  489.  
  490.         x1 ^= x2;  x4 ^= x3;
  491.  
  492.         x2 ^= s3;  x3 ^= s2;
  493.     } while (--r);
  494.     MUL(x1, *key++);
  495.     x3 += *key++;
  496.     x2 += *key++;
  497.     MUL(x4, *key);
  498. #endif /* ?OPTIMIZE */
  499.  
  500.     out = (word16 *)outbuf;
  501. #ifdef HIGHFIRST
  502.     *out++ = x1;
  503.     *out++ = x3;
  504.     *out++ = x2;
  505.     *out = x4;
  506. #else /* !HIGHFIRST */
  507. #ifdef OPTIMIZE
  508.     out[0] = (x1>>8) | (x1<<8);
  509.     out[1] = (x3>>8) | (x3<<8);
  510.     out[2] = (x2>>8) | (x2<<8);
  511.     out[3] = (x4>>8) | (x4<<8);
  512. #else  /* !OPTIMIZE */
  513.     x1 = low16(x1);
  514.     x2 = low16(x2);
  515.     x3 = low16(x3);
  516.     x4 = low16(x4);
  517.     *out++ = (x1>>8) | (x1<<8);
  518.     *out++ = (x3>>8) | (x3<<8);
  519.     *out++ = (x2>>8) | (x2<<8);
  520.     *out   = (x4>>8) | (x4<<8);
  521. #endif /* ?OPTIMIZE */
  522. #endif
  523. } /* ideaCipher */
  524.  
  525. /*-------------------------------------------------------------*/
  526.  
  527. #ifdef TEST
  528.  
  529. #include <stdio.h>
  530. #include <stdlib.h>
  531. #include <time.h>
  532. /*
  533.  * This is the number of Kbytes of test data to encrypt.
  534.  * It defaults to 1 MByte.
  535.  */
  536. #ifndef BLOCKS
  537.   #ifndef KBYTES
  538.     #define KBYTES 1024L
  539.   #endif
  540.   #define BLOCKS (64*KBYTES)
  541. #endif
  542.  
  543. int
  544. main(void)
  545. {    /* Test driver for IDEA cipher */
  546.     int i, j, k;
  547.     byte userkey[16];
  548.     word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN];
  549.     byte XX[8], YY[8], ZZ[8];
  550.     clock_t start, end;
  551.     long l;
  552.     float secs;
  553.  
  554.     /* Make a sample user key for testing... */
  555.     for(i=0; i<16; i++)
  556.         userkey[i] = i+1;
  557.  
  558.     /* Compute encryption subkeys from user key... */
  559.     ideaExpandKey(userkey, EK);
  560.     printf("\nEncryption key subblocks: ");
  561.     for (j=0; j<IDEAROUNDS+1; j++) {
  562.         printf("\nround %d:   ", j+1);
  563.         if (j < IDEAROUNDS)
  564.             for(i=0; i<6; i++)
  565.                 printf(" %6u", EK[j*6+i]);
  566.         else
  567.             for(i=0; i<4; i++)
  568.                 printf(" %6u", EK[j*6+i]);
  569.     }
  570.  
  571.     /* Compute decryption subkeys from encryption subkeys... */
  572.     ideaInvertKey(EK, DK);
  573.     printf("\nDecryption key subblocks: ");
  574.     for (j=0; j<IDEAROUNDS+1; j++) {
  575.         printf("\nround %d:   ", j+1);
  576.         if (j < IDEAROUNDS)
  577.             for(i=0; i<6; i++)
  578.                 printf(" %6u", DK[j*6+i]);
  579.         else
  580.             for(i=0; i<4; i++)
  581.                 printf(" %6u", DK[j*6+i]);
  582.     }
  583.  
  584.     /* Make a sample plaintext pattern for testing... */
  585.     for (k=0; k<8; k++)
  586.         XX[k] = k;
  587.  
  588.     printf("\nEncrypting %ld bytes (%ld blocks)...", BLOCKS*16, BLOCKS);
  589.     fflush(stdout);
  590.     start = clock();
  591.     memcpy(YY, XX, 8);
  592.     for (l = 0; l < BLOCKS; l++)
  593.         ideaCipher(YY, YY, EK);    /* repeated encryption */
  594.     memcpy(ZZ, YY, 8);
  595.     for (l = 0; l < BLOCKS; l++)
  596.         ideaCipher(ZZ, ZZ, DK);    /* repeated decryption */
  597.     end = clock() - start;
  598. /*
  599.     l = end  / (CLOCKS_PER_SEC/1000) + 1;
  600.     i = l/1000;
  601.     j = l%1000;
  602.     l = (16 * BLOCKS * (CLOCKS_PER_SEC/1000)) / (end/1000);
  603.     printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
  604. */
  605.     secs = (float) end / CLOCKS_PER_SEC;
  606.     printf("%.2f sec = %.0f bytes/sec.\n",
  607.         secs, (float) BLOCKS*16 / secs);
  608.  
  609.     printf("\nX %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
  610.       XX[0], XX[1],  XX[2], XX[3], XX[4], XX[5],  XX[6], XX[7]);
  611.     printf("\nY %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
  612.       YY[0], YY[1],  YY[2], YY[3], YY[4], YY[5],  YY[6], YY[7]);
  613.     printf("\nZ %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",    
  614.       ZZ[0], ZZ[1],  ZZ[2], ZZ[3], ZZ[4], ZZ[5],  ZZ[6], ZZ[7]);
  615.  
  616.     /* Now decrypted ZZ should be same as original XX */
  617.     for (k=0; k<8; k++)
  618.         if (XX[k] != ZZ[k]) {
  619.             printf("\n\07Error!  Noninvertable encryption.\n");
  620.             exit(-1);    /* error exit */ 
  621.         }
  622.     printf("\nNormal exit.\n");
  623.     return 0;    /* normal exit */
  624. } /* main */
  625.  
  626. #endif /* TEST */
  627.  
  628. /* end of idea.c */
  629.