home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / HPACK78S.ZIP / crypt / mdc.c < prev    next >
C/C++ Source or Header  |  1992-11-20  |  8KB  |  257 lines

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