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

  1. /****************************************************************************
  2. *                                                                            *
  3. *                        cryptlib MDC/SHS 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 "sha.h"
  16. #else
  17.   #include "hash/sha.h"
  18. #endif /* Compiler-specific includes */
  19.  
  20. /* The default key setup iteration count.  This gives roughly 0.5s delay on
  21.    a 10K dhrystone machine */
  22.  
  23. #define MDCSHS_DEFAULT_ITERATIONS    200
  24.  
  25. /* The size of an MDCSHS key.  If we're running on a machine with a > 32
  26.    bit wordsize, we need to store the key as an array of words rather than
  27.    an array of bytes which is cast to an array of words */
  28.  
  29. #ifdef _BIG_WORDS
  30.   #define MDCSHS_KEY_WORDS        ( SHA_DATASIZE / 4 )
  31.   #define MDCSHS_KEYSIZE        ( MDCSHS_KEY_WORDS * sizeof( LONG ) )
  32. #else
  33.   #define MDCSHS_KEYSIZE        SHA_DATASIZE
  34. #endif /* _BIG_WORDS */
  35.  
  36. /****************************************************************************
  37. *                                                                            *
  38. *                            MDC/SHS Self-test Routines                        *
  39. *                                                                            *
  40. ****************************************************************************/
  41.  
  42. /* Test the SHA output against the test vectors given in FIPS 180 */
  43.  
  44. static LONG shaTestResults[][ SHA_DIGESTSIZE / 4 ] = {
  45.     { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L },
  46.     { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L },
  47.     { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L }
  48.     };
  49.  
  50. static int compareSHSresults( SHA_INFO *shaInfo, int shaTestLevel )
  51.     {
  52.     int i;
  53.  
  54.     /* Compare the returned digest and required values */
  55.     for( i = 0; i < SHA_DIGESTSIZE / 4; i++ )
  56.         if( shaInfo->digest[ i ] != shaTestResults[ shaTestLevel ][ i ] )
  57.             return( CRYPT_SELFTEST );
  58.     return( CRYPT_OK );
  59.     }
  60.  
  61. int mdcshsSelfTest( void )
  62.     {
  63.     SHA_INFO shaInfo;
  64.  
  65.     /* Test SHA against values given in FIPS 180 */
  66.     shaInitial( &shaInfo );
  67.     shaUpdate( &shaInfo, ( BYTE * ) "abc", 3 );
  68.     shaFinal( &shaInfo );
  69.     if( compareSHSresults( &shaInfo, 0 ) != CRYPT_OK )
  70.         return( CRYPT_SELFTEST );
  71.     shaInitial( &shaInfo );
  72.     shaUpdate( &shaInfo, ( BYTE * ) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 );
  73.     shaFinal( &shaInfo );
  74.     if( compareSHSresults( &shaInfo, 1 ) != CRYPT_OK )
  75.         return( CRYPT_SELFTEST );
  76. #if 0
  77.     /* We skip the third test since this takes several seconds to execute,
  78.        which leads to an unacceptable delay in the library startup time */
  79.     shaInitial( &shaInfo );
  80.     for( i = 0; i < 15625; i++ )
  81.         shaUpdate( &shaInfo, ( BYTE * ) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 );
  82.     shaFinal( &shaInfo );
  83.     if( compareSHSresults( &shaInfo, 2 ) != CRYPT_OK )
  84.         return( CRYPT_SELFTEST );
  85. #endif /* 0 */
  86.  
  87.     return( CRYPT_OK );
  88.     }
  89.  
  90. /****************************************************************************
  91. *                                                                            *
  92. *                            Init/Shutdown Routines                            *
  93. *                                                                            *
  94. ****************************************************************************/
  95.  
  96. /* Perform auxiliary init and shutdown actions on an encryption context */
  97.  
  98. int mdcshsInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx )
  99.     {
  100.     CRYPT_INFO_MDCSHS *cryptInfoExPtr = ( CRYPT_INFO_MDCSHS * ) cryptInfoEx;
  101.     int status;
  102.  
  103.     /* Allocate memory for the key and the algorithm-specific data within
  104.        the crypt context and set up any pointers we need */
  105.     if( cryptInfo->key != NULL || cryptInfo->privateData != NULL )
  106.         return( CRYPT_INITED );
  107.     if( ( status = secureMalloc( &cryptInfo->key, MDCSHS_KEYSIZE ) ) != CRYPT_OK )
  108.         return( status );
  109.     if( cryptInfoExPtr->keySetupIterations == CRYPT_USE_DEFAULT )
  110.         cryptInfo->privateUseDefaults = TRUE;
  111.     if( ( status = secureMalloc( &cryptInfo->privateData, sizeof( CRYPT_INFO_MDCSHS ) ) ) != CRYPT_OK )
  112.         {
  113.         secureFree( &cryptInfo->key );
  114.         return( status );
  115.         }
  116.     if( cryptInfoExPtr->keySetupIterations == CRYPT_USE_DEFAULT )
  117.         setMDCSHSinfo( cryptInfo, MDCSHS_DEFAULT_ITERATIONS );
  118.     else
  119.         setMDCSHSinfo( cryptInfo, cryptInfoExPtr->keySetupIterations );
  120.     cryptInfo->keyLength = MDCSHS_KEYSIZE;
  121.  
  122.     return( CRYPT_OK );
  123.     }
  124.  
  125. int mdcshsInit( CRYPT_INFO *cryptInfo )
  126.     {
  127.     CRYPT_INFO_MDCSHS cryptInfoEx;
  128.  
  129.     /* Use the default number of setup iterations */
  130.     memset( &cryptInfoEx, 0, sizeof( CRYPT_INFO_MDCSHS ) );
  131.     cryptInfoEx.keySetupIterations = CRYPT_USE_DEFAULT;
  132.  
  133.     /* Pass through to the extended setup routine */
  134.     return( mdcshsInitEx( cryptInfo, &cryptInfoEx ) );
  135.     }
  136.  
  137. int mdcshsEnd( CRYPT_INFO *cryptInfo )
  138.     {
  139.     /* Free any allocated memory */
  140.     secureFree( &cryptInfo->key );
  141.     secureFree( &cryptInfo->privateData );
  142.  
  143.     return( CRYPT_OK );
  144.     }
  145.  
  146. /****************************************************************************
  147. *                                                                            *
  148. *                        MDC/SHS En/Decryption Routines                        *
  149. *                                                                            *
  150. ****************************************************************************/
  151.  
  152. /* The SHS transformation.  What we're doing here isn't totally correct since
  153.    we're forcing the IV to big-endian, transforming it, and returning it to
  154.    the local endianness, rather than changing the data to the local
  155.    endianness and back as we should.  However doing it correctly isn't really
  156.    possible since we can only endianness-swap 4 bytes at a time which
  157.    precludes swapping the data.  The use of the temp variable when the IV is
  158.    copied back in the _BIG_WORDS case is to eliminate multiple memory
  159.    accesses when the four bytes are extracted from ivLong[ n ], since many
  160.    compilers won't risk optimising the loads due to possible aliasing
  161.    problems.  We declare the necessary ivLong array as part of the actual
  162.    encryption function to save it having to be instantiated for every use
  163.    of shsTransform() */
  164.  
  165. #ifdef _BIG_WORDS
  166.   #define shaTransform(cI)  { \
  167.                             LONG temp; \
  168.                             BYTE *ivPtr; \
  169.                             ivPtr = ( BYTE * ) cI->currentIV; \
  170.                             for( i = 0; i < SHA_DIGESTSIZE / 4; i++ ) \
  171.                                 { \
  172.                                 ivLong[ i ] = mgetBLong( ivPtr ); \
  173.                                 } \
  174.                             SHATransform( ivLong, cI->key ); \
  175.                             ivPtr = ( BYTE * ) cI->currentIV; \
  176.                             for( i = 0; i < SHA_DIGESTSIZE / 4; i++ ) \
  177.                                 { \
  178.                                 temp = ivLong[ i ]; \
  179.                                 mputBLong( ivPtr, temp ); \
  180.                                 } \
  181.                             }
  182. #else
  183.   #define shaTransform(cI)    bigToLittleLong( ( LONG * ) cI->currentIV, SHA_DIGESTSIZE ); \
  184.                             SHATransform( ( LONG * ) cI->currentIV, ( LONG * ) cI->key ); \
  185.                             bigToLittleLong( ( LONG * ) cI->currentIV, SHA_DIGESTSIZE );
  186. #endif /* _BIG_WORDS */
  187.  
  188. void SHATransform( LONG *digest, LONG *data );
  189.  
  190. /* Encrypt data in CFB mode */
  191.  
  192. int mdcshsEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  193.     {
  194.     int i, ivCount = cryptInfo->ivCount;
  195. #ifdef _BIG_WORDS
  196.     LONG ivLong[ SHA_DIGESTSIZE / 4 ];
  197. #endif /* _BIG_WORDS */
  198.  
  199.     /* If there's any encrypted material left in the IV, use it now */
  200.     if( ivCount )
  201.         {
  202.         int bytesToUse;
  203.  
  204.         /* Find out how much material left in the encrypted IV we can use */
  205.         bytesToUse = SHA_DIGESTSIZE - ivCount;
  206.         if( noBytes < bytesToUse )
  207.             bytesToUse = noBytes;
  208.  
  209.         /* Encrypt the data */
  210.         for( i = 0; i < bytesToUse; i++ )
  211.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  212.         memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse );
  213.  
  214.         /* Adjust the byte count and buffer position */
  215.         noBytes -= bytesToUse;
  216.         buffer += bytesToUse;
  217.         ivCount += bytesToUse;
  218.         }
  219.  
  220.     while( noBytes )
  221.         {
  222.         ivCount = ( noBytes > SHA_DIGESTSIZE ) ? SHA_DIGESTSIZE : noBytes;
  223.  
  224.         /* Encrypt the IV */
  225.         shaTransform( cryptInfo );
  226.  
  227.         /* XOR the buffer contents with the encrypted IV */
  228.         for( i = 0; i < ivCount; i++ )
  229.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  230.  
  231.         /* Shift the ciphertext into the IV */
  232.         memcpy( cryptInfo->currentIV, buffer, ivCount );
  233.  
  234.         /* Move on to next block of data */
  235.         noBytes -= ivCount;
  236.         buffer += ivCount;
  237.         }
  238.  
  239.     /* Remember how much of the IV is still available for use */
  240.     cryptInfo->ivCount = ( ivCount % SHA_DIGESTSIZE );
  241.  
  242.     return( CRYPT_OK );
  243.     }
  244.  
  245. /* Decrypt data in CFB mode.  Note that the transformation can be made
  246.    faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp
  247.    all in one loop */
  248.  
  249. int mdcshsDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  250.     {
  251.     BYTE temp[ SHA_DIGESTSIZE ];
  252.     int i, ivCount = cryptInfo->ivCount;
  253. #ifdef _BIG_WORDS
  254.     LONG ivLong[ SHA_DIGESTSIZE / 4 ];
  255. #endif /* _BIG_WORDS */
  256.  
  257.     /* If there's any encrypted material left in the IV, use it now */
  258.     if( ivCount )
  259.         {
  260.         int bytesToUse;
  261.  
  262.         /* Find out how much material left in the encrypted IV we can use */
  263.         bytesToUse = SHA_DIGESTSIZE - ivCount;
  264.         if( noBytes < bytesToUse )
  265.             bytesToUse = noBytes;
  266.  
  267.         /* Decrypt the data */
  268.         memcpy( temp, buffer, bytesToUse );
  269.         for( i = 0; i < bytesToUse; i++ )
  270.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  271.         memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse );
  272.  
  273.         /* Adjust the byte count and buffer position */
  274.         noBytes -= bytesToUse;
  275.         buffer += bytesToUse;
  276.         ivCount += bytesToUse;
  277.         }
  278.  
  279.     while( noBytes )
  280.         {
  281.         ivCount = ( noBytes > SHA_DIGESTSIZE ) ? SHA_DIGESTSIZE : noBytes;
  282.  
  283.         /* Encrypt the IV */
  284.         shaTransform( cryptInfo );
  285.  
  286.         /* Save the ciphertext */
  287.         memcpy( temp, buffer, ivCount );
  288.  
  289.         /* XOR the buffer contents with the encrypted IV */
  290.         for( i = 0; i < ivCount; i++ )
  291.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  292.  
  293.         /* Shift the ciphertext into the IV */
  294.         memcpy( cryptInfo->currentIV, temp, ivCount );
  295.  
  296.         /* Move on to next block of data */
  297.         noBytes -= ivCount;
  298.         buffer += ivCount;
  299.         }
  300.  
  301.     /* Remember how much of the IV is still available for use */
  302.     cryptInfo->ivCount = ( ivCount % SHA_DIGESTSIZE );
  303.  
  304.     /* Clear the temporary buffer */
  305.     zeroise( temp, SHA_DIGESTSIZE );
  306.  
  307.     return( CRYPT_OK );
  308.     }
  309.  
  310. /****************************************************************************
  311. *                                                                            *
  312. *                        MDC/SHS Key Management Routines                        *
  313. *                                                                            *
  314. ****************************************************************************/
  315.  
  316. /* Get/set algorithm-specific parameters */
  317.  
  318. int getMDCSHSinfo( const CRYPT_INFO *cryptInfo )
  319.     {
  320.     return( ( ( CRYPT_INFO_MDCSHS * ) cryptInfo->privateData )->keySetupIterations );
  321.     }
  322.  
  323. void setMDCSHSinfo( CRYPT_INFO *cryptInfo, const int keySetupIterations )
  324.     {
  325.     ( ( CRYPT_INFO_MDCSHS * ) cryptInfo->privateData )->keySetupIterations = keySetupIterations;
  326.     }
  327.  
  328. /* The size of the key buffer.  Note that increasing this value will result
  329.    in a significant increase in the setup time, so it will be necessary to
  330.    make a corresponding decrease in the iteration count */
  331.  
  332. #define KEYBUFFER_SIZE        256
  333.  
  334. /* Initialise an MDC/SHS key.  This is done by repeatedly encrypting the
  335.    user key as follows:
  336.  
  337.     IV <- 0
  338.     key <- 0
  339.     repeat
  340.         encrypt userkey with key
  341.         key <- userkey
  342.  
  343.    The IV is updated transparently as part of the encryption process */
  344.  
  345. int mdcshsInitKey( CRYPT_INFO *cryptInfo )
  346.     {
  347.     BYTE keyData[ KEYBUFFER_SIZE ];
  348.     int keySetupIterations = ( ( CRYPT_INFO_MDCSHS * ) cryptInfo->privateData )->keySetupIterations;
  349.     int count;
  350.  
  351.     /* Copy the key information into the key data buffer.  We silently
  352.        truncate the key length to the size of the buffer, but this usually
  353.        is some hundreds of bytes so it shouldn't be a problem.
  354.        We also correct the endianness of the keyData at this point.  From
  355.        here on all data is in the local endianness format so there is no need
  356.        for further corrections */
  357.     memset( keyData, 0, KEYBUFFER_SIZE );
  358.     keyData[ 0 ] = ( BYTE ) ( cryptInfo->userKeyLength >> 8 );
  359.     keyData[ 1 ] = ( BYTE ) cryptInfo->userKeyLength;
  360.     cryptInfo->userKeyLength %= KEYBUFFER_SIZE - 2;
  361.     memcpy( keyData + 2, cryptInfo->userKey, cryptInfo->userKeyLength );
  362.  
  363.     /* Set the initial key and IV to null */
  364.     memset( cryptInfo->currentIV, 0, MAX_IVSIZE );
  365.     memset( cryptInfo->key, 0, MDCSHS_KEYSIZE );
  366.  
  367.     /* Convert the endianness of the input data from the canonical form to
  368.        the local form */
  369.     bigToLittleLong( ( LONG * ) keyData, KEYBUFFER_SIZE );
  370.  
  371.     /* "Encrypt" the keyData with the given IV and then set the key to
  372.        the encrypted keyData.  The act of encryption also sets the IV.
  373.        This is particularly important in the case of SHA, since although only
  374.        the first SHA_DATASIZE bytes are copied into the key, the IV is
  375.        still affected by the entire buffer */
  376.     for( count = 0; count < keySetupIterations; count++ )
  377.         {
  378.         mdcshsEncrypt( cryptInfo, keyData, KEYBUFFER_SIZE );
  379.         copyToLong( cryptInfo->key, keyData, SHA_DATASIZE );
  380.         }
  381.  
  382.     /* Perform one last copy in case they've specified zero iterations and
  383.        the loop was never executed.  For MDCSHS, the transformed key is the
  384.        same as the raw encryption key, so we just copy it over */
  385.     copyToLong( cryptInfo->key, keyData, SHA_DATASIZE );
  386.  
  387. #if 0
  388.     /* Set the key check byte to the last WORD of the encrypted keyData.
  389.        This is never used for anything (it's 191 bytes past the end of the
  390.        last value used to set the key) so we're not revealing much to an
  391.        attacker */
  392.     bigToLittleLong( ( LONG * ) ( keyData + KEYBUFFER_SIZE - sizeof( LONG ) ), sizeof( LONG ) );
  393.     cryptInfo->keyCheck = ( ( WORD ) keyData[ KEYBUFFER_SIZE - 2 ] << 8 ) | \
  394.                                    keyData[ KEYBUFFER_SIZE - 1 ];
  395. #endif /* 0 */
  396.  
  397.     /* Wipe the keyData */
  398.     zeroise( keyData, KEYBUFFER_SIZE );
  399.  
  400.     return( CRYPT_OK );
  401.     }
  402.  
  403. /* Initialise the IV */
  404.  
  405. int mdcshsInitIV( CRYPT_INFO *cryptInfo )
  406.     {
  407.     /* Convert the working IV from the canonical to the internal form */
  408.     bigToLittleLong( ( LONG * ) cryptInfo->currentIV, MAX_IVSIZE );
  409.  
  410.     return( CRYPT_OK );
  411.     }
  412.