home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / LIB_CERT.C < prev    next >
Text File  |  1996-10-07  |  13KB  |  447 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                    cryptlib Certificate Management Routines                *
  4. *                        Copyright Peter Gutmann 1995-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. #ifdef INC_ALL
  14.   #include "asn1keys.h"
  15. #else
  16.   #include "keymgmt/asn1keys.h"
  17. #endif /* Compiler-specific includes */
  18.  
  19. /* The structure which holds information on a list element */
  20.  
  21. typedef struct LI {
  22.     /* The list element payload */
  23.     void *data;
  24.     int dataSize;
  25.  
  26.     /* The next and previous list element in the linked list of elements */
  27.     struct LI *next, *prev;
  28.     } LISTITEM;
  29.  
  30. /* The structure which stores information on a certificate */
  31.  
  32. typedef struct RI {
  33.     /* The DER-encoded SubjectPublicKeyInfo */
  34.     void *keyInfo;                    /* Key information */
  35.     int keyInfoSize;                /* Size of the key information */
  36.  
  37.     /* General certificate information */
  38.     long serialNumber;                /* This may be a bignum, but there don't
  39.                                        seem to be any implementations which
  40.                                        do this */
  41.     time_t validityNotBefore;        /* Validity start */
  42.     time_t validityNotAfter;        /* Validity end */
  43.  
  44.     /* Name fields */
  45.     LISTITEM *issuerNameHead, *issuerNameTail;    /* Issuer name */
  46.     LISTITEM *subjectNameHead, *subjectNameTail;/* Subject name */
  47.  
  48.     /* A check value so we can determine whether the keyset context has been
  49.        initialised or not.  This is needed because passing in an
  50.        uninitialised block of memory as a keyset context can lead to problems
  51.        when we try to dereference wild pointers */
  52.     LONG checkValue;
  53.  
  54.     /* The next and previous certificate context in the linked list of
  55.        contexts */
  56.     struct RI *next, *prev;
  57.     } CERT_INFO;
  58.  
  59. /* Macros to convert to/from certificate contexts.  These are analogous to
  60.    the encryption context macros in crypt.h */
  61.  
  62. #define CERT_TO_INFO( x )    ( CERT_INFO * ) ( ( BYTE * ) x - cryptContextConversionOffset )
  63. #define INFO_TO_CERT( x )    ( CRYPT_CERT ) ( ( BYTE * ) x + cryptContextConversionOffset )
  64.  
  65. /****************************************************************************
  66. *                                                                            *
  67. *                    List Functions for Certificate Information                *
  68. *                                                                            *
  69. ****************************************************************************/
  70.  
  71. /* Insert an element into a list */
  72.  
  73. static int insertElement( LISTITEM **listHead, LISTITEM **listTail,
  74.                           void *data, int dataLength )
  75.     {
  76.     LISTITEM *newElement;
  77.  
  78.     /* Allocate memory for the new element */
  79.     if( ( newElement  = ( LISTITEM * ) malloc( sizeof( LISTITEM ) ) ) == NULL )
  80.         return( CRYPT_NOMEM );
  81.     if( ( newElement->data = malloc( dataLength ) ) == NULL )
  82.         {
  83.         free( newElement );
  84.         return( CRYPT_NOMEM );
  85.         }
  86.     memset( newElement, 0, sizeof( LISTITEM ) );
  87.     memcpy( newElement->data, data, dataLength );
  88.     newElement->dataSize = dataLength;
  89.  
  90.     /* Link it into the list */
  91.     if( *listHead == NULL )
  92.         *listHead = newElement;
  93.     else
  94.         {
  95.         ( *listTail )->next = newElement;
  96.         newElement->prev = *listTail;
  97.         }
  98.     *listTail = newElement;
  99.  
  100.     return( CRYPT_OK );
  101.     }
  102.  
  103. /* Delete an element from a list */
  104.  
  105. static void deleteElement( LISTITEM **listHead, LISTITEM **listTail,
  106.                            LISTITEM *listItem )
  107.     {
  108.     LISTITEM *listPrevPtr = listItem->prev, *listNextPtr = listItem->next;
  109.  
  110.     /* Remove the item from the list */
  111.     if( listItem == *listHead )
  112.         {
  113.         /* Special case for first item */
  114.         *listHead = listNextPtr;
  115.         if( listNextPtr != NULL )
  116.             listNextPtr->prev = NULL;
  117.         }
  118.     else
  119.         {
  120.         /* Delete from the middle or the end of the chain */
  121.         listPrevPtr->next = listNextPtr;
  122.         if( listNextPtr != NULL )
  123.             listNextPtr->prev = listPrevPtr;
  124.         }
  125.  
  126.     /* If this was the last element, move the tail pointer back */
  127.     if( *listTail == listItem )
  128.         *listTail = listPrevPtr;
  129.  
  130.     /* Clear all data in the list item and free the memory */
  131.     zeroise( listItem->data, listItem->dataSize );
  132.     free( listItem->data );
  133.     zeroise( listItem, sizeof( LISTITEM ) );
  134.     free( listItem );
  135.     }
  136.  
  137. /* Delete a list */
  138.  
  139. static void deleteList( LISTITEM **listHead, LISTITEM **listTail )
  140.     {
  141.     LISTITEM *listPtr = *listHead;
  142.  
  143.     /* Mark the list as being empty */
  144.     *listHead = *listTail = NULL;
  145.  
  146.     /* If the list was empty, return now */
  147.     if( listPtr == NULL )
  148.         return;
  149.  
  150.     /* Destroy any remaining list items */
  151.     while( listPtr != NULL )
  152.         {
  153.         LISTITEM *itemToFree = listPtr;
  154.  
  155.         listPtr = listPtr->next;
  156.         zeroise( itemToFree->data, itemToFree->dataSize );
  157.         free( itemToFree->data );
  158.         zeroise( itemToFree, sizeof( LISTITEM ) );
  159.         free( itemToFree );
  160.         }
  161.     }
  162.  
  163. /****************************************************************************
  164. *                                                                            *
  165. *                Memory Management Functions for Certificate Contexts        *
  166. *                                                                            *
  167. ****************************************************************************/
  168.  
  169. /* The linked list of certificate contexts */
  170.  
  171. static CERT_INFO *certInfoListHead = NULL, *certInfoListTail;
  172.  
  173. /* Create a cert context and add it to the list */
  174.  
  175. static int createCertificateContext( CERT_INFO **certInfo )
  176.     {
  177.     CERT_INFO *newElement;
  178.  
  179.     /* Allocate memory for the new cert context */
  180.     if( ( newElement  = malloc( sizeof( CERT_INFO ) ) ) == NULL )
  181.         return( CRYPT_NOMEM );
  182.     memset( newElement, 0, sizeof( CERT_INFO ) );
  183.  
  184.     /* Link it into the list */
  185.     if( certInfoListHead == NULL )
  186.         certInfoListHead = newElement;
  187.     else
  188.         {
  189.         certInfoListTail->next = newElement;
  190.         newElement->prev = certInfoListTail;
  191.         }
  192.     certInfoListTail = newElement;
  193.  
  194.     *certInfo = newElement;
  195.     return( CRYPT_OK );
  196.     }
  197.  
  198. /* Delete a certificate context from the list */
  199.  
  200. static void deleteCertificateContext( CERT_INFO *certInfo )
  201.     {
  202.     CERT_INFO *certInfoPrevPtr = certInfo->prev, *certInfoNextPtr = certInfo->next;
  203.  
  204.     /* Remove the cert context from the list of contexts */
  205.     if( certInfo == certInfoListHead )
  206.         {
  207.         /* Special case for first certificate */
  208.         certInfoListHead = certInfoNextPtr;
  209.         if( certInfoNextPtr != NULL )
  210.             certInfoNextPtr->prev = NULL;
  211.         }
  212.     else
  213.         {
  214.         /* Delete from the middle or the end of the chain */
  215.         certInfoPrevPtr->next = certInfoNextPtr;
  216.         if( certInfoNextPtr != NULL )
  217.             certInfoNextPtr->prev = certInfoPrevPtr;
  218.         }
  219.  
  220.     /* If this was the last element, move the tail pointer back */
  221.     if( certInfoListTail == certInfo )
  222.         certInfoListTail = certInfoPrevPtr;
  223.  
  224.     /* Clear all data in the cert context and free the memory */
  225.     zeroise( certInfo, sizeof( CERT_INFO ) );
  226.     free( certInfo );
  227.     }
  228.  
  229. /* Delete all certificate contexts */
  230.  
  231. int deleteAllCertificateContexts( void )
  232.     {
  233.     CERT_INFO *certInfoListPtr = certInfoListHead;
  234.  
  235.     /* Mark the list as being empty */
  236.     certInfoListHead = certInfoListTail = NULL;
  237.  
  238.     /* If there are no remaining allocated cert contexts, return now */
  239.     if( certInfoListPtr == NULL )
  240.         return( CRYPT_OK );
  241.  
  242.     /* Destroy any remaining cert contexts */
  243.     while( certInfoListPtr != NULL )
  244.         {
  245.         CERT_INFO *certInfoToFree = certInfoListPtr;
  246.  
  247.         certInfoListPtr = certInfoListPtr->next;
  248.         cryptDestroyCert( INFO_TO_CERT( certInfoToFree ) );
  249.         }
  250.  
  251.     /* If there were cert contexts still allocated, warn the user about
  252.        them */
  253.     return( CRYPT_ORPHAN );
  254.     }
  255.  
  256. /****************************************************************************
  257. *                                                                            *
  258. *                        Certificate Management API Functions                *
  259. *                                                                            *
  260. ****************************************************************************/
  261.  
  262. /* Create/destroy a certificate */
  263.  
  264. CRET cryptCreateCert( CRYPT_CERT CPTR certificate,
  265.                       const CRYPT_CONTEXT pkcContext )
  266.     {
  267.     STREAM stream;
  268.     CERT_INFO *certInfoPtr;
  269.     CRYPT_INFO *pkcInfoPtr = CONTEXT_TO_INFO( pkcContext );
  270.     void *keyInfo;
  271.     int keyInfoSize, status;
  272.  
  273.     /* Perform basic error checking */
  274.     if( certificate == NULL )
  275.         return( CRYPT_BADPARM1 );
  276.     if( isBadCookie( pkcContext ) || \
  277.         pkcInfoPtr->checkValue != CRYPT_MAGIC || \
  278.         !pkcInfoPtr->keySet || !pkcInfoPtr->isPKCcontext )
  279.         return( CRYPT_BADPARM2 );
  280.  
  281.     /* Find out how large the encoded key information will be and allocate
  282.        memory for it */
  283.     sMemNullOpen( &stream );
  284.     status = writePublicKey( &stream, pkcInfoPtr->pkcInfo );
  285.     keyInfoSize = sMemSize( &stream );
  286.     sMemClose( &stream );
  287.     if( cryptStatusError( status ) )
  288.         return( status );
  289.     if( ( keyInfo = malloc( keyInfoSize ) ) == NULL )
  290.         return( CRYPT_NOMEM );
  291.  
  292.     /* Create the certificate context */
  293.     if( ( status = createCertificateContext( &certInfoPtr ) ) != CRYPT_OK )
  294.         {
  295.         free( keyInfo );
  296.         return( status );
  297.         }
  298.  
  299.     /* Encode the PKC information as a SubjectPublicKey and store the result
  300.        in the public-key field of the certificate.  We don't need to check
  301.        the status of writePublicKey() this time since we just called it a few
  302.        lines ago */
  303.     sMemOpen( &stream, keyInfo, keyInfoSize );
  304.     writePublicKey( &stream, pkcInfoPtr->pkcInfo );
  305.     sMemDisconnect( &stream );
  306.     certInfoPtr->keyInfo = keyInfo;
  307.     certInfoPtr->keyInfoSize = keyInfoSize;
  308.  
  309.     /* Set the check value */
  310.     certInfoPtr->checkValue = CRYPT_MAGIC;
  311.  
  312.     /* Convert the keyset information pointer to a certificate context and
  313.        return it to the user */
  314.     *certificate = INFO_TO_CERT( certInfoPtr );
  315.  
  316.     return( CRYPT_OK );
  317.     }
  318.  
  319. CRET cryptDestroyCert( CRYPT_CERT certificate )
  320.     {
  321.     CERT_INFO *certInfoPtr = CERT_TO_INFO( certificate );
  322.  
  323.     /* Perform basic error checking */
  324.     if( isBadCookie( certificate ) )
  325.         return( CRYPT_BADPARM1 );
  326.     if( certInfoPtr->checkValue != CRYPT_MAGIC )
  327.         return( CRYPT_NOTINITED );
  328.  
  329.     /* Clear the SubjectPublicKeyInfo if necessary */
  330.     if( certInfoPtr->keyInfo != NULL )
  331.         {
  332.         zeroise( certInfoPtr->keyInfo, certInfoPtr->keyInfoSize );
  333.         free( certInfoPtr->keyInfo );
  334.         }
  335.  
  336.     /* Clear the name fields if necessary */
  337.     if( certInfoPtr->issuerNameHead != NULL )
  338.         deleteList( &certInfoPtr->issuerNameHead, &certInfoPtr->issuerNameTail );
  339.     if( certInfoPtr->subjectNameHead != NULL )
  340.         deleteList( &certInfoPtr->subjectNameHead, &certInfoPtr->subjectNameTail );
  341.  
  342.     /* Delete the certificate itself */
  343.     deleteCertificateContext( certInfoPtr );
  344.  
  345.     return( CRYPT_OK );
  346.     }
  347.  
  348. #if 0
  349.  
  350. /* Get/add/delete certificate components */
  351.  
  352. CRET cryptGetCertComponent( CRYPT_CERT certificate,
  353.                             const CRYPT_CERTINFO_TYPE certInfoType,
  354.                             void CPTR certInfo );
  355. CRET cryptAddCertComponent( CRYPT_CERT certificate,
  356.                             const CRYPT_CERTINFO_TYPE certInfoType,
  357.                             const void CPTR certInfo );
  358. CRET cryptDeleteCertComponent( CRYPT_CERT certificate,
  359.                                const CRYPT_CERTINFO_TYPE certInfoType,
  360.                                const void CPTR certInfo );
  361.  
  362. /* Sign a certificate */
  363.  
  364. CRET cryptSignCert( CRYPT_CERT certificate, CRYPT_CONTEXT pkcContext );
  365.  
  366. #endif /* 0 */
  367.  
  368. /* Import a certificate */
  369.  
  370. CRET cryptImportCert( const void CPTR certObject, CRYPT_CERT CPTR certificate )
  371.     {
  372.     CERT_INFO *certInfoPtr = CERT_TO_INFO( certificate );
  373.     BYTE *objectPtr = ( BYTE * ) certObject;
  374.     void *keyInfo;
  375.     int keyInfoSize, status;
  376.  
  377.     /* Perform basic error checking */
  378.     if( certObject == NULL )
  379.         return( CRYPT_BADPARM1 );
  380.     if( isBadCookie( certificate ) || \
  381.         certInfoPtr->checkValue != CRYPT_MAGIC )
  382.         return( CRYPT_BADPARM2 );
  383.  
  384.     /* In this release all that's supported is reading the raw
  385.        SubjectPublicKeyInfo record from the input */
  386.     if( memcmp( objectPtr, "RAW0", 4 ) )
  387.         return( CRYPT_BADDATA );
  388.     objectPtr += 4;
  389.  
  390.     /* Find out how big the object is */
  391.     keyInfoSize = *objectPtr++ << 8;
  392.     keyInfoSize += *objectPtr++;
  393.  
  394.     /* Allocate room for the SubjectPublicKeyInfo record */
  395.     if( ( keyInfo = malloc( keyInfoSize ) ) == NULL )
  396.         return( CRYPT_NOMEM );
  397.  
  398.     /* Create the certificate context */
  399.     if( ( status = createCertificateContext( &certInfoPtr ) ) != CRYPT_OK )
  400.         {
  401.         free( keyInfo );
  402.         return( status );
  403.         }
  404.     memcpy( keyInfo, objectPtr, keyInfoSize );
  405.     certInfoPtr->keyInfo = keyInfo;
  406.  
  407.     /* Set the check value and convert the keyset information pointer to a
  408.        certificate context */
  409.     certInfoPtr->checkValue = CRYPT_MAGIC;
  410.     *certificate = INFO_TO_CERT( certInfoPtr );
  411.  
  412.     return( CRYPT_OK );
  413.     }
  414.  
  415. /* Export a certificate */
  416.  
  417. CRET cryptExportCert( void CPTR certObject, int CPTR certObjectLength,
  418.                       CRYPT_CERT certificate )
  419.     {
  420.     CERT_INFO *certInfoPtr = CERT_TO_INFO( certificate );
  421.  
  422.     /* Perform basic error checking */
  423.     if( certObject == NULL )
  424.         return( CRYPT_BADPARM1 );
  425.     if( certObjectLength == NULL )
  426.         return( CRYPT_BADPARM2 );
  427.     if( isBadCookie( certificate ) || \
  428.         certInfoPtr->checkValue != CRYPT_MAGIC )
  429.         return( CRYPT_BADPARM3 );
  430.  
  431.     /* In this release all that's supported is writing the raw
  432.        SubjectPublicKeyInfo record to the output */
  433.     *certObjectLength = certInfoPtr->keyInfoSize + 6;
  434.     if( certObject != NULL )
  435.         {
  436.         BYTE *objectPtr = certObject;
  437.  
  438.         memcpy( objectPtr, "RAW0", 4 );
  439.         objectPtr += 4;
  440.         *objectPtr++ = certInfoPtr->keyInfoSize >> 8;
  441.         *objectPtr++ = certInfoPtr->keyInfoSize & 0xFF;
  442.         memcpy( objectPtr, certInfoPtr->keyInfo, certInfoPtr->keyInfoSize + 2 );
  443.         }
  444.  
  445.     return( CRYPT_OK );
  446.     }
  447.