home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / LIB_IDEA.C < prev    next >
Text File  |  1996-09-29  |  15KB  |  540 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                        cryptlib IDEA Encryption Routines                    *
  4. *                        Copyright Peter Gutmann 1992-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include "crypt.h"
  14. #ifdef INC_ALL
  15.   #include "idea.h"
  16. #else
  17.   #include "idea/idea.h"
  18. #endif /* Compiler-specific includes */
  19.  
  20. /* The IDEA key and block size */
  21.  
  22. #define IDEA_KEYSIZE    IDEAKEYSIZE
  23. #define IDEA_BLOCKSIZE    IDEABLOCKSIZE
  24.  
  25. /* A structure to hold the two expanded IDEA keys */
  26.  
  27. typedef struct {
  28.     WORD eKey[ IDEAKEYLEN ];        /* The encryption key */
  29.     WORD dKey[ IDEAKEYLEN ];        /* The decryption key */
  30.     } IDEA_KEY;
  31.  
  32. /* The size of the expanded IDEA keys */
  33.  
  34. #define IDEA_EXPANDED_KEYSIZE        sizeof( IDEA_KEY )
  35.  
  36. /****************************************************************************
  37. *                                                                            *
  38. *                                IDEA Self-test Routines                        *
  39. *                                                                            *
  40. ****************************************************************************/
  41.  
  42. #include "testidea.h"
  43.  
  44. /* Test the IDEA code against the test vectors from the ETH reference
  45.    implementation */
  46.  
  47. int ideaSelfTest( void )
  48.     {
  49.     BYTE temp[ IDEA_BLOCKSIZE ];
  50.     WORD key[ IDEAKEYLEN ];
  51.     int i;
  52.  
  53.     for( i = 0; i < sizeof( testIdea ) / sizeof( IDEA_TEST ); i++ )
  54.         {
  55.         memcpy( temp, testIdea[ i ].plaintext, IDEA_BLOCKSIZE );
  56.         ideaExpandKey( testIdea[ i ].key, key );
  57.         ideaCipher( temp, temp, key );
  58.         if( memcmp( testIdea[ i ].ciphertext, temp, IDEA_BLOCKSIZE ) )
  59.             return( CRYPT_ERROR );
  60.         }
  61.  
  62.     return( CRYPT_OK );
  63.     }
  64.  
  65. /****************************************************************************
  66. *                                                                            *
  67. *                            Init/Shutdown Routines                            *
  68. *                                                                            *
  69. ****************************************************************************/
  70.  
  71. /* Perform auxiliary init and shutdown actions on an encryption context */
  72.  
  73. int ideaInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx )
  74.     {
  75.     int status;
  76.  
  77.     UNUSED( cryptInfoEx );
  78.  
  79.     /* Allocate memory for the keyscheduled key */
  80.     if( cryptInfo->key != NULL || cryptInfo->privateData != NULL )
  81.         return( CRYPT_INITED );
  82.     if( ( status = secureMalloc( &cryptInfo->key, IDEA_EXPANDED_KEYSIZE ) ) != CRYPT_OK )
  83.         return( status );
  84.     cryptInfo->keyLength = IDEA_EXPANDED_KEYSIZE;
  85.  
  86.     return( CRYPT_OK );
  87.     }
  88.  
  89. int ideaInit( CRYPT_INFO *cryptInfo )
  90.     {
  91.     /* Just pass the call through to the extended setup routine */
  92.     return( ideaInitEx( cryptInfo, NULL ) );
  93.     }
  94.  
  95. int ideaEnd( CRYPT_INFO *cryptInfo )
  96.     {
  97.     /* Free any allocated memory */
  98.     secureFree( &cryptInfo->key );
  99.  
  100.     return( CRYPT_OK );
  101.     }
  102.  
  103. /****************************************************************************
  104. *                                                                            *
  105. *                            IDEA En/Decryption Routines                        *
  106. *                                                                            *
  107. ****************************************************************************/
  108.  
  109. /* Encrypt/decrypt data in ECB mode */
  110.  
  111. int ideaEncryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  112.     {
  113.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  114.     int blockCount = noBytes / IDEA_BLOCKSIZE;
  115.  
  116.     /* Make sure the data length is a multiple of the block size */
  117.     if( noBytes % IDEA_BLOCKSIZE )
  118.         return( CRYPT_BADPARM3 );
  119.  
  120.     while( blockCount-- )
  121.         {
  122.         /* Encrypt a block of data */
  123.         ideaCipher( buffer, buffer, ideaKey->eKey );
  124.  
  125.         /* Move on to next block of data */
  126.         buffer += IDEA_BLOCKSIZE;
  127.         }
  128.  
  129.     return( CRYPT_OK );
  130.     }
  131.  
  132. int ideaDecryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  133.     {
  134.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  135.     int blockCount = noBytes / IDEA_BLOCKSIZE;
  136.  
  137.     /* Make sure the data length is a multiple of the block size */
  138.     if( noBytes % IDEA_BLOCKSIZE )
  139.         return( CRYPT_BADPARM3 );
  140.  
  141.     while( blockCount-- )
  142.         {
  143.         /* Decrypt a block of data */
  144.         ideaCipher( buffer, buffer, ideaKey->dKey );
  145.  
  146.         /* Move on to next block of data */
  147.         buffer += IDEA_BLOCKSIZE;
  148.         }
  149.  
  150.     return( CRYPT_OK );
  151.     }
  152.  
  153. /* Encrypt/decrypt data in CBC mode */
  154.  
  155. int ideaEncryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  156.     {
  157.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  158.     int blockCount = noBytes / IDEA_BLOCKSIZE;
  159.  
  160.     /* Make sure the data length is a multiple of the block size */
  161.     if( noBytes % IDEA_BLOCKSIZE )
  162.         return( CRYPT_BADPARM3 );
  163.  
  164.     while( blockCount-- )
  165.         {
  166.         int i;
  167.  
  168.         /* XOR the buffer contents with the IV */
  169.         for( i = 0; i < IDEA_BLOCKSIZE; i++ )
  170.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  171.  
  172.         /* Encrypt a block of data */
  173.         ideaCipher( buffer, buffer, ideaKey->eKey );
  174.  
  175.         /* Shift ciphertext into IV */
  176.         memcpy( cryptInfo->currentIV, buffer, IDEA_BLOCKSIZE );
  177.  
  178.         /* Move on to next block of data */
  179.         buffer += IDEA_BLOCKSIZE;
  180.         }
  181.  
  182.     return( CRYPT_OK );
  183.     }
  184.  
  185. int ideaDecryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  186.     {
  187.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  188.     BYTE temp[ IDEA_BLOCKSIZE ];
  189.     int blockCount = noBytes / IDEA_BLOCKSIZE;
  190.  
  191.     /* Make sure the data length is a multiple of the block size */
  192.     if( noBytes % IDEA_BLOCKSIZE )
  193.         return( CRYPT_BADPARM3 );
  194.  
  195.     while( blockCount-- )
  196.         {
  197.         int i;
  198.  
  199.         /* Save the ciphertext */
  200.         memcpy( temp, buffer, IDEA_BLOCKSIZE );
  201.  
  202.         /* Decrypt a block of data */
  203.         ideaCipher( buffer, buffer, ideaKey->dKey );
  204.  
  205.         /* XOR the buffer contents with the IV */
  206.         for( i = 0; i < IDEA_BLOCKSIZE; i++ )
  207.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  208.  
  209.         /* Shift the ciphertext into the IV */
  210.         memcpy( cryptInfo->currentIV, temp, IDEA_BLOCKSIZE );
  211.  
  212.         /* Move on to next block of data */
  213.         buffer += IDEA_BLOCKSIZE;
  214.         }
  215.  
  216.     /* Clear the temporary buffer */
  217.     zeroise( temp, IDEA_BLOCKSIZE );
  218.  
  219.     return( CRYPT_OK );
  220.     }
  221.  
  222. /* Encrypt/decrypt data in CFB mode */
  223.  
  224. int ideaEncryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  225.     {
  226.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  227.     int i, ivCount = cryptInfo->ivCount;
  228.  
  229.     /* If there's any encrypted material left in the IV, use it now */
  230.     if( ivCount )
  231.         {
  232.         int bytesToUse;
  233.  
  234.         /* Find out how much material left in the encrypted IV we can use */
  235.         bytesToUse = IDEA_BLOCKSIZE - ivCount;
  236.         if( noBytes < bytesToUse )
  237.             bytesToUse = noBytes;
  238.  
  239.         /* Encrypt the data */
  240.         for( i = 0; i < bytesToUse; i++ )
  241.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  242.         memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse );
  243.  
  244.         /* Adjust the byte count and buffer position */
  245.         noBytes -= bytesToUse;
  246.         buffer += bytesToUse;
  247.         ivCount += bytesToUse;
  248.         }
  249.  
  250.     while( noBytes )
  251.         {
  252.         ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes;
  253.  
  254.         /* Encrypt the IV */
  255.         ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey );
  256.  
  257.         /* XOR the buffer contents with the encrypted IV */
  258.         for( i = 0; i < ivCount; i++ )
  259.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  260.  
  261.         /* Shift the ciphertext into the IV */
  262.         memcpy( cryptInfo->currentIV, buffer, ivCount );
  263.  
  264.         /* Move on to next block of data */
  265.         noBytes -= ivCount;
  266.         buffer += ivCount;
  267.         }
  268.  
  269.     /* Remember how much of the IV is still available for use */
  270.     cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE );
  271.  
  272.     return( CRYPT_OK );
  273.     }
  274.  
  275. /* Decrypt data in CFB mode.  Note that the transformation can be made
  276.    faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp
  277.    all in one loop */
  278.  
  279. int ideaDecryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  280.     {
  281.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  282.     BYTE temp[ IDEA_BLOCKSIZE ];
  283.     int i, ivCount = cryptInfo->ivCount;
  284.  
  285.     /* If there's any encrypted material left in the IV, use it now */
  286.     if( ivCount )
  287.         {
  288.         int bytesToUse;
  289.  
  290.         /* Find out how much material left in the encrypted IV we can use */
  291.         bytesToUse = IDEA_BLOCKSIZE - ivCount;
  292.         if( noBytes < bytesToUse )
  293.             bytesToUse = noBytes;
  294.  
  295.         /* Decrypt the data */
  296.         memcpy( temp, buffer, bytesToUse );
  297.         for( i = 0; i < bytesToUse; i++ )
  298.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  299.         memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse );
  300.  
  301.         /* Adjust the byte count and buffer position */
  302.         noBytes -= bytesToUse;
  303.         buffer += bytesToUse;
  304.         ivCount += bytesToUse;
  305.         }
  306.  
  307.     while( noBytes )
  308.         {
  309.         ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes;
  310.  
  311.         /* Encrypt the IV */
  312.         ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey );
  313.  
  314.         /* Save the ciphertext */
  315.         memcpy( temp, buffer, ivCount );
  316.  
  317.         /* XOR the buffer contents with the encrypted IV */
  318.         for( i = 0; i < ivCount; i++ )
  319.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  320.  
  321.         /* Shift the ciphertext into the IV */
  322.         memcpy( cryptInfo->currentIV, temp, ivCount );
  323.  
  324.         /* Move on to next block of data */
  325.         noBytes -= ivCount;
  326.         buffer += ivCount;
  327.         }
  328.  
  329.     /* Remember how much of the IV is still available for use */
  330.     cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE );
  331.  
  332.     /* Clear the temporary buffer */
  333.     zeroise( temp, IDEA_BLOCKSIZE );
  334.  
  335.     return( CRYPT_OK );
  336.     }
  337.  
  338. /* Encrypt/decrypt data in OFB mode */
  339.  
  340. int ideaEncryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  341.     {
  342.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  343.     int i, ivCount = cryptInfo->ivCount;
  344.  
  345.     /* If there's any encrypted material left in the IV, use it now */
  346.     if( ivCount )
  347.         {
  348.         int bytesToUse;
  349.  
  350.         /* Find out how much material left in the encrypted IV we can use */
  351.         bytesToUse = IDEA_BLOCKSIZE - ivCount;
  352.         if( noBytes < bytesToUse )
  353.             bytesToUse = noBytes;
  354.  
  355.         /* Encrypt the data */
  356.         for( i = 0; i < bytesToUse; i++ )
  357.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  358.  
  359.         /* Adjust the byte count and buffer position */
  360.         noBytes -= bytesToUse;
  361.         buffer += bytesToUse;
  362.         ivCount += bytesToUse;
  363.         }
  364.  
  365.     while( noBytes )
  366.         {
  367.         ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes;
  368.  
  369.         /* Encrypt the IV */
  370.         ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey );
  371.  
  372.         /* XOR the buffer contents with the encrypted IV */
  373.         for( i = 0; i < ivCount; i++ )
  374.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  375.  
  376.         /* Move on to next block of data */
  377.         noBytes -= ivCount;
  378.         buffer += ivCount;
  379.         }
  380.  
  381.     /* Remember how much of the IV is still available for use */
  382.     cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE );
  383.  
  384.     return( CRYPT_OK );
  385.     }
  386.  
  387. /* Decrypt data in OFB mode */
  388.  
  389. int ideaDecryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  390.     {
  391.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  392.     int i, ivCount = cryptInfo->ivCount;
  393.  
  394.     /* If there's any encrypted material left in the IV, use it now */
  395.     if( ivCount )
  396.         {
  397.         int bytesToUse;
  398.  
  399.         /* Find out how much material left in the encrypted IV we can use */
  400.         bytesToUse = IDEA_BLOCKSIZE - ivCount;
  401.         if( noBytes < bytesToUse )
  402.             bytesToUse = noBytes;
  403.  
  404.         /* Decrypt the data */
  405.         for( i = 0; i < bytesToUse; i++ )
  406.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  407.  
  408.         /* Adjust the byte count and buffer position */
  409.         noBytes -= bytesToUse;
  410.         buffer += bytesToUse;
  411.         ivCount += bytesToUse;
  412.         }
  413.  
  414.     while( noBytes )
  415.         {
  416.         ivCount = ( noBytes > IDEA_BLOCKSIZE ) ? IDEA_BLOCKSIZE : noBytes;
  417.  
  418.         /* Encrypt the IV */
  419.         ideaCipher( cryptInfo->currentIV, cryptInfo->currentIV, ideaKey->eKey );
  420.  
  421.         /* XOR the buffer contents with the encrypted IV */
  422.         for( i = 0; i < ivCount; i++ )
  423.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  424.  
  425.         /* Move on to next block of data */
  426.         noBytes -= ivCount;
  427.         buffer += ivCount;
  428.         }
  429.  
  430.     /* Remember how much of the IV is still available for use */
  431.     cryptInfo->ivCount = ( ivCount % IDEA_BLOCKSIZE );
  432.  
  433.     return( CRYPT_OK );
  434.     }
  435.  
  436. /* Encrypt/decrypt data in PCBC mode.  We have to carry along the previous
  437.    block's plaintext as well as the IV so we store it after the IV in the
  438.    buffer allocated for IV storage.  Initially the plaintextChain value will
  439.    be null as the IV buffer is zeroed on init, so we don't need to worry
  440.    about the special case of the first ciphertext block */
  441.  
  442. int ideaEncryptPCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  443.     {
  444.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  445.     BYTE *plaintextChain = cryptInfo->currentIV + IDEA_BLOCKSIZE;
  446.     BYTE temp[ IDEA_BLOCKSIZE ];
  447.     int blockCount = noBytes / IDEA_BLOCKSIZE;
  448.  
  449.     /* Make sure the data length is a multiple of the block size */
  450.     if( noBytes % IDEA_BLOCKSIZE )
  451.         return( CRYPT_BADPARM3 );
  452.  
  453.     while( blockCount-- )
  454.         {
  455.         int i;
  456.  
  457.         /* Remember the previous block's plaintext and copy the current
  458.            plaintext for chaining in the next iteration */
  459.         memcpy( temp, plaintextChain, IDEA_BLOCKSIZE );
  460.         memcpy( plaintextChain, buffer, IDEA_BLOCKSIZE );
  461.  
  462.         /* XOR the buffer contents with the IV and previous plaintext */
  463.         for( i = 0; i < IDEA_BLOCKSIZE; i++ )
  464.             buffer[ i ] ^= cryptInfo->currentIV[ i ] ^ temp[ i ];
  465.  
  466.         /* Encrypt a block of data */
  467.         ideaCipher( buffer, buffer, ideaKey->eKey );
  468.  
  469.         /* Shift ciphertext into IV */
  470.         memcpy( cryptInfo->currentIV, buffer, IDEA_BLOCKSIZE );
  471.  
  472.         /* Move on to next block of data */
  473.         buffer += IDEA_BLOCKSIZE;
  474.         }
  475.  
  476.     /* Clear the temporary buffer */
  477.     zeroise( temp, IDEA_BLOCKSIZE );
  478.  
  479.     return( CRYPT_OK );
  480.     }
  481.  
  482. int ideaDecryptPCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  483.     {
  484.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  485.     BYTE *plaintextChain = cryptInfo->currentIV + IDEA_BLOCKSIZE;
  486.     BYTE temp[ IDEA_BLOCKSIZE ];
  487.     int blockCount = noBytes / IDEA_BLOCKSIZE;
  488.  
  489.     /* Make sure the data length is a multiple of the block size */
  490.     if( noBytes % IDEA_BLOCKSIZE )
  491.         return( CRYPT_BADPARM3 );
  492.  
  493.     while( blockCount-- )
  494.         {
  495.         int i;
  496.  
  497.         /* Save the ciphertext */
  498.         memcpy( temp, buffer, IDEA_BLOCKSIZE );
  499.  
  500.         /* Decrypt a block of data */
  501.         ideaCipher( buffer, buffer, ideaKey->dKey );
  502.  
  503.         /* XOR the buffer contents with the IV and previous plaintext */
  504.         for( i = 0; i < IDEA_BLOCKSIZE; i++ )
  505.             buffer[ i ] ^= cryptInfo->currentIV[ i ] ^ plaintextChain[ i ];
  506.  
  507.         /* Shift the ciphertext into the IV and copy the current plaintext
  508.            for chaining in the next iteration */
  509.         memcpy( cryptInfo->currentIV, temp, IDEA_BLOCKSIZE );
  510.         memcpy( plaintextChain, buffer, IDEA_BLOCKSIZE );
  511.  
  512.         /* Move on to next block of data */
  513.         buffer += IDEA_BLOCKSIZE;
  514.         }
  515.  
  516.     /* Clear the temporary buffer */
  517.     zeroise( temp, IDEA_BLOCKSIZE );
  518.  
  519.     return( CRYPT_OK );
  520.     }
  521.  
  522. /****************************************************************************
  523. *                                                                            *
  524. *                            IDEA Key Management Routines                    *
  525. *                                                                            *
  526. ****************************************************************************/
  527.  
  528. /* Key schedule an IDEA key */
  529.  
  530. int ideaInitKey( CRYPT_INFO *cryptInfo )
  531.     {
  532.     IDEA_KEY *ideaKey = ( IDEA_KEY * ) cryptInfo->key;
  533.  
  534.     /* Generate an expanded IDEA key and its inverse */
  535.     ideaExpandKey( cryptInfo->userKey, ideaKey->eKey );
  536.     ideaInvertKey( ideaKey->eKey, ideaKey->dKey );
  537.  
  538.     return( CRYPT_OK );
  539.     }
  540.