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

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            MDC.C - MDC en/decryption code                    *
  4. *                                                                            *
  5. *         Written by Peter Gutmann, pgut1@cs.aukuni.ac.nz, September 1992        *
  6. *                    You can use this code in any way you want,                *
  7. *        although it'd be nice if you kept my name + contact address on it     *
  8. *                                                                            *
  9. ****************************************************************************/
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <time.h>
  14. #include "mdc.h"
  15.  
  16. /* Function to perform byte-reversal in an array of LONG's for little-endian
  17.    CPU's */
  18.  
  19. void longReverse( LONG *buffer, int byteCount );
  20.  
  21. /* Information needed in CFB mode:  The IV and the count of bytes already
  22.    processed in the current block */
  23.  
  24. BYTE iv[ BLOCKSIZE ];            /* CFB initialization vector */
  25. int ivCount;                    /* Count of bytes used in block */
  26.  
  27. /* A delay count for the key setup.  We repeat the key setup operation this
  28.    many times to slow it down.  The key setup is inherently non-
  29.    parallelizable, making it necessary to sequentially step through each
  30.    setup operation.  The value below has been chosen to give a delay of about
  31.    0.5s on a 10K-Dhrystone machine */
  32.  
  33. #define DELAYCOUNT        100
  34.  
  35. /****************************************************************************
  36. *                                                                            *
  37. *                MDC Key Generation and Encryption Routines                    *
  38. *                                                                            *
  39. ****************************************************************************/
  40.  
  41. /* The Mysterious Constants and IV are generated by running MD5 over a
  42.    buffer containing the user key, with the MD5 initial value being set to
  43.    the IV.  These are then substituted for the standard MD5 constants to
  44.    create the MDC function.  The buffer looks as follows:
  45.  
  46.    [ Key length: 16 bits ] [ Key: 2032 bits ]
  47.  
  48.    These 2048 bits are used for the MDC constants - the IV is the MD5
  49.    initial value.
  50.  
  51.    The transformation is in fact somewhat more complex than this, since MD5
  52.    uses both the 'input' and 'output' data in its transformation, and reduces
  53.    64 bytes of input to 16 bytes of output.  It works as follows:
  54.  
  55.    in[ 64 ] + out[ 16 ] -> out'[ 16 ]
  56.  
  57.    This problem is resolved by initially setting out[ 16 ] to the IV, and
  58.    in[ 64 ] to zeroes.  Then, once the MDC constants have been set, we set
  59.    in[ 64 ] to auxiliary key values derived from the key.  This means that
  60.    even chosen plaintext attacks can only resolve 16 of 80 bytes of input.
  61.    Thus the best attack possible is a 20%-chosen plaintext attack (128 bits
  62.    known, 512 bits unknown).
  63.  
  64.    We are transforming a 640-bit input value of which 128 bits are known, to
  65.    a 128-bit output value via the MDC tranformation, a one-way hash function
  66.    which is controlled by a user-supplied key */
  67.  
  68. BYTE auxKey[ MD5_BLOCKSIZE ];    /* The auxiliary key in[ 64 ] */
  69.  
  70. void initKey( BYTE *key, int keyLength, const BYTE *userIV )
  71.     {
  72.     BYTE keyData[ MD5_ROUNDS * sizeof( LONG ) ];
  73.     int delayCount;
  74.  
  75.     /* Copy the key information into the key data buffer */
  76.     memset( keyData, 0, sizeof( keyData ) );
  77.     keyData[ 0 ] = ( BYTE ) ( keyLength >> 8 );
  78.     keyData[ 1 ] = ( BYTE ) keyLength;
  79.     memcpy( keyData + sizeof( WORD ), key, keyLength );
  80.     ivCount = 0;
  81.  
  82.     /* Set up the IV intermediate.  The MD5 transformation uses both the
  83.        source and destination value to produce the output value (ie
  84.        MDC( a, b ) transforms a and b to give b'), so we simply set b, the
  85.        temporary intermediate, to the IV, and a, the auxKey, to all zeroes */
  86.     memcpy( iv, userIV, IV_SIZE );
  87.     memcpy( iv + IV_SIZE, userIV, IV_SIZE );
  88.     memset( auxKey, 0, MD5_BLOCKSIZE );
  89.  
  90.     /* Set the Mysterious Constants to the MD5 values and "encrypt" the
  91.        keyData with them, then set the Mysterious Constants to these values.
  92.        Note that the act of encryption also sets up the IV */
  93.     MD5SetConst( NULL );
  94.     for( delayCount = 0; delayCount < DELAYCOUNT; delayCount++ )
  95.         {
  96.         encryptCFB( keyData, MD5_ROUNDS * sizeof( LONG ) );
  97.         MD5SetConst( keyData );
  98.         }
  99.     ivCount = 0;
  100.  
  101.     /* Now set the auxiliary key data to the Mysterious Constants encrypted
  102.        with themselves */
  103.     encryptCFB( keyData, MD5_BLOCKSIZE );
  104.     memcpy( auxKey, keyData, MD5_BLOCKSIZE );
  105. #ifdef LITTLE_ENDIAN
  106.     longReverse( ( LONG * ) auxKey, MD5_BLOCKSIZE );
  107. #endif /* LITTLE_ENDIAN */
  108.     ivCount = 0;
  109.  
  110.     /* Finally, wipe the keyData */
  111.     memset( keyData, 0, sizeof( keyData ) );
  112.     }
  113.  
  114. /* Save and restore the current states of the encryption */
  115.  
  116. static BYTE savedIV[ BLOCKSIZE ];
  117. static int savedIvCount;
  118.  
  119. void saveCryptState( void )
  120.     {
  121.     memcpy( savedIV, iv, BLOCKSIZE );
  122.     savedIvCount = ivCount;
  123.     }
  124.  
  125. void restoreCryptState( void )
  126.     {
  127.     memcpy( iv, savedIV, BLOCKSIZE );
  128.     ivCount = savedIvCount;
  129.     }
  130.  
  131. /* Get the IV value.  It doesn't matter much what it is, as long as it's
  132.    completely different for each call */
  133.  
  134. BYTE *getIV( void )
  135.     {
  136.     static BOOLEAN initialised = FALSE;
  137.     static BYTE randomIV[ BLOCKSIZE ];
  138.  
  139.     if( !initialised )
  140.         {
  141.         /* Seed the data with a value which is guaranteed to be different
  142.            each time (unless the entire program is rerun more than twice a
  143.            second, which is doubtful) */
  144.         MD5SetConst( NULL );
  145.         memset( randomIV, 0, BLOCKSIZE );
  146.         time( ( time_t * ) randomIV );
  147.         initialised = TRUE;
  148.         }
  149.  
  150.     /* Shuffle the bits.  It doesn't really matter whether we use MD5 or MDC
  151.        constants here since all we want to do is shuffle them */
  152.     mdcTransform( randomIV );
  153.     return( randomIV );
  154.     }
  155.  
  156. /****************************************************************************
  157. *                                                                            *
  158. *                        Cipher Feedback Mode Routines                        *
  159. *                                                                            *
  160. ****************************************************************************/
  161.  
  162. /* Encrypt data in CFB mode */
  163.  
  164. void encryptCFB( BYTE *buffer, int noBytes )
  165.     {
  166.     int bytesToUse, i;
  167.  
  168.     if( ivCount )
  169.         {
  170.         /* Use any material left in the encrypted IV */
  171.         bytesToUse = BLOCKSIZE - ivCount;
  172.         if( noBytes < bytesToUse )
  173.             bytesToUse = noBytes;
  174.         for( i = 0; i < bytesToUse; i++ )
  175.             buffer[ i ] ^= iv[ i + ivCount ];
  176.         memcpy( iv + ivCount, buffer, bytesToUse );
  177.         noBytes -= bytesToUse;
  178.         buffer += bytesToUse;
  179.         ivCount += bytesToUse;
  180.         }
  181.  
  182.     while( noBytes )
  183.         {
  184.         ivCount = ( noBytes > BLOCKSIZE ) ? BLOCKSIZE : noBytes;
  185.  
  186.         /* Encrypt the IV */
  187.         mdcTransform( iv );
  188.  
  189.         /* XOR the buffer contents with the encrypted IV */
  190.         for( i = 0; i < ivCount; i++ )
  191.             buffer[ i ] ^= iv[ i ];
  192.  
  193.         /* Shift ciphertext into IV */
  194.         memcpy( iv, buffer, ivCount );
  195.  
  196.         /* Move on to next block of data */
  197.         noBytes -= ivCount;
  198.         buffer += ivCount;
  199.         }
  200.     }
  201.  
  202. /* Decrypt data in CFB mode */
  203.  
  204. void decryptCFB( BYTE *buffer, int noBytes )
  205.     {
  206.     int bytesToUse, i;
  207.     BYTE temp[ BLOCKSIZE ];
  208.  
  209.     if( ivCount )
  210.         {
  211.         /* Use any material left in the encrypted IV */
  212.         bytesToUse = BLOCKSIZE - ivCount;
  213.         if( noBytes < bytesToUse )
  214.             bytesToUse = noBytes;
  215.         memcpy( temp, buffer, bytesToUse );
  216.         for( i = 0; i < bytesToUse; i++ )
  217.             buffer[ i ] ^= iv[ i + ivCount ];
  218.         memcpy( iv + ivCount, temp, bytesToUse );
  219.         noBytes -= bytesToUse;
  220.         buffer += bytesToUse;
  221.         ivCount += bytesToUse;
  222.         }
  223.  
  224.     while( noBytes )
  225.         {
  226.         ivCount = ( noBytes > BLOCKSIZE ) ? BLOCKSIZE : noBytes;
  227.  
  228.         /* Encrypt the IV */
  229.         mdcTransform( iv );
  230.  
  231.         /* Save ciphertext */
  232.         memcpy( temp, buffer, ivCount );
  233.  
  234.         /* XOR the buffer contents with the encrypted IV */
  235.         for( i = 0; i < ivCount; i++ )
  236.             buffer[ i ] ^= iv[ i ];
  237.  
  238.         /* Shift ciphertext into IV */
  239.         memcpy( iv, temp, ivCount );
  240.  
  241.         /* Move on to next block of data */
  242.         noBytes -= ivCount;
  243.         buffer += ivCount;
  244.         }
  245.     }
  246.