home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / CRYPT.C < prev    next >
Text File  |  1996-10-12  |  31KB  |  966 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            cryptlib Core Routines                            *
  4. *                        Copyright Peter Gutmann 1992-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <time.h>
  12. #include "crypt.h"
  13.  
  14. /* "Modern cryptography is nothing more than a mathematical framework for
  15.     debating the implications of various paranoid delusions".
  16.                                                 - Don Alvarez */
  17.  
  18. /* Prototypes for functions in cryptcapability.c */
  19.  
  20. BOOLEAN queryCapabilitiesInited( void );
  21. void freeCapabilityList( void );
  22. int initCapabilities( void );
  23. int addCapability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, int blockSize,
  24.                    char *name, int speed, int minKeySize, int keySize,
  25.                    int maxKeySize );
  26. CAPABILITY_INFO *findCapabilityInfo( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode );
  27.  
  28. /* Prototypes for functions in cryptdbx.c */
  29.  
  30. int deleteAllKeysetContexts( void );
  31.  
  32. /* To convert from the external CRYPT_CONTEXT cookie which is used to
  33.    reference encryption contexts to the internal CRYPT_INFO structure, we
  34.    subtract an offset from the CRYPT_CONTEXT value to obtain a pointer to
  35.    the CRYPT_INFO struct.  The use of the conversion offset means programs
  36.    outside the library security perimeter will generate a protection
  37.    violation if they try to treat the CRYPT_CONTEXT as a pointer to
  38.    anything unless they go to some lengths to determine the conversion
  39.    value */
  40.  
  41. int cryptContextConversionOffset;
  42.  
  43. /****************************************************************************
  44. *                                                                            *
  45. *                Memory Management Functions for Encryption Contexts            *
  46. *                                                                            *
  47. ****************************************************************************/
  48.  
  49. /* The linked list of encryption contexts */
  50.  
  51. static CRYPT_INFO *cryptInfoListHead = NULL, *cryptInfoListTail;
  52.  
  53. /* Create an encryption context and add it to the list */
  54.  
  55. static int createCryptContext( CRYPT_INFO **cryptInfo )
  56.     {
  57.     CRYPT_INFO *newElement;
  58.     int status;
  59.  
  60.     /* Allocate memory for the new encryption context */
  61.     if( ( status = secureMalloc( ( void ** ) &newElement,
  62.                                  sizeof( CRYPT_INFO ) ) ) != CRYPT_OK )
  63.         return( status );
  64.     memset( newElement, 0, sizeof( CRYPT_INFO ) );
  65.  
  66.     /* Link it into the list */
  67.     if( cryptInfoListHead == NULL )
  68.         cryptInfoListHead = newElement;
  69.     else
  70.         {
  71.         cryptInfoListTail->next = newElement;
  72.         newElement->prev = cryptInfoListTail;
  73.         }
  74.     cryptInfoListTail = newElement;
  75.  
  76.     *cryptInfo = newElement;
  77.     return( CRYPT_OK );
  78.     }
  79.  
  80. /* Delete an encryption context from the list */
  81.  
  82. static void deleteCryptContext( CRYPT_INFO *cryptInfo )
  83.     {
  84.     CRYPT_INFO *cryptInfoPrevPtr = cryptInfo->prev, *cryptInfoNextPtr = cryptInfo->next;
  85.  
  86.     /* Remove the encryption context from the list of contexts */
  87.     if( cryptInfo == cryptInfoListHead )
  88.         {
  89.         /* Special case for first encryption context */
  90.         cryptInfoListHead = cryptInfoNextPtr;
  91.         if( cryptInfoNextPtr != NULL )
  92.             cryptInfoNextPtr->prev = NULL;
  93.         }
  94.     else
  95.         {
  96.         /* Delete from the middle or the end of the chain */
  97.         cryptInfoPrevPtr->next = cryptInfoNextPtr;
  98.         if( cryptInfoNextPtr != NULL )
  99.             cryptInfoNextPtr->prev = cryptInfoPrevPtr;
  100.         }
  101.  
  102.     /* If this was the last element, move the tail pointer back */
  103.     if( cryptInfoListTail == cryptInfo )
  104.         cryptInfoListTail = cryptInfoPrevPtr;
  105.  
  106.     /* Clear all data in the encryption context and free the memory */
  107.     secureFree( ( void ** ) &cryptInfo );
  108.     }
  109.  
  110. /* Delete all encryption contexts */
  111.  
  112. static int deleteAllCryptContexts( void )
  113.     {
  114.     CRYPT_INFO *cryptInfoListPtr = cryptInfoListHead;
  115.  
  116.     /* If there are no remaining allocated encryption contexts, return now */
  117.     if( cryptInfoListPtr == NULL )
  118.         return( CRYPT_OK );
  119.  
  120.     /* Destroy any remaining encryption contexts */
  121.     while( cryptInfoListPtr != NULL )
  122.         {
  123.         CRYPT_INFO *cryptInfoToFree = cryptInfoListPtr;
  124.  
  125.         cryptInfoListPtr = cryptInfoListPtr->next;
  126.         cryptDestroyContext( INFO_TO_CONTEXT( cryptInfoToFree ) );
  127.         }
  128.  
  129.     /* If there were encryption contexts still allocated we warn the user
  130.        about it */
  131.     return( CRYPT_ORPHAN );
  132.     }
  133.  
  134. /****************************************************************************
  135. *                                                                            *
  136. *                            Capability Query Functions                        *
  137. *                                                                            *
  138. ****************************************************************************/
  139.  
  140. /* Determine whether a given encryption mode is available */
  141.  
  142. CRET cryptModeAvailable( const CRYPT_ALGO cryptAlgo, \
  143.                          const CRYPT_MODE cryptMode )
  144.     {
  145.     /* Perform basic error checking */
  146.     if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
  147.         return( CRYPT_BADPARM1 );
  148.     if( cryptMode < CRYPT_MODE_NONE || cryptMode >= CRYPT_MODE_LAST )
  149.         return( CRYPT_BADPARM2 );
  150.  
  151.     /* Make sure the library has been initalised */
  152.     if( !queryCapabilitiesInited() )
  153.         return( CRYPT_NOTINITED );
  154.  
  155.     /* See if we have any information on this encryption algo/mode */
  156.     if( findCapabilityInfo( cryptAlgo, cryptMode ) == NULL )
  157.         return( ( findCapabilityInfo( cryptAlgo, CRYPT_MODE_NONE ) == NULL ) ? \
  158.                 CRYPT_NOALGO : CRYPT_NOMODE );
  159.  
  160.     return( CRYPT_OK );
  161.     }
  162.  
  163. CRET cryptAlgoAvailable( const CRYPT_ALGO cryptAlgo )
  164.     {
  165.     return( cryptModeAvailable( cryptAlgo, CRYPT_MODE_NONE ) );
  166.     }
  167.  
  168. /* Get information on a given encrytion algorithm */
  169.  
  170. CRET cryptQueryAlgoMode( const CRYPT_ALGO cryptAlgo, \
  171.                          const CRYPT_MODE cryptMode, \
  172.                          CRYPT_QUERY_INFO CPTR cryptQueryInfo )
  173.     {
  174.     CAPABILITY_INFO *capabilityInfo;
  175.  
  176.     /* Perform basic error checking */
  177.     if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST )
  178.         return( CRYPT_BADPARM1 );
  179.     if( cryptMode < CRYPT_MODE_NONE || cryptMode >= CRYPT_MODE_LAST )
  180.         return( CRYPT_BADPARM2 );
  181.     if( cryptQueryInfo == NULL )
  182.         return( CRYPT_BADPARM3 );
  183.  
  184.     /* Make sure the library has been initalised */
  185.     if( !queryCapabilitiesInited() )
  186.         return( CRYPT_NOTINITED );
  187.  
  188.     /* Clear the fields in the query structure */
  189.     memset( cryptQueryInfo, 0, sizeof( CRYPT_QUERY_INFO ) );
  190.  
  191.     /* Find the information record on this algorithm */
  192.     if( ( capabilityInfo = findCapabilityInfo( cryptAlgo, cryptMode ) ) == NULL )
  193.         {
  194.         cryptQueryInfo->algoName = "";
  195.         cryptQueryInfo->blockSize = CRYPT_ERROR;
  196.         cryptQueryInfo->minKeySize = CRYPT_ERROR;
  197.         cryptQueryInfo->keySize = CRYPT_ERROR;
  198.         cryptQueryInfo->maxKeySize = CRYPT_ERROR;
  199.         cryptQueryInfo->minIVsize = CRYPT_ERROR;
  200.         cryptQueryInfo->ivSize = CRYPT_ERROR;
  201.         cryptQueryInfo->maxIVsize = CRYPT_ERROR;
  202.         cryptQueryInfo->speed = CRYPT_ERROR;
  203.         return( ( findCapabilityInfo( cryptAlgo, CRYPT_MODE_NONE ) == NULL ) ? \
  204.                 CRYPT_NOALGO : CRYPT_NOMODE );
  205.         }
  206.  
  207.     /* Return the appropriate information */
  208.     cryptQueryInfo->cryptAlgo = cryptAlgo;
  209.     cryptQueryInfo->cryptMode = cryptMode;
  210.     cryptQueryInfo->algoName = capabilityInfo->algoName;
  211.     cryptQueryInfo->modeName = capabilityInfo->modeName;
  212.     cryptQueryInfo->blockSize = capabilityInfo->blockSize;
  213.     cryptQueryInfo->minKeySize = capabilityInfo->minKeySize;
  214.     cryptQueryInfo->keySize = capabilityInfo->keySize;
  215.     cryptQueryInfo->maxKeySize = capabilityInfo->maxKeySize;
  216.     cryptQueryInfo->minIVsize = capabilityInfo->minIVsize;
  217.     cryptQueryInfo->ivSize = capabilityInfo->ivSize;
  218.     cryptQueryInfo->maxIVsize = capabilityInfo->maxIVsize;
  219.     cryptQueryInfo->speed = capabilityInfo->speed;
  220.     return( CRYPT_OK );
  221.     }
  222.  
  223. /* Get information on the algorithm used by a given encryption context */
  224.  
  225. CRET cryptQueryContext( const CRYPT_CONTEXT cryptContext, \
  226.                         CRYPT_QUERY_INFO CPTR cryptQueryInfo )
  227.     {
  228.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  229.     CAPABILITY_INFO *capabilityInfoPtr;
  230.     int status;
  231.  
  232.     /* Perform basic error checking */
  233.     if( isBadCookie( cryptContext ) )
  234.         return( CRYPT_BADPARM1 );
  235.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  236.         return( CRYPT_NOTINITED );
  237.  
  238.     /* Fill in the basic information */
  239.     capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
  240.     if( ( status = cryptQueryAlgoMode( capabilityInfoPtr->cryptAlgo,
  241.                         capabilityInfoPtr->cryptMode, cryptQueryInfo ) ) != CRYPT_OK )
  242.         return( status );
  243.  
  244.     /* We may be able to get more specific information than the generic
  245.        cryptQueryAlgoMode() call could give us since the encryption context
  246.        contains extra information on the algorithm being used */
  247.     if( capabilityInfoPtr->getKeysizeFunction != NULL )
  248.         cryptQueryInfo->maxKeySize = \
  249.                     capabilityInfoPtr->getKeysizeFunction( cryptInfoPtr );
  250.  
  251.     /* If it's a hash function, copy in the current state */
  252.     if( capabilityInfoPtr->cryptMode == CRYPT_MODE_NONE )
  253.         {
  254.         if( ( status = capabilityInfoPtr->getDataFunction( cryptInfoPtr,
  255.                                 cryptQueryInfo->hashValue ) ) != CRYPT_OK )
  256.             return( status );
  257.         }
  258.  
  259.     /* If it's a PKC function, copy in the key ID */
  260.     if( capabilityInfoPtr->cryptMode == CRYPT_MODE_PKC )
  261.         {
  262.         memcpy( cryptQueryInfo->keyID, cryptInfoPtr->keyID,
  263.                 cryptInfoPtr->keyIDlength );
  264.         cryptQueryInfo->keyIDsize = cryptInfoPtr->keyIDlength;
  265.         }
  266.  
  267.     /* Copy in other information */
  268.     cryptQueryInfo->controlVector = cryptInfoPtr->controlVector;
  269.  
  270.     return( CRYPT_OK );
  271.     }
  272.  
  273. /* Initialise and shut down the encryption library.  If we're being called
  274.    from a DLL then the startup code will have already initialised the library,
  275.    so we don't need to do anything further.  The use of a global variable to
  276.    control this is somewhat messy, but there isn't really any clean way to do
  277.    it */
  278.  
  279. #ifdef __WINDOWS__
  280.   static BOOLEAN isDLLcall = FALSE;
  281. #endif /* __WINDOWS__ */
  282.  
  283. static BOOLEAN isInitialised = FALSE;
  284.  
  285. CRET cryptInit( void )
  286.     {
  287.     /* Make sure we don't get called more than once */
  288.     if( isInitialised )
  289.         return( CRYPT_INITED );
  290.     isInitialised = TRUE;
  291.  
  292.     /* Set up the conversion offset used to translate CRYPT_CONTEXT cookies
  293.        into CRYPT_INFO structures.  This doesn't have to be secure, just a
  294.        random value that isn't too easy to guess and which generates some
  295.        form of error if the the CRYPT_CONTEXT it is added to is treated as a
  296.        pointer (makeCookie() forces an odd address which guarantees this for
  297.        most architectures) */
  298.     cryptContextConversionOffset = makeCookie( ( int ) time( NULL ) );
  299.  
  300.     /* Initialise the BigNum library */
  301.     bnInit();
  302.  
  303.     return( initCapabilities() );
  304.     }
  305.  
  306. CRET cryptEnd( void )
  307.     {
  308.     int status, dbxStatus;
  309.  
  310. #ifdef __WINDOWS__
  311.     if( !isDLLcall )
  312.         return( CRYPT_OK );
  313. #endif /* __WINDOWS__ */
  314.  
  315.     /* If we haven't been initialised yet, signal an error */
  316.     if( !isInitialised )
  317.         return( CRYPT_NOTINITED );
  318.  
  319.     /* Clean up all library data structures */
  320.     status = deleteAllCryptContexts();
  321.     dbxStatus = deleteAllKeysetContexts();
  322.     freeCapabilityList();
  323.     endRandom();
  324.  
  325.     return( cryptStatusOK( status ) ? cryptStatusOK( dbxStatus ) ? \
  326.             CRYPT_OK : dbxStatus : status );
  327.     }
  328.  
  329. /****************************************************************************
  330. *                                                                            *
  331. *                    Encryption Context Management Functions                    *
  332. *                                                                            *
  333. ****************************************************************************/
  334.  
  335. /* A magic value to detect whether an encryption context has been
  336.    initialised yet */
  337.  
  338. #define CRYPT_MAGIC        0xC0EDBABEUL
  339.  
  340. /* Initialise or perform an extended initialisation of an encryption
  341.    context */
  342.  
  343. CRET cryptCreateContextEx( CRYPT_CONTEXT CPTR cryptContext, \
  344.                            const CRYPT_ALGO cryptAlgo, \
  345.                            const CRYPT_MODE cryptMode, \
  346.                            const void CPTR cryptInfoEx )
  347.     {
  348.     CRYPT_ALGO localCryptAlgo = cryptAlgo;
  349.     CRYPT_MODE localCryptMode = cryptMode;
  350.     CAPABILITY_INFO *capabilityInfoPtr;
  351.     CRYPT_INFO *cryptInfoPtr;
  352.     int status;
  353.  
  354.     /* Perform basic error checking */
  355.     if( cryptContext == NULL )
  356.         return( CRYPT_BADPARM1 );
  357.     if( cryptAlgo < CRYPT_ALGO_NONE || cryptAlgo >= CRYPT_ALGO_LAST && \
  358.         cryptAlgo != CRYPT_USE_DEFAULT )
  359.         return( CRYPT_BADPARM2 );
  360.     if( cryptMode < CRYPT_MODE_NONE || cryptMode >= CRYPT_MODE_LAST && \
  361.         cryptMode != CRYPT_USE_DEFAULT )
  362.         return( CRYPT_BADPARM3 );
  363.     if( cryptInfoEx == NULL )
  364.         return( CRYPT_BADPARM4 );
  365.  
  366.     /* Handle any default settings for algorithm and mode */
  367.     if( cryptAlgo == CRYPT_USE_DEFAULT )
  368.         {
  369.         /* If the mode is CRYPT_MODE_NONE, it's a hash context */
  370.         if( cryptMode == CRYPT_MODE_NONE )
  371.             localCryptAlgo = getOptionHashAlgo();
  372.         else
  373.             /* If the mode is CRYPT_MODE_PKC, it's a PKC context */
  374.             if( cryptMode == CRYPT_MODE_PKC )
  375.                 localCryptAlgo = getOptionPKCAlgo();
  376.             else
  377.                 {
  378.                 /* It's a conventional encryption context */
  379.                 localCryptAlgo = getOptionCryptAlgo();
  380.                 if( cryptMode == CRYPT_USE_DEFAULT )
  381.                     localCryptMode = getOptionCryptMode();
  382.                 }
  383.         }
  384.     if( localCryptMode == CRYPT_USE_DEFAULT )
  385.         if( ( cryptAlgo < CRYPT_ALGO_FIRST_CONVENTIONAL ) || \
  386.             ( cryptAlgo >= CRYPT_ALGO_LAST_CONVENTIONAL ) )
  387.             return( CRYPT_BADPARM3 );
  388.         else
  389.             localCryptMode = getOptionCryptMode();
  390.  
  391.     /* Set up the pointer to the capability information and make sure the
  392.        context can use the extended initialisation parameters if they're
  393.        present */
  394.     if( ( capabilityInfoPtr = findCapabilityInfo( localCryptAlgo, localCryptMode ) ) == NULL )
  395.         return( ( cryptAlgoAvailable( localCryptAlgo ) ) ? \
  396.                 CRYPT_NOMODE : CRYPT_NOALGO );
  397.     if( cryptInfoEx != ( void * ) CRYPT_UNUSED && \
  398.         capabilityInfoPtr->initExFunction == NULL )
  399.         return( CRYPT_BADPARM2 );
  400.  
  401.     /* Make sure the algorithm self-test went OK */
  402.     if( capabilityInfoPtr->selfTestStatus != CRYPT_OK )
  403.         return( CRYPT_SELFTEST );
  404.  
  405.     /* We're through the intialization phase, now we can create the
  406.        encryption context */
  407.     if( ( status = createCryptContext( &cryptInfoPtr ) ) != CRYPT_OK )
  408.         return( status );
  409.     cryptInfoPtr->capabilityInfo = capabilityInfoPtr;
  410.     if( capabilityInfoPtr->cryptMode == CRYPT_MODE_PKC )
  411.         {
  412.         cryptInfoPtr->isPKCcontext = TRUE;
  413.         cryptInfoPtr->keySizeBits = 0;
  414.         cryptInfoPtr->ivSet = TRUE;    /* No IV for PKC's */
  415.  
  416.         /* Initialise the BigNum information */
  417.         bnBegin( &cryptInfoPtr->pkcParam1 );
  418.         bnBegin( &cryptInfoPtr->pkcParam2 );
  419.         bnBegin( &cryptInfoPtr->pkcParam3 );
  420.         bnBegin( &cryptInfoPtr->pkcParam4 );
  421.         bnBegin( &cryptInfoPtr->pkcParam5 );
  422.         bnBegin( &cryptInfoPtr->pkcParam6 );
  423.         bnBegin( &cryptInfoPtr->pkcParam7 );
  424.         bnBegin( &cryptInfoPtr->pkcParam8 );
  425.         }
  426.  
  427.     /* Perform any algorithm-specific initialization */
  428.     if( cryptInfoEx == ( void * ) CRYPT_UNUSED )
  429.         {
  430.         if( capabilityInfoPtr->initFunction != NULL )
  431.             status = capabilityInfoPtr->initFunction( cryptInfoPtr );
  432.         }
  433.     else
  434.         status = capabilityInfoPtr->initExFunction( cryptInfoPtr, cryptInfoEx );
  435.     if( cryptStatusError( status ) )
  436.         {
  437.         deleteCryptContext( cryptInfoPtr );
  438.         return( status );
  439.         }
  440.  
  441.     /* If we don't need a key and IV, record them as being set */
  442.     if( capabilityInfoPtr->cryptMode == CRYPT_MODE_NONE )
  443.         {
  444.         cryptInfoPtr->keySet = TRUE;
  445.         cryptInfoPtr->ivSet = TRUE;
  446.         }
  447.  
  448.     /* Set up the IV information and key cookie export flag to the default
  449.        values.  These can be overridden later if required */
  450.     cryptInfoPtr->ivLength = capabilityInfoPtr->ivSize;
  451.     cryptInfoPtr->exportKeyCookie = CRYPT_USE_DEFAULT;
  452.  
  453.     /* Set the check value.  Note that we set it after the capability info
  454.        has been set, so that a check on this value will also tell us whether
  455.        the capability info is present */
  456.     cryptInfoPtr->checkValue = CRYPT_MAGIC;
  457.  
  458.     /* Convert the encryption information pointer to an encryption context
  459.        and return it to the user */
  460.     *cryptContext = INFO_TO_CONTEXT( cryptInfoPtr );
  461.  
  462.     return( CRYPT_OK );
  463.     }
  464.  
  465. /* Destroy an encryption context */
  466.  
  467. CRET cryptDestroyContext( CRYPT_CONTEXT cryptContext )
  468.     {
  469.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  470.  
  471.     /* Perform basic error checking */
  472.     if( isBadCookie( cryptContext ) )
  473.         return( CRYPT_BADPARM1 );
  474.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  475.         return( CRYPT_NOTINITED );
  476.  
  477.     /* Perform any algorithm-specific shutdown */
  478.     if( cryptInfoPtr->capabilityInfo->endFunction != NULL )
  479.         {
  480.         int status;
  481.  
  482.         status = cryptInfoPtr->capabilityInfo->endFunction( cryptInfoPtr );
  483.         if( cryptStatusError( status ) )
  484.             return( status );
  485.         }
  486.  
  487.     /* If it's a PKC crypt context, free the BigNum information */
  488.     if( cryptInfoPtr->isPKCcontext )
  489.         {
  490.         bnEnd( &cryptInfoPtr->pkcParam1 );
  491.         bnEnd( &cryptInfoPtr->pkcParam2 );
  492.         bnEnd( &cryptInfoPtr->pkcParam3 );
  493.         bnEnd( &cryptInfoPtr->pkcParam4 );
  494.         bnEnd( &cryptInfoPtr->pkcParam5 );
  495.         bnEnd( &cryptInfoPtr->pkcParam6 );
  496.         bnEnd( &cryptInfoPtr->pkcParam7 );
  497.         bnEnd( &cryptInfoPtr->pkcParam8 );
  498.         if( cryptInfoPtr->userID != NULL )
  499.             {
  500.             zeroise( cryptInfoPtr->userID, strlen( cryptInfoPtr->userID ) );
  501.             free( cryptInfoPtr->userID );
  502.             }
  503.         if( cryptInfoPtr->pkcInfo != NULL )
  504.             secureFree( &cryptInfoPtr->pkcInfo );
  505.         }
  506.  
  507.     /* Delete the encryption context */
  508.     deleteCryptContext( cryptInfoPtr );
  509.  
  510.     return( CRYPT_OK );
  511.     }
  512.  
  513. /****************************************************************************
  514. *                                                                            *
  515. *                                Keying Functions                            *
  516. *                                                                            *
  517. ****************************************************************************/
  518.  
  519. /* Load a user key into an encryption context */
  520.  
  521. CRET cryptLoadContext( CRYPT_CONTEXT cryptContext, void CPTR userKey,
  522.                        const int userKeyLength )
  523.     {
  524.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  525.     CAPABILITY_INFO *capabilityInfoPtr;
  526.     int status;
  527.  
  528.     /* Perform basic error checking */
  529.     if( isBadCookie( cryptContext ) )
  530.         return( CRYPT_BADPARM1 );
  531.     if( userKey == NULL )
  532.         return( CRYPT_BADPARM2 );
  533.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  534.         return( CRYPT_NOTINITED );
  535.     capabilityInfoPtr = cryptInfoPtr->capabilityInfo;
  536.     if( !cryptInfoPtr->isPKCcontext &&
  537.         ( userKeyLength < capabilityInfoPtr->minKeySize ||
  538.           userKeyLength > capabilityInfoPtr->maxKeySize ) )
  539.         return( CRYPT_BADPARM3 );
  540.     if( capabilityInfoPtr->initKeyFunction == NULL )
  541.         return( CRYPT_NOALGO );
  542.  
  543.     /* If it's a hash function, the load key operation is meaningless */
  544.     if( capabilityInfoPtr->cryptMode == CRYPT_MODE_NONE )
  545.         return( CRYPT_NOTAVAIL );
  546.  
  547.     /* Load either PKC keying information or a conventional key */
  548.     if( cryptInfoPtr->isPKCcontext )
  549.         {
  550.         /* Call the algorithm-specific function to load the key components */
  551.         cryptInfoPtr->keyComponentPtr = ( void CPTR ) userKey;
  552.         if( ( status = capabilityInfoPtr->initKeyFunction( cryptInfoPtr ) ) != CRYPT_OK )
  553.             return( status );
  554.         }
  555.     else
  556.         {
  557.         /* Some conventional algorithms allow various key sizes depending on
  558.            how they're used.  We now perform a more rigorous check to make
  559.            sure that the key length is correct */
  560.         if( capabilityInfoPtr->getKeysizeFunction != NULL && \
  561.             userKeyLength > capabilityInfoPtr->getKeysizeFunction( cryptInfoPtr ) )
  562.             return( CRYPT_BADPARM3 );
  563.  
  564.         /* Load the user encryption key into the encryption context */
  565.         memcpy( cryptInfoPtr->userKey, userKey, userKeyLength );
  566.         cryptInfoPtr->userKeyLength = userKeyLength;
  567.         if( cryptInfoPtr->clearBuffer )
  568.             zeroise( userKey, userKeyLength );
  569.  
  570.         /* Remember that we need to set an IV before we encrypt anything */
  571.         if( needsIV( capabilityInfoPtr->cryptMode ) )
  572.             cryptInfoPtr->ivSet = FALSE;
  573.         else
  574.             /* We don't need an IV, record it as being set */
  575.             cryptInfoPtr->ivSet = TRUE;
  576.  
  577.         /* Call the encryption routine for this algorithm/mode */
  578.         status = capabilityInfoPtr->initKeyFunction( cryptInfoPtr );
  579.         if( cryptStatusError( status ) )
  580.             return( status );
  581.  
  582.         /* Generate the key cookie for this key */
  583.         status = generateKeyCookie( cryptInfoPtr );
  584.         if( cryptStatusError( status ) )
  585.             return( status );
  586.         }
  587.  
  588.     /* Record the fact that the key has been initialized */
  589.     cryptInfoPtr->keySet = TRUE;
  590.  
  591.     return( CRYPT_OK );
  592.     }
  593.  
  594. /****************************************************************************
  595. *                                                                            *
  596. *                            IV Handling Functions                            *
  597. *                                                                            *
  598. ****************************************************************************/
  599.  
  600. /* Load an IV into an encryption context */
  601.  
  602. CRET cryptLoadIV( CRYPT_CONTEXT cryptContext, const void CPTR iv, const int ivLength )
  603.     {
  604.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  605.  
  606.     /* Perform basic error checking */
  607.     if( isBadCookie( cryptContext ) )
  608.         return( CRYPT_BADPARM1 );
  609.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  610.         return( CRYPT_NOTINITED );
  611.     if( iv == NULL )
  612.         return( CRYPT_BADPARM2 );
  613.     if( ivLength < cryptInfoPtr->capabilityInfo->minIVsize ||
  614.         ivLength > cryptInfoPtr->capabilityInfo->maxIVsize )
  615.         return( CRYPT_BADPARM3 );
  616.  
  617.     /* If it's a PKC crypt context or an mode which doesn't use an IV, the
  618.        load IV operation is meaningless */
  619.     if( cryptInfoPtr->isPKCcontext )
  620.         return( CRYPT_NOTAVAIL );
  621.     if( !needsIV( cryptInfoPtr->capabilityInfo->cryptMode ) )
  622.         return( CRYPT_NOTAVAIL );
  623.  
  624.     /* Load the IV */
  625.     return( loadIV( cryptInfoPtr, iv, ivLength ) );
  626.     }
  627.  
  628. /* Retrieve an IV from an encryption context */
  629.  
  630. CRET cryptRetrieveIV( CRYPT_CONTEXT cryptContext, void CPTR iv )
  631.     {
  632.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  633.  
  634.     /* Perform basic error checking */
  635.     if( isBadCookie( cryptContext ) )
  636.         return( CRYPT_BADPARM1 );
  637.     if( iv == NULL )
  638.         return( CRYPT_BADPARM2 );
  639.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  640.         return( CRYPT_NOTINITED );
  641.  
  642.     /* If it's a PKC crypt context or an mode which doesn't use an IV, the
  643.        load IV operation is meaningless */
  644.     if( cryptInfoPtr->isPKCcontext )
  645.         return( CRYPT_NOTAVAIL );
  646.     if( !needsIV( cryptInfoPtr->capabilityInfo->cryptMode ) )
  647.         return( CRYPT_NOTAVAIL );
  648.  
  649.     /* Make sure the IV has been set */
  650.     if( cryptInfoPtr->ivSet == FALSE )
  651.         return( CRYPT_NOIV );
  652.  
  653.     /* Copy the IV data of the required length to the output buffer */
  654.     memcpy( iv, cryptInfoPtr->iv, cryptInfoPtr->ivLength );
  655.  
  656.     return( CRYPT_OK );
  657.     }
  658.  
  659. /****************************************************************************
  660. *                                                                            *
  661. *                            Encrypt/Decrypt Routines                        *
  662. *                                                                            *
  663. ****************************************************************************/
  664.  
  665. /* Encrypt a block of memory */
  666.  
  667. CRET cryptEncrypt( CRYPT_CONTEXT cryptContext, void CPTR buffer, \
  668.                    const int length )
  669.     {
  670.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  671.  
  672.     /* Perform basic error checking */
  673.     if( isBadCookie( cryptContext ) )
  674.         return( CRYPT_BADPARM1 );
  675.     if( buffer == NULL )
  676.         return( CRYPT_BADPARM2 );
  677.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  678.         return( CRYPT_NOTINITED );
  679.     if( cryptInfoPtr->isPKCcontext )
  680.         {
  681.         if( length != CRYPT_USE_DEFAULT )
  682.             return( CRYPT_BADPARM3 );
  683.         }
  684.     else
  685.         if( length < 0 )
  686.             return( CRYPT_BADPARM3 );
  687.     if( !cryptInfoPtr->keySet )
  688.         return( CRYPT_NOKEY );
  689.     if( cryptInfoPtr->capabilityInfo->encryptFunction == NULL )
  690.         return( CRYPT_NOALGO );
  691.  
  692.     /* If there's no IV set, generate one ourselves */
  693.     if( !cryptInfoPtr->ivSet )
  694.         {
  695.         BYTE iv[ CRYPT_MAX_IVSIZE ];
  696.         int status;
  697.  
  698.         getNonce( iv, cryptInfoPtr->ivLength );
  699.         if( ( status = loadIV( cryptInfoPtr, iv, cryptInfoPtr->ivLength ) ) != CRYPT_OK )
  700.             return( status );
  701.         }
  702.  
  703.     /* Call the encryption routine for this algorithm/mode */
  704.     return( cryptInfoPtr->capabilityInfo->encryptFunction( cryptInfoPtr, buffer, length ) );
  705.     }
  706.  
  707. /* Decrypt a block of memory */
  708.  
  709. CRET cryptDecrypt( CRYPT_CONTEXT cryptContext, void CPTR buffer, \
  710.                    const int length )
  711.     {
  712.     CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  713.  
  714.     /* Perform basic error checking */
  715.     if( isBadCookie( cryptContext ) )
  716.         return( CRYPT_BADPARM1 );
  717.     if( buffer == NULL )
  718.         return( CRYPT_BADPARM2 );
  719.     if( cryptInfoPtr->checkValue != CRYPT_MAGIC )
  720.         return( CRYPT_NOTINITED );
  721.     if( cryptInfoPtr->isPKCcontext )
  722.         {
  723.         if( length != CRYPT_USE_DEFAULT )
  724.             return( CRYPT_BADPARM3 );
  725.         }
  726.     else
  727.         if( length < 0 )
  728.             return( CRYPT_BADPARM3 );
  729.     if( !cryptInfoPtr->keySet )
  730.         return( CRYPT_NOKEY );
  731.     if( cryptInfoPtr->capabilityInfo->decryptFunction == NULL )
  732.         return( CRYPT_NOALGO );
  733.  
  734.     /* Make sure the IV has been set */
  735.     if( cryptInfoPtr->ivSet == FALSE )
  736.         return( CRYPT_NOIV );
  737.  
  738.     /* Call the decryption routine for this algorithm/mode */
  739.     return( cryptInfoPtr->capabilityInfo->decryptFunction( cryptInfoPtr, buffer, length ) );
  740.     }
  741.  
  742. /****************************************************************************
  743. *                                                                            *
  744. *                            Miscellaneous Routines                            *
  745. *                                                                            *
  746. ****************************************************************************/
  747.  
  748. #if 0
  749.  
  750. /* Add a new encryption capability to the library.  This routine is quite
  751.    powerful, but what a kludge! */
  752.  
  753. CRET cryptAddCapability( CRYPT_ALGO cryptAlgo, CRYPT_MODE cryptMode, \
  754.                          int blockSize, char *name, int speed, \
  755.                          int minKeySize, int keySize, int maxKeySize )
  756.     {
  757.     int status;
  758.  
  759.     /* Add the basic capability information */
  760.     status = addCapability( cryptAlgo, cryptMode, blockSize, name,
  761.                             speed, minKeySize, keySize, maxKeySize );
  762.     if( cryptStatusError( status ) )
  763.         return( status );
  764.  
  765.     /* Add the handlers */
  766. /* Not implemented yet */
  767.  
  768.     return( CRYPT_ERROR );
  769.     }
  770. #endif /* 0 */
  771.  
  772. /* Perform a library IOCTL */
  773.  
  774. CRET cryptIoctl( CRYPT_IOCTL ioctlCode, void CPTR ioctlInformation,
  775.                  CRYPT_CONTEXT cryptContext )
  776.     {
  777.     /* Perform basic error checking */
  778.     if( ioctlCode < CRYPT_IOCTL_NONE || ioctlCode > CRYPT_IOCTL_LAST )
  779.         return( CRYPT_BADPARM1 );
  780.     if( ioctlCode != CRYPT_IOCTL_NONE && ioctlInformation == NULL )
  781.         return( CRYPT_BADPARM2 );
  782.     if( ioctlCode == CRYPT_IOCTL_NONE || ioctlCode == CRYPT_IOCTL_MEMORY )
  783.         {
  784.         if( cryptContext != NULL )
  785.             return( CRYPT_BADPARM3 );
  786.         }
  787.     else
  788.         if( cryptContext != NULL && isBadCookie( cryptContext ) )
  789.             return( CRYPT_BADPARM3 );
  790.  
  791.     /* Null IOCTL */
  792.     if( ioctlCode == CRYPT_IOCTL_NONE )
  793.         return( CRYPT_OK );
  794.  
  795.     /* Memory locking IOCTL */
  796.     if( ioctlCode == CRYPT_IOCTL_MEMORY )
  797.         {
  798.         CRYPT_IOCTLINFO_MEMORY *ioctlInfo = \
  799.                             ( CRYPT_IOCTLINFO_MEMORY * ) ioctlInformation;
  800.  
  801.         if( ioctlInfo->memoryLockType < CRYPT_MEMORY_NOLOCK || \
  802.             ioctlInfo->memoryLockType > CRYPT_MEMORY_FORCELOCK )
  803.             return( CRYPT_BADPARM2 );
  804.         setOptionMemoryLockType( ioctlInfo->memoryLockType );
  805.         return( CRYPT_OK );
  806.         }
  807.  
  808.     /* Cookie export IOCTL's */
  809.     if( ioctlCode == CRYPT_IOCTL_KEYCOOKIE )
  810.         {
  811.         CRYPT_IOCTLINFO_COOKIE *ioctlInfo = \
  812.                             ( CRYPT_IOCTLINFO_COOKIE * ) ioctlInformation;
  813.         if( cryptContext == NULL )
  814.             setOptionExportKeyCookie( ( BOOLEAN ) ioctlInfo->exportCookie );
  815.         else
  816.             {
  817.             CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  818.  
  819.             cryptInfoPtr->exportKeyCookie = ioctlInfo->exportCookie;
  820.             }
  821.         return( CRYPT_OK );
  822.         }
  823.     if( ioctlCode == CRYPT_IOCTL_SIGCOOKIE )
  824.         {
  825.         CRYPT_IOCTLINFO_COOKIE *ioctlInfo = \
  826.                             ( CRYPT_IOCTLINFO_COOKIE * ) ioctlInformation;
  827.         if( cryptContext == NULL )
  828.             setOptionExportSigCookie( ( BOOLEAN ) ioctlInfo->exportCookie );
  829.         else
  830.             {
  831.             CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  832.  
  833.             cryptInfoPtr->exportSigCookie = ioctlInfo->exportCookie;
  834.             }
  835.         return( CRYPT_OK );
  836.         }
  837.  
  838.     /* PKC padding type IOCTL */
  839.     if( ioctlCode == CRYPT_IOCTL_PKCPADDING )
  840.         {
  841.         CRYPT_IOCTLINFO_PKCPADDING *ioctlInfo = \
  842.                             ( CRYPT_IOCTLINFO_PKCPADDING * ) ioctlInformation;
  843.         if( cryptContext == NULL )
  844.             setOptionUseOAEP( ( BOOLEAN ) ioctlInfo->useOAEP );
  845.         else
  846.             {
  847.             CRYPT_INFO *cryptInfoPtr = CONTEXT_TO_INFO( cryptContext );
  848.  
  849.             cryptInfoPtr->useOAEP = ioctlInfo->useOAEP;
  850.             }
  851.         return( CRYPT_OK );
  852.         }
  853.  
  854.     /* Keyset table names IOCTL */
  855.     if( ioctlCode == CRYPT_IOCTL_KEYSETNAMES )
  856.         {
  857.         CRYPT_IOCTLINFO_KEYSETNAMES *ioctlInfo = \
  858.                             ( CRYPT_IOCTLINFO_KEYSETNAMES * ) ioctlInformation;
  859.         if( cryptContext == NULL )
  860.             setOptionKeysetNames( ioctlInfo );
  861.         else
  862.             /* The keyset-specific config is implemented in cryptdbx.c since
  863.                it involves manipulation of the KEYSET_INFO structure which
  864.                isn't exported to the entire library */
  865.             return( setKeysetNames( cryptContext, ioctlInfo ) );
  866.         return( CRYPT_OK );
  867.         }
  868.  
  869.     /* We should never get here */
  870.     return( CRYPT_ERROR );
  871.     }
  872.  
  873. /****************************************************************************
  874. *                                                                            *
  875. *                        OS-Specific Support Routines                        *
  876. *                                                                            *
  877. ****************************************************************************/
  878.  
  879. #if defined( __WINDOWS__ ) && !defined( __WIN32__ )
  880.  
  881. /* Whether LibMain() has been called before */
  882.  
  883. static BOOLEAN libMainCalled = FALSE;
  884. static HWND hInst;
  885.  
  886. /* The main function for the DLL */
  887.  
  888. int CALLBACK LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD wHeapSize, \
  889.                       LPSTR lpszCmdLine )
  890.     {   
  891.     int status;
  892.     
  893.     /* If we've been called before, return with an error message */
  894.     if( libMainCalled )
  895.         return( FALSE );
  896.     libMainCalled = TRUE;
  897.  
  898.     /* Initialise the library */
  899.     isDLLcall = TRUE;
  900.     status = cryptInit();
  901.     isDLLcall = FALSE;
  902.     if( status != CRYPT_OK )
  903.         return( FALSE );
  904.  
  905.     /* Remember the proc instance for later */
  906.     hInst = hInstance;
  907.  
  908.     return( TRUE );
  909.     }
  910.  
  911. /* Shut down the DLL */
  912.  
  913. int CALLBACK WEP( int nSystemExit )
  914.     {
  915.     switch( nSystemExit )
  916.         {
  917.         case WEP_SYSTEM_EXIT:
  918.             /* System is shutting down */
  919.             break;
  920.  
  921.         case WEP_FREE_DLL:
  922.             /* DLL reference count = 0, DLL-only shutdown */
  923.             break;
  924.         }
  925.  
  926.     /* Shut down the encryption library if necessary */
  927.     isDLLcall = TRUE;
  928.     cryptEnd();
  929.     isDLLcall = FALSE;
  930.  
  931.     return( TRUE );
  932.     }
  933.  
  934. #elif defined( __WINDOWS__ ) && defined( __WIN32__ )
  935.  
  936. static HANDLE hLibInst;
  937.  
  938. BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
  939.     {
  940.     int status;
  941.  
  942.     switch( fdwReason )
  943.         {
  944.         case DLL_PROCESS_ATTACH:
  945.             /* Remember the instance handle and initialise the library */
  946.             hLibInst = hinstDLL;
  947.             isDLLcall = TRUE;
  948.             status = cryptInit();
  949.             isDLLcall = FALSE;
  950.             break;
  951.  
  952.         case DLL_PROCESS_DETACH:
  953.             /* Shut down the library */
  954.             isDLLcall = TRUE;
  955.             cryptEnd();
  956.             isDLLcall = FALSE;
  957.  
  958.         case DLL_THREAD_ATTACH:
  959.         case DLL_THREAD_DETACH:
  960.             break;
  961.         }
  962.  
  963.     return( ( status == CRYPT_OK ) ? TRUE : FALSE );
  964.     }
  965. #endif /* __WINDOWS__ && !__WIN32__ */
  966.