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

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            cryptlib SHA Hash 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. /****************************************************************************
  21. *                                                                            *
  22. *                                SHA Self-test Routines                        *
  23. *                                                                            *
  24. ****************************************************************************/
  25.  
  26. /* Test the SHA output against the test vectors given in FIPS 180 and FIPS
  27.    180-1 (the first three values are the SHA results, the second three are
  28.    the SHA1 results).
  29.  
  30.    We skip the third test since this takes several seconds to execute, which
  31.    leads to an unacceptable delay in the library startup time */
  32.  
  33. void shaHashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer,
  34.                     int length, const HASH_STATE hashState );
  35.  
  36. static struct {
  37.     char *data;                        /* Data to hash */
  38.     int length;                        /* Length of data */
  39.     BYTE digest[ SHA_DIGESTSIZE ];    /* Digest of data */
  40.     } digestValues[] = {
  41.     { "abc", 3,
  42.       { 0x01, 0x64, 0xB8, 0xA9, 0x14, 0xCD, 0x2A, 0x5E,
  43.         0x74, 0xC4, 0xF7, 0xFF, 0x08, 0x2C, 0x4D, 0x97,
  44.         0xF1, 0xED, 0xF8, 0x80 } },
  45.     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
  46.       { 0xD2, 0x51, 0x6E, 0xE1, 0xAC, 0xFA, 0x5B, 0xAF,
  47.         0x33, 0xDF, 0xC1, 0xC4, 0x71, 0xE4, 0x38, 0x44,
  48.         0x9E, 0xF1, 0x34, 0xC8 } },
  49. /*    { "aaaaa...", 1000000L,
  50.       { 0x32, 0x32, 0xAF, 0xFA, 0x48, 0x62, 0x8A, 0x26,
  51.         0x65, 0x3B, 0x5A, 0xAA, 0x44, 0x54, 0x1F, 0xD9,
  52.         0x0D, 0x69, 0x06, 0x03 } }, */
  53.     { "abc", 3,
  54.       { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A,
  55.         0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C,
  56.         0x9C, 0xD0, 0xD8, 0x9D } },
  57.     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
  58.       { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
  59.         0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
  60.         0xE5, 0x46, 0x70, 0xF1 } },
  61. /*    { "aaaaa...", 1000000L,
  62.       { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4,
  63.         0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31,
  64.         0x65, 0x34, 0x01, 0x6F } }, */
  65.     { NULL, 0, { 0 } }
  66.     };
  67.  
  68. int shaSelfTest( void )
  69.     {
  70.     SHA_INFO shaInfo;
  71.     BYTE digest[ SHA_DIGESTSIZE ], *digestPtr;
  72.     int i;
  73.  
  74.     /* Test SHA against the test vectors given in FIPS 180.  We can't use the
  75.        internal shaHashBuffer() API for this since it defaults to SHA-1, so
  76.        we duplicate the functionality of shaHashBuffer() here */
  77.     shaInitial( &shaInfo );
  78.     shaUpdate( &shaInfo, ( BYTE * ) digestValues[ 0 ].data,
  79.                digestValues[ 0 ].length );
  80.     shaFinal( &shaInfo );
  81.     digestPtr = digest;
  82.     for( i = 0; i < SHA_DIGESTSIZE / 4; i++ )
  83.         {
  84.         mputBLong( digestPtr, shaInfo.digest[ i ] );
  85.         }
  86.     if( memcmp( digest, digestValues[ 0 ].digest, SHA_DIGESTSIZE ) )
  87.         return( CRYPT_SELFTEST );
  88.     shaInitial( &shaInfo );
  89.     shaUpdate( &shaInfo, ( BYTE * ) digestValues[ 1 ].data,
  90.                digestValues[ 1 ].length );
  91.     shaFinal( &shaInfo );
  92.     digestPtr = digest;
  93.     for( i = 0; i < SHA_DIGESTSIZE / 4; i++ )
  94.         {
  95.         mputBLong( digestPtr, shaInfo.digest[ i ] );
  96.         }
  97.     if( memcmp( digest, digestValues[ 1 ].digest, SHA_DIGESTSIZE ) )
  98.         return( CRYPT_SELFTEST );
  99.  
  100.     /* Test SHA against values given in FIPS 180-1 */
  101.     for( i = 2; digestValues[ i ].data != NULL; i++ )
  102.         {
  103.         shaHashBuffer( NULL, digest, ( BYTE * ) digestValues[ i ].data,
  104.                        digestValues[ i ].length, HASH_ALL );
  105.         if( memcmp( digest, digestValues[ i ].digest, SHA_DIGESTSIZE ) )
  106.             return( CRYPT_SELFTEST );
  107.         }
  108.  
  109.     return( CRYPT_OK );
  110.     }
  111.  
  112. /****************************************************************************
  113. *                                                                            *
  114. *                            Init/Shutdown Routines                            *
  115. *                                                                            *
  116. ****************************************************************************/
  117.  
  118. /* Perform auxiliary init and shutdown actions on an encryption context */
  119.  
  120. int shaInitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx )
  121.     {
  122.     CRYPT_INFO_SHA *cryptInfoExPtr = ( CRYPT_INFO_SHA * ) cryptInfoEx;
  123.     int status;
  124.  
  125.     /* Allocate memory for the SHA context within the encryption context */
  126.     if( cryptInfo->privateData != NULL )
  127.         return( CRYPT_INITED );
  128.     if( ( status = secureMalloc( &cryptInfo->privateData, sizeof( SHA_INFO ) ) ) != CRYPT_OK )
  129.         return( status );
  130.     if( cryptInfoExPtr->isSHA == CRYPT_USE_DEFAULT )
  131.         {
  132.         cryptInfo->privateUseDefaults = TRUE;
  133.         setSHAinfo( cryptInfo, FALSE );
  134.         }
  135.     else
  136.         setSHAinfo( cryptInfo, ( BOOLEAN ) cryptInfoExPtr->isSHA );
  137.     if( ( ( SHA_INFO * ) cryptInfo->privateData )->isSHA )
  138.         shaInitial( ( SHA_INFO * ) cryptInfo->privateData );
  139.     else
  140.         sha1Initial( ( SHA_INFO * ) cryptInfo->privateData );
  141.  
  142.     return( CRYPT_OK );
  143.     }
  144.  
  145. int shaInit( CRYPT_INFO *cryptInfo )
  146.     {
  147.     CRYPT_INFO_SHA cryptInfoEx;
  148.  
  149.     /* Use SHA1 */
  150.     memset( &cryptInfoEx, 0, sizeof( CRYPT_INFO_SHA ) );
  151.     cryptInfoEx.isSHA = CRYPT_USE_DEFAULT;
  152.  
  153.     /* Pass through to the extended setup routine */
  154.     return( shaInitEx( cryptInfo, &cryptInfoEx ) );
  155.     }
  156.  
  157. int shaEnd( CRYPT_INFO *cryptInfo )
  158.     {
  159.     /* Free any allocated memory */
  160.     secureFree( &cryptInfo->privateData );
  161.  
  162.     return( CRYPT_OK );
  163.     }
  164.  
  165. /****************************************************************************
  166. *                                                                            *
  167. *                                SHA Hash Routines                            *
  168. *                                                                            *
  169. ****************************************************************************/
  170.  
  171. /* Hash data using SHA */
  172.  
  173. int shaHash( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  174.     {
  175.     SHA_INFO *shaInfo = ( SHA_INFO * ) cryptInfo->privateData;
  176.  
  177.     /* If we've already called shaFinal(), we can't continue */
  178.     if( shaInfo->done )
  179.         return( CRYPT_COMPLETE );
  180.  
  181.     if( !noBytes )
  182.         {
  183.         if( shaInfo->isSHA )
  184.             shaFinal( shaInfo );
  185.         else
  186.             sha1Final( shaInfo );
  187.         }
  188.     else
  189.         {
  190.         if( shaInfo->isSHA )
  191.             shaUpdate( shaInfo, buffer, noBytes );
  192.         else
  193.             sha1Update( shaInfo, buffer, noBytes );
  194.         }
  195.  
  196.     return( CRYPT_OK );
  197.     }
  198.  
  199. /* Retrieve the hash value */
  200.  
  201. int shaGetData( CRYPT_INFO *cryptInfo, BYTE *buffer )
  202.     {
  203.     SHA_INFO *shaInfo = ( SHA_INFO * ) cryptInfo->privateData;
  204.     int i;
  205.  
  206.     /* Extract the digest into the memory buffer */
  207.     for( i = 0; i < SHA_DIGESTSIZE / 4; i++ )
  208.         {
  209.         mputBLong( buffer, shaInfo->digest[ i ] );
  210.         }
  211.  
  212.     return( ( shaInfo->done ) ? CRYPT_OK : CRYPT_INCOMPLETE );
  213.     }
  214.  
  215. /* Internal API: Hash a single block of memory without the overhead of
  216.    creating an encryption context.  This always uses SHA1 */
  217.  
  218. void shaHashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer,
  219.                     int length, const HASH_STATE hashState )
  220.     {
  221.     SHA_INFO *shaInfo = ( SHA_INFO * ) hashInfo, shaInfoBuffer;
  222.     int i;
  223.  
  224.     /* If the user has left it up to us to allocate the hash context buffer,
  225.        use the internal buffer */
  226.     if( shaInfo == NULL )
  227.         shaInfo = &shaInfoBuffer;
  228.  
  229.     if( hashState == HASH_ALL )
  230.         {
  231.         sha1Initial( shaInfo );
  232.         sha1Update( shaInfo, inBuffer, length );
  233.         sha1Final( shaInfo );
  234.         for( i = 0; i < SHA_DIGESTSIZE / 4; i++ )
  235.             {
  236.             mputBLong( outBuffer, shaInfo->digest[ i ] );
  237.             }
  238.         }
  239.     else
  240.         switch( hashState )
  241.             {
  242.             case HASH_START:
  243.                 sha1Initial( shaInfo );
  244.                 /* Drop through */
  245.  
  246.             case HASH_CONTINUE:
  247.                 sha1Update( shaInfo, inBuffer, length );
  248.                 break;
  249.  
  250.             case HASH_END:
  251.                 sha1Update( shaInfo, inBuffer, length );
  252.                 sha1Final( shaInfo );
  253.                 for( i = 0; i < SHA_DIGESTSIZE / 4; i++ )
  254.                     {
  255.                     mputBLong( outBuffer, shaInfo->digest[ i ] );
  256.                     }
  257.             }
  258.  
  259.     /* Clean up */
  260.     zeroise( &shaInfoBuffer, sizeof( SHA_INFO ) );
  261.     }
  262.  
  263. /****************************************************************************
  264. *                                                                            *
  265. *                            SHA Key Management Routines                        *
  266. *                                                                            *
  267. ****************************************************************************/
  268.  
  269. /* Get/set algorithm-specific parameters */
  270.  
  271. BOOLEAN getSHAinfo( const CRYPT_INFO *cryptInfo )
  272.     {
  273.     return( ( ( SHA_INFO * ) cryptInfo->privateData )->isSHA );
  274.     }
  275.  
  276. void setSHAinfo( CRYPT_INFO *cryptInfo, const BOOLEAN isSHA )
  277.     {
  278.     ( ( SHA_INFO * ) cryptInfo->privateData )->isSHA = isSHA;
  279.     }
  280.