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

  1. /****************************************************************************
  2. *                                                                            *
  3. *                        cryptlib Internal API Routines                        *
  4. *                        Copyright Peter Gutmann 1992-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <ctype.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <time.h>
  12. #include "crypt.h"
  13. #ifdef INC_ALL
  14.   #include "md2.h"
  15.   #include "md4.h"
  16.   #include "md5.h"
  17.   #include "ripemd.h"
  18.   #include "sha.h"
  19.   #include "asn1objs.h"
  20. #else
  21.   #include "hash/md2.h"
  22.   #include "hash/md4.h"
  23.   #include "hash/md5.h"
  24.   #include "hash/ripemd.h"
  25.   #include "hash/sha.h"
  26.   #include "keymgmt/asn1objs.h"
  27. #endif /* Compiler-specific includes */
  28.  
  29. /****************************************************************************
  30. *                                                                            *
  31. *                            Library-Wide Config Options                        *
  32. *                                                                            *
  33. ****************************************************************************/
  34.  
  35. /* Various default settings */
  36.  
  37. #define DEFAULT_MEMLOCK_MODE        CRYPT_MEMORY_LOCK
  38. #define DEFAULT_EXPORT_KEYCOOKIES    TRUE
  39. #define DEFAULT_EXPORT_SIGCOOKIES    FALSE
  40. #define DEFAULT_USE_OAEP            FALSE
  41. #define DEFAULT_KEYSET_USERID        "Name"
  42. #define DEFAULT_KEYSET_KEYID        "Key ID"
  43. #define DEFAULT_KEYSET_PUBLICKEY    "Public Key"
  44. #define DEFAULT_KEYSET_PRIVATEKEY    "Private Key"
  45.  
  46. /* Whether to not lock pages, lock pages and fail silently, or lock pages and
  47.    fail with an error code */
  48.  
  49. static int memoryLockType = DEFAULT_MEMLOCK_MODE;
  50.  
  51. /* Whether key and signature cookies should be exported */
  52.  
  53. static BOOLEAN exportKeyCookies = DEFAULT_EXPORT_KEYCOOKIES;
  54. static BOOLEAN exportSigCookies = DEFAULT_EXPORT_SIGCOOKIES;
  55.  
  56. /* Whether to use Bellare-Rogaway optimal asymmetric encryption padding */
  57.  
  58. static BOOLEAN useOAEP = DEFAULT_USE_OAEP;
  59.  
  60. /* The names of the tables in the key database */
  61.  
  62. static char *keysetUserID = NULL;
  63. static char *keysetKeyID = NULL;
  64. static char *keysetPublicKey = NULL;
  65. static char *keysetPrivateKey = NULL;
  66.  
  67. /* Functions to set/query the config options */
  68.  
  69. void setOptionExportKeyCookie( const BOOLEAN option )
  70.     {
  71.     exportKeyCookies = option;
  72.     }
  73.  
  74. BOOLEAN getOptionExportKeyCookie( void )
  75.     {
  76.     return( exportKeyCookies );
  77.     }
  78.  
  79. void setOptionExportSigCookie( const BOOLEAN option )
  80.     {
  81.     exportSigCookies = option;
  82.     }
  83.  
  84. BOOLEAN getOptionExportSigCookie( void )
  85.     {
  86.     return( exportSigCookies );
  87.     }
  88.  
  89. void setOptionUseOAEP( const BOOLEAN option )
  90.     {
  91.     useOAEP = option;
  92.     }
  93.  
  94. BOOLEAN getOptionUseOAEP( void )
  95.     {
  96.     return( useOAEP );
  97.     }
  98.  
  99. void setOptionKeysetNames( const CRYPT_IOCTLINFO_KEYSETNAMES *keysetNames )
  100.     {
  101.     /* Set the appropriate table name to the default (if the input value is
  102.        CRYPT_USE_DEFAULT) or the given string if otherwise */
  103.     if( keysetNames->userID != ( char * ) CRYPT_UNUSED )
  104.         {
  105.         if( keysetUserID !=  NULL )
  106.             free( keysetUserID );
  107.         keysetUserID = ( keysetNames->userID == ( char * ) CRYPT_USE_DEFAULT ) ? \
  108.                        NULL : keysetNames->userID;
  109.         }
  110.     if( keysetNames->keyID != ( char * ) CRYPT_UNUSED )
  111.         {
  112.         if( keysetKeyID !=  NULL )
  113.             free( keysetKeyID );
  114.         keysetKeyID = ( keysetNames->keyID == ( char * ) CRYPT_USE_DEFAULT ) ? \
  115.                        NULL : keysetNames->keyID;
  116.         }
  117.     if( keysetNames->publicKey != ( char * ) CRYPT_UNUSED )
  118.         {
  119.         if( keysetPublicKey !=  NULL )
  120.             free( keysetPublicKey );
  121.         keysetKeyID = ( keysetNames->publicKey == ( char * ) CRYPT_USE_DEFAULT ) ? \
  122.                        NULL : keysetNames->publicKey;
  123.         }
  124.     if( keysetNames->privateKey != ( char * ) CRYPT_UNUSED )
  125.         {
  126.         if( keysetPrivateKey !=  NULL )
  127.             free( keysetPrivateKey );
  128.         keysetKeyID = ( keysetNames->privateKey == ( char * ) CRYPT_USE_DEFAULT ) ? \
  129.                        NULL : keysetNames->privateKey;
  130.         }
  131.     }
  132.  
  133. void getOptionKeysetNames( CRYPT_IOCTLINFO_KEYSETNAMES *keysetNames )
  134.     {
  135.     keysetNames->userID = ( keysetUserID == NULL ) ? \
  136.                             DEFAULT_KEYSET_USERID : keysetUserID;
  137.     keysetNames->keyID = ( keysetKeyID == NULL ) ? \
  138.                             DEFAULT_KEYSET_KEYID : keysetKeyID;
  139.     keysetNames->publicKey = ( keysetPublicKey == NULL ) ? \
  140.                             DEFAULT_KEYSET_PUBLICKEY : keysetPublicKey;
  141.     keysetNames->privateKey = ( keysetPrivateKey == NULL ) ? \
  142.                             DEFAULT_KEYSET_PRIVATEKEY : keysetPrivateKey;
  143.     }
  144.  
  145. int getOptionHashAlgo( void )
  146.     {
  147.     return( CRYPT_ALGO_SHA );
  148.     }
  149.  
  150. int getOptionPKCAlgo( void )
  151.     {
  152.     return( CRYPT_ALGO_RSA );
  153.     }
  154.  
  155. int getOptionCryptAlgo( void )
  156.     {
  157.     return( CRYPT_ALGO_3DES );
  158.     }
  159.  
  160. int getOptionCryptMode( void )
  161.     {
  162.     return( CRYPT_MODE_CFB );
  163.     }
  164.  
  165. /****************************************************************************
  166. *                                                                            *
  167. *                                Internal API Functions                        *
  168. *                                                                            *
  169. ****************************************************************************/
  170.  
  171. /* Get a nonce  It doesn't matter much what it is, as long as it's completely
  172.    different for each call */
  173.  
  174. void getNonce( void *nonce, int nonceLength )
  175.     {
  176.     static BOOLEAN initialised = FALSE;
  177.     static BYTE nonceBuffer[ CRYPT_MAX_HASHSIZE ];
  178.     int hashInfoSize, hashInputSize, hashOutputSize;
  179.     HASHFUNCTION hashFunction;
  180.     BYTE *noncePtr = nonce;
  181.  
  182.     if( !initialised )
  183.         {
  184.         /* Seed the data with a value which is guaranteed to be different
  185.            each time (unless the entire program is rerun more than twice a
  186.            second, which is doubtful) */
  187.         memset( nonceBuffer, 0, CRYPT_MAX_HASHSIZE );
  188.         time( ( time_t * ) nonceBuffer );
  189.         initialised = TRUE;
  190.         }
  191.  
  192.     /* Get the hash algorithm information and repeatedly shuffle the bits and
  193.        copy them to the output buffer until it's full */
  194.     if( !getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashInputSize,
  195.                             &hashOutputSize, &hashInfoSize ) )
  196.         {
  197.         memset( nonce, '?', nonceLength );
  198.         return;                        /* API error, should never occur */
  199.         }
  200.     while( nonceLength )
  201.         {
  202.         int count = ( nonceLength > hashOutputSize ) ? hashOutputSize : nonceLength;
  203.  
  204.         /* Hash the nonce and copy the appropriate amount to the output
  205.            buffer */
  206.         hashFunction( NULL, nonceBuffer, nonceBuffer, hashOutputSize, HASH_ALL );
  207.         memcpy( noncePtr, nonceBuffer, count );
  208.  
  209.         /* Move on to the next block of the output buffer */
  210.         noncePtr += count;
  211.         nonceLength -= count;
  212.         }
  213.     }
  214.  
  215. /* Determine the parameters for a particular hash algorithm */
  216.  
  217. BOOLEAN getHashParameters( const CRYPT_ALGO hashAlgorithm,
  218.                            HASHFUNCTION *hashFunction, int *hashInputSize,
  219.                            int *hashOutputSize, int *hashInfoSize )
  220.     {
  221.     void nullHashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer, \
  222.                         int length, const HASH_STATE hashState );
  223.     void md2HashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer, \
  224.                         int length, const HASH_STATE hashState );
  225.     void md4HashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer, \
  226.                         int length, const HASH_STATE hashState );
  227.     void md5HashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer, \
  228.                         int length, const HASH_STATE hashState );
  229.     void ripemd160HashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer, \
  230.                               int length, const HASH_STATE hashState );
  231.     void shaHashBuffer( void *hashInfo, BYTE *outBuffer, BYTE *inBuffer, \
  232.                         int length, const HASH_STATE hashState );
  233.  
  234.     switch( hashAlgorithm )
  235.         {
  236.         case CRYPT_ALGO_NONE:
  237.             *hashFunction = nullHashBuffer;
  238.             *hashInputSize = 1000;
  239.             *hashOutputSize = CRYPT_MAX_HASHSIZE;
  240.             *hashInfoSize = 0;
  241.             break;
  242.  
  243.         case CRYPT_ALGO_MD2:
  244.             *hashFunction = md2HashBuffer;
  245.             *hashInputSize = MD2_DATASIZE;
  246.             *hashOutputSize = MD2_DIGESTSIZE;
  247.             *hashInfoSize = sizeof( MD2_INFO );
  248.             break;
  249.  
  250.         case CRYPT_ALGO_MD4:
  251.             *hashFunction = md4HashBuffer;
  252.             *hashInputSize = MD4_DATASIZE;
  253.             *hashOutputSize = MD4_DIGESTSIZE;
  254.             *hashInfoSize = sizeof( MD4_INFO );
  255.             break;
  256.  
  257.         case CRYPT_ALGO_MD5:
  258.             *hashFunction = md5HashBuffer;
  259.             *hashInputSize = MD5_DATASIZE;
  260.             *hashOutputSize = MD5_DIGESTSIZE;
  261.             *hashInfoSize = sizeof( MD5_INFO );
  262.             break;
  263.  
  264.         case CRYPT_ALGO_RIPEMD160:
  265.             *hashFunction = ripemd160HashBuffer;
  266.             *hashInputSize = RIPEMD160_DATASIZE;
  267.             *hashOutputSize = RIPEMD160_DIGESTSIZE;
  268.             *hashInfoSize = sizeof( RIPEMD160_INFO );
  269.             break;
  270.  
  271.         case CRYPT_ALGO_SHA:
  272.             *hashFunction = shaHashBuffer;
  273.             *hashInputSize = SHA_DATASIZE;
  274.             *hashOutputSize = SHA_DIGESTSIZE;
  275.             *hashInfoSize = sizeof( SHA_INFO );
  276.             break;
  277.  
  278.         default:
  279.             return( FALSE );    /* API error, should never occur */
  280.         }
  281.  
  282.     return( TRUE );
  283.     }
  284.  
  285. /* Byte-reverse an array of 16- and 32-bit words to/from network byte order
  286.    to account for processor endianness.  These routines assume the given
  287.    count is a multiple of 16 or 32 bits.  They are safe even for CPU's with
  288.    a word size > 32 bits since on a little-endian CPU the important 32 bits
  289.    are stored first, so that by zeroizing the first 32 bits and oring the
  290.    reversed value back in we don't need to rely on the processor only writing
  291.    32 bits into memory */
  292.  
  293. void longReverse( LONG *buffer, int count )
  294.     {
  295. #if defined( _BIG_WORDS )
  296.     BYTE *bufPtr = ( BYTE * ) buffer, temp;
  297.  
  298.     count /= 4;        /* sizeof( LONG ) != 4 */
  299.     while( count-- )
  300.         {
  301.   #if 0
  302.         LONG temp;
  303.  
  304.         /* This code is cursed */
  305.         temp = value = *buffer & 0xFFFFFFFFUL;
  306.         value = ( ( value & 0xFF00FF00UL ) >> 8  ) | \
  307.                 ( ( value & 0x00FF00FFUL ) << 8 );
  308.         value = ( ( value << 16 ) | ( value >> 16 ) ) ^ temp;
  309.         *buffer ^= value;
  310.         buffer = ( LONG * ) ( ( BYTE * ) buffer + 4 );
  311.   #endif /* 0 */
  312.         /* There's really no nice way to do this - the above code generates
  313.            misaligned accesses on processors with a word size > 32 bits, so
  314.            we have to work at the byte level (either that or turn misaligned
  315.            access warnings off by trapping the signal the access corresponds
  316.            to.  However a context switch per memory access is probably
  317.            somewhat slower than the current byte-twiddling mess) */
  318.         temp = bufPtr[ 3 ];
  319.         bufPtr[ 3 ] = bufPtr[ 0 ];
  320.         bufPtr[ 0 ] = temp;
  321.         temp = bufPtr[ 2 ];
  322.         bufPtr[ 2 ] = bufPtr[ 1 ];
  323.         bufPtr[ 1 ] = temp;
  324.         bufPtr += 4;
  325.         }
  326. #elif defined( __WIN32__ )
  327.     /* The following code which makes use of bswap is significantly faster
  328.        than what the compiler would otherwise generate.  This code is used
  329.        such a lot that it's worth the effort */
  330. __asm {
  331.     mov ecx, count
  332.     mov edx, buffer
  333.     shr ecx, 2
  334. swapLoop:
  335.     mov eax, [edx]
  336.     bswap eax
  337.     mov [edx], eax
  338.     add edx, 4
  339.     dec ecx
  340.     jnz swapLoop
  341.     }
  342. #else
  343.     LONG value;
  344.  
  345.     count /= sizeof( LONG );
  346.     while( count-- )
  347.         {
  348.         value = *buffer;
  349.         value = ( ( value & 0xFF00FF00UL ) >> 8  ) | \
  350.                 ( ( value & 0x00FF00FFUL ) << 8 );
  351.         *buffer++ = ( value << 16 ) | ( value >> 16 );
  352.         }
  353. #endif /* _BIG_WORDS */
  354.     }
  355.  
  356. void wordReverse( WORD *buffer, int count )
  357.     {
  358.     WORD value;
  359.  
  360.     count /= sizeof( WORD );
  361.     while( count-- )
  362.         {
  363.         value = *buffer;
  364.         *buffer++ = ( value << 8 ) | ( value >> 8 );
  365.         }
  366.     }
  367.  
  368. /* Load an IV into a CRYPT_INFO structure */
  369.  
  370. int loadIV( CRYPT_INFO *cryptInfo, const BYTE *iv, const int ivLength )
  371.     {
  372.     /* Load the IV of the required length.  If the required IV size is less
  373.        than the maximum possible IV size, we pad it to the right with
  374.        zeroes */
  375.     cryptInfo->ivLength = ivLength;
  376.     cryptInfo->ivCount = 0;
  377.     memset( cryptInfo->iv, 0, CRYPT_MAX_IVSIZE );
  378.     memcpy( cryptInfo->iv, iv, cryptInfo->ivLength );
  379.     memcpy( cryptInfo->currentIV, cryptInfo->iv, CRYPT_MAX_IVSIZE );
  380.     cryptInfo->ivSet = TRUE;
  381.     if( cryptInfo->capabilityInfo->initIVFunction != NULL )
  382.         {
  383.         int status;
  384.  
  385.         status = cryptInfo->capabilityInfo->initIVFunction( cryptInfo );
  386.         if( cryptStatusError( status ) )
  387.             return( status );
  388.         }
  389.  
  390.     return( CRYPT_OK );
  391.     }
  392.  
  393. /* Match a given substring against a string in a case-insensitive manner */
  394.  
  395. #if !defined( __WINDOWS__ ) && !defined( __MSDOS__ )
  396.  
  397. static int strnicmp( const char *src, const char *dest, int length )
  398.     {
  399.     char srcCh, destCh;
  400.  
  401.     while( length-- )
  402.         {
  403.         /* Need to be careful with toupper() side-effects */
  404.         srcCh = *src++;
  405.         srcCh = toupper( srcCh );
  406.         destCh = *dest++;
  407.         destCh = toupper( destCh );
  408.  
  409.         if( srcCh != destCh )
  410.             return( srcCh - destCh );
  411.         }
  412.  
  413.     return( 0 );
  414.     }
  415. #endif /* !( __WINDOWS__ || __MSDOS__ ) */
  416.  
  417. BOOLEAN matchSubstring( const char *subString, const char *string )
  418.     {
  419.     char firstChar = toupper( subString[ 0 ] );
  420.     int subStringlength = strlen( subString ), i;
  421.  
  422.     /* Check trivial cases */
  423.     if( subString == NULL || string == NULL )
  424.         return( FALSE );
  425.     if( strlen( string ) < ( size_t ) subStringlength )
  426.         return( FALSE );
  427.  
  428.     /* Perform a case-insensitive match for the required substring in the
  429.        user ID */
  430.     for( i = 0; string[ i ]; i++ )
  431.         if( ( toupper( string[ i ] ) == firstChar ) &&
  432.             !strnicmp( subString, string + i, subStringlength ) )
  433.                 return( TRUE );
  434.  
  435.     return( FALSE );
  436.     }
  437.  
  438. /****************************************************************************
  439. *                                                                            *
  440. *                            Secure malloc/free Routines                        *
  441. *                                                                            *
  442. ****************************************************************************/
  443.  
  444. /* To support page locking we need to store some additional information with
  445.    the memory block.  We do this by reserving an extra 16 bytes at the start
  446.    of the block and saving the information there (the 16-byte size is to
  447.    preserve alignment on most systems) */
  448.  
  449. typedef struct {
  450.     BOOLEAN isLocked;                /* Whether this block is locked */
  451.     int size;                        /* Size of the block */
  452.     } MEMLOCK_INFO;
  453.  
  454. #ifdef __UNIX__
  455.  
  456. /* Since the function prototypes for the SYSV/POSIX mlock() call are stored
  457.    all over the place depending on the Unix version, we prototype it
  458.    ourselves here rather than try to guess its location */
  459.  
  460. #if defined( __osf__ )
  461.   #include <sys/mman.h>
  462. #elif defined( sun )
  463.   #include <sys/types.h>
  464. #else
  465.   int mlock( void *address, size_t length );
  466.   int munlock( void *address, size_t length );
  467. #endif /* Unix-variant-specific includes */
  468.  
  469. #endif /* __UNIX__ */
  470.  
  471. /* Set the memory lock type */
  472.  
  473. void setOptionMemoryLockType( int lockType )
  474.     {
  475.     memoryLockType = lockType;
  476.     }
  477.  
  478. /* A secure version of malloc() and free() which perform page locking if
  479.    necessary and zeroise memory before it is freed */
  480.  
  481. int secureMalloc( void **pointer, int size )
  482.     {
  483.     MEMLOCK_INFO *memLockPtr;
  484.     BYTE *memPtr;
  485.  
  486.     /* Try and allocate the memory */        /* Shadu yu liktumkunushi */
  487.     if( ( memPtr = malloc( size + 16 ) ) == NULL )
  488.         {                                    /* Shadu yu liklakunushi */
  489.         *pointer = NULL;                    /* Shadu yu lini yix kunushi */
  490.         return( CRYPT_NOMEM );                /* Shadu yu li yixsi kunushi */
  491.         }                                    /* Shadu yu lite kunushi */
  492.     memset( memPtr, 0, size + 16 );            /* Shadu yu lini kunushi */
  493.     memLockPtr = ( MEMLOCK_INFO * ) memPtr;    /* Shadu yu linir kunushi */
  494.     memLockPtr->isLocked = FALSE;            /* Shadu yu likattin kunushi */
  495.     memLockPtr->size = size + 16;            /* Shadu yu dannu elikunu limqut */
  496.     *pointer = memPtr + 16;                    /* Ina zumri ya lu yu tapparrasama! */
  497.  
  498.     /* If the OS supports it, try to lock the pages in memory */
  499. #ifdef __WIN16__
  500.     /* Under Windows 3.x there's no support for memory locking, so we simply
  501.        return an error code for a forced lock */
  502.     if( memoryLockType == CRYPT_MEMORY_FORCELOCK )
  503.         {
  504.         free( memPtr );
  505.         *pointer = NULL;
  506.         return( CRYPT_NOLOCK );
  507.         }
  508. #endif /* __WIN16__ */
  509.  
  510. #ifdef __WIN32__
  511.     /* Under Win95 the VirtualLock() function appears to be implemented as
  512.        `return( TRUE )' ("Thank Microsoft kids" - "Thaaaanks Bill").  Under
  513.        NT the function does actually work */
  514.     if( VirtualLock( memPtr, size ) )
  515.         memLockPtr->isLocked = TRUE;
  516.     else
  517.         if( memoryLockType == CRYPT_MEMORY_FORCELOCK )
  518.             {
  519.             free( memPtr );
  520.             *pointer = NULL;
  521.             return( CRYPT_NOLOCK );
  522.             }
  523. #endif /* __WIN32__ */
  524.  
  525. #ifdef __UNIX__
  526.     /* Under many Unix variants the SYSV/POSIX mlock() call can be used, but
  527.        only by the superuser.  OSF/1 has mlock(), but this is defined to the
  528.        nonexistant memlk() so we need to special-case it out.  Aches and PHUX
  529.        don't even pretend to have mlock().  Many systems also have plock(),
  530.        but this is pretty crude since it locks all data, and also has various
  531.        other shortcomings.  Finally, PHUX has datalock(), which is just a
  532.        plock() variant */
  533.   #if !( defined( __osf__ ) || defined( _AIX ) || defined( __hpux ) || \
  534.          defined( _M_XENIX ) )
  535.     if( !mlock( memPtr, size ) )
  536.         memLockPtr->isLocked = TRUE;
  537.     else
  538.   #endif /* !( __osf__ || _AIX || __hpux || _M_XENIX ) */
  539.         if( memoryLockType == CRYPT_MEMORY_FORCELOCK )
  540.             {
  541.             free( memPtr );
  542.             *pointer = NULL;
  543.             return( CRYPT_NOLOCK );
  544.             }
  545. #endif /* __UNIX__ */
  546.  
  547.     return( CRYPT_OK );
  548.     }
  549.  
  550. /* A safe free function which scrubs memory and zeroes the pointer.
  551.  
  552.     "You will softly and suddenly vanish away
  553.      And never be met with again"    - Lewis Carroll,
  554.                                       "The Hunting of the Snark" */
  555.  
  556. void secureFree( void **pointer )
  557.     {
  558.     MEMLOCK_INFO *memLockPtr;
  559.     BYTE *memPtr = ( BYTE * ) *pointer;
  560.  
  561.     /* Make sure we're not trying to free unallocated memory */
  562.     if( memPtr == NULL )
  563.         return;
  564.  
  565.     /* If the memory is locked, unlock it now */
  566.     memPtr -= 16;
  567.     memLockPtr = ( MEMLOCK_INFO * ) memPtr;
  568. #if defined( __UNIX__ ) && !( defined( __osf__ ) || defined( _AIX ) || \
  569.                               defined( __hpux ) || defined _M_XENIX )
  570.     if( memLockPtr->isLocked )
  571.         munlock( memPtr, memLockPtr->size );
  572. #endif /* __UNIX__ && !( __osf__ || _AIX || __hpux || _M_XENIX ) */
  573. #ifdef __WIN32__
  574.     if( memLockPtr->isLocked )
  575.         VirtualUnlock( memPtr, memLockPtr->size );
  576. #endif /* __WIN32__ */
  577.  
  578.     /* Zeroise the memory, free it, and zero the pointer */
  579.     zeroise( memPtr, memLockPtr->size );
  580.     free( memPtr );
  581.     *pointer = NULL;
  582.     }
  583.  
  584. /* An alternative version of secureFree() which doesn't work with locked
  585.    memory blocks.  This is mainly a convenience function for low-security
  586.    memory areas */
  587.  
  588. void cleanFree( void **pointer, int size )
  589.     {
  590.     if( *pointer != NULL )
  591.         {
  592.         zeroise( *pointer, size );
  593.         free( *pointer );
  594.         *pointer = NULL;
  595.         }
  596.     }
  597.  
  598. /****************************************************************************
  599. *                                                                            *
  600. *        Reduce a Variable-length User Key to a Fixed Encryption Key            *
  601. *                                                                            *
  602. ****************************************************************************/
  603.  
  604. /* Derive an encryption key from a variable-length user key (the simpler
  605.    cryptDeriveKey() form is just a macro which expands to
  606.    cryptDeriveKeyEx()).  This function works as follows:
  607.  
  608.    key[] = { 0 };
  609.    state = hash( algorithm, mode, parameters, userKey );
  610.  
  611.    for count = 1 to iterations
  612.      for length = 1 to keyLength
  613.        state = hash( state );
  614.        key[ length ] = hash( state, userKey );
  615.  
  616.    The state acts as an RNG which ensures that the user key hashing is
  617.    serialized (ie that any form of parallelization or precomputation isn't
  618.    possible) */
  619.  
  620. CRET cryptDeriveKeyEx( CRYPT_CONTEXT cryptContext, const void CPTR userKey,
  621.                        const int userKeyLength, const CRYPT_ALGO algorithm,
  622.                        const int iterations )
  623.     {
  624.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  625.     CRYPT_ALGO hashAlgorithm = algorithm;
  626.     BYTE *hashInfo, *keyBuffer, *state, *temp, *userKeyPtr = ( BYTE * ) userKey;
  627.     BYTE buffer[ 50 ];
  628.     int keyLength, keySetupIterations = iterations, iterationCount;
  629.     int hashInfoSize, hashInputSize, hashOutputSize, status;
  630.     HASHFUNCTION hashFunction;
  631.     STREAM stream;
  632.  
  633.     /* Perform basic error checking.  We check for the availability of the
  634.        hash algorithm and whether the iteration count has a sane value
  635.        because it may have come from a high-level object query function which
  636.        read corrupted data */
  637.     if( isBadCookie( cryptContext ) )
  638.         return( CRYPT_BADPARM1 );
  639.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  640.         return( CRYPT_NOTINITED );
  641.     if( userKey == NULL )
  642.         return( CRYPT_BADPARM2 );
  643.     if( userKeyLength <= 0 )
  644.         return( CRYPT_BADPARM3 );
  645.     if( keySetupIterations == CRYPT_USE_DEFAULT )
  646.         keySetupIterations = DEFAULT_KEYSETUP_ITERATIONS;
  647.     if( hashAlgorithm == CRYPT_USE_DEFAULT )
  648.         hashAlgorithm = DEFAULT_KEYSETUP_ALGO;
  649.     if( cryptStatusError( cryptModeAvailable( hashAlgorithm, CRYPT_MODE_NONE ) ) )
  650.         return( CRYPT_BADPARM4 );
  651.     if( keySetupIterations < 1 || keySetupIterations > 20000 )
  652.         return( CRYPT_BADPARM5 );
  653.  
  654.     /* If it's a hash function or PKC, the derive key operation is
  655.        meaningless */
  656.     if( cryptInfoPtr->capabilityInfo->cryptMode == CRYPT_MODE_NONE || \
  657.         cryptInfoPtr->isPKCcontext )
  658.         return( CRYPT_NOTAVAIL );
  659.  
  660.     /* Get the hash algorithm information */
  661.     if( !getHashParameters( hashAlgorithm, &hashFunction, &hashInputSize,
  662.                             &hashOutputSize, &hashInfoSize ) )
  663.         return( CRYPT_ERROR );    /* API error, should never occur */
  664.  
  665.     /* Allocate storage for the hash information, the RNG state information,
  666.        the hash output temporary storage which is used to build up the key,
  667.        and the encryption key itself.  Since the memory is pagelocked, we
  668.        pack it all into a single block of memory from which we suballocate
  669.        the required chunks (this should all fit into a 4K page.  Even if it's
  670.        not locked it's being constantly touched so shouldn't ever get paged) */
  671.     keyLength = cryptInfoPtr->capabilityInfo->keySize;
  672.     if( ( status = secureMalloc( ( void ** ) &hashInfo, hashInfoSize + \
  673.                                  hashOutputSize + hashOutputSize + \
  674.                                  keyLength ) ) != CRYPT_OK )
  675.         return( status );
  676.     state = hashInfo + hashInfoSize;
  677.     temp = state + hashOutputSize;
  678.     keyBuffer = temp + hashOutputSize;
  679.  
  680.     /* Generate the initial state information from the user key.  If we
  681.        hashed the key directly and then used it for a number of algorithms
  682.        then someone who could recover the key for one algorithm could
  683.        compromise it if used for other algorithms (for example recovering a
  684.        DES key would also recover half an IDEA key), so we hash the
  685.        contents of a KeyInformation record so that all the information
  686.        about the algorithm and mode being used influences the state.  This
  687.        means that a successful attack one an algorithm, mode, or
  688.        configuration won't allow the key for any other algorithm, mode, or
  689.        configuration to be recovered */
  690.     sMemOpen( &stream, buffer, 50 );
  691.     status = writeKeyInfoHeader( &stream, cryptInfoPtr, userKeyLength );
  692.     if( cryptStatusError( status ) )
  693.         {
  694.         secureFree( ( void ** ) &hashInfo );
  695.         return( status );
  696.         }
  697.     hashFunction( hashInfo, NULL, buffer, sMemSize( &stream ), HASH_START );
  698.     hashFunction( hashInfo, state, userKeyPtr, userKeyLength, HASH_END );
  699.     sMemClose( &stream );
  700.  
  701.     /* Hash the variable-length input to a fixed-length output */
  702.     memset( keyBuffer, 0, keyLength );
  703.     for( iterationCount = 0; iterationCount < keySetupIterations; iterationCount++ )
  704.         {
  705.         int keyIndex, length;
  706.  
  707.         for( keyIndex = 0; keyIndex < keyLength; keyIndex += hashOutputSize )
  708.             {
  709.             int i;
  710.  
  711.             /* state = hash( state ); key[ n ] = hash( state, userKey ) */
  712.             hashFunction( hashInfo, state, state, hashOutputSize, HASH_ALL );
  713.             hashFunction( hashInfo, NULL, state, hashOutputSize, HASH_START );
  714.             hashFunction( hashInfo, temp, userKeyPtr, userKeyLength, HASH_END );
  715.  
  716.             /* Copy as much of the hashed data as required to the output */
  717.             length = ( keyLength - keyIndex ) % hashOutputSize;
  718.             for( i = 0; i < length; i++ )
  719.                 keyBuffer[ i ] ^= temp[ i ];
  720.             }
  721.         }
  722.  
  723.     /* Copy the result into the encryption context */
  724.     status = cryptLoadContext( cryptContext, keyBuffer, keyLength );
  725.     if( cryptStatusOK( status ) )
  726.         {
  727.         /* Remember the setup parameters */
  728.         cryptInfoPtr->keySetupIterations = keySetupIterations;
  729.         cryptInfoPtr->keySetupAlgorithm = hashAlgorithm;
  730.         }
  731.  
  732.     /* Clean up */
  733.     secureFree( ( void ** ) &hashInfo );
  734.     return( status );
  735.     }
  736.