certrust.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 548 行 · 第 1/2 页

C
548
字号
/****************************************************************************
*																			*
*					  Certificate Trust Management Routines					*
*						Copyright Peter Gutmann 1998-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined( INC_ALL ) ||  defined( INC_CHILD )
  #include "asn1.h"
  #include "asn1objs.h"
  #include "cert.h"
#else
  #include "keymgmt/asn1.h"
  #include "keymgmt/asn1objs.h"
  #include "keymgmt/cert.h"
#endif /* Compiler-specific includes */

/* Trusted certificate information */

typedef struct TI {
	/* Identification information */
	int sCheck;
	BYTE sHash[ 20 ];			/* Checksum and hash of subjectName */

	/* The trusted certificate.  When we read trusted certs from a config 
	   file, the cert is stored in the encoded form to save creating 
	   cert objects which will never be used, when it's needed the cert is
	   created on the fly from the encoded form.  When we get the trust info 
	   from the user setting it, the cert object already exists and the 
	   encoded form isn't used */
	void *certObject;
	int certObjectLength;
	CRYPT_CERTIFICATE iCryptCert;

	/* Pointer to the next entry */
	struct TI *next;				/* Next trustInfo record in the chain */
	} TRUST_INFO;

/****************************************************************************
*																			*
*						Trust Information Management Routines				*
*																			*
****************************************************************************/

/* The table of trust information */

static TRUST_INFO *trustInfoIndex[ 256 ];

/* Checksum and hash a DN */

static int checksumName( const BYTE *name, const int nameLength )
	{
	int sum1 = 0, sum2 = 0, i;

	/* Calculate an 8-bit Fletcher checksum of the name */
	for( i = 0; i < nameLength; i++ )
		{
		sum1 += name[ i ];
		sum2 += sum1;
		}

	return( sum2 & 0xFF );
	}

static void hashName( BYTE *hash, const BYTE *name, const int nameLength )
	{
	static HASHFUNCTION hashFunction = NULL;
	int hashSize;

	/* Get the hash algorithm information if necessary */
	if( hashFunction == NULL )
		getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );

	/* Hash the DN */
	hashFunction( NULL, hash, ( BYTE * ) name, nameLength, HASH_ALL );
	}

/* Touch the config data to let the config options know that a trust option
   has changed */

static void touchConfigData( const CRYPT_USER cryptOwner )
	{
	int value;

	/* Since we've changed a trust option, we have to tell the config
	   subsystem that the config data has been updated even if the config 
	   options haven't been changed explicitly.  We do this by toggling the 
	   async init flag (used only at startup) to mark the config options as 
	   having changed */
	krnlSendMessage( cryptOwner, RESOURCE_MESSAGE_GETATTRIBUTE, &value, 
					 CRYPT_OPTION_MISC_ASYNCINIT );
	value = !value;
	krnlSendMessage( cryptOwner, RESOURCE_MESSAGE_SETATTRIBUTE, &value, 
					 CRYPT_OPTION_MISC_ASYNCINIT );
	value = !value;
	krnlSendMessage( cryptOwner, RESOURCE_MESSAGE_SETATTRIBUTE, &value, 
					 CRYPT_OPTION_MISC_ASYNCINIT );
	}

/* Add and delete a trust entry */

static int addTrustEntry( const CERT_INFO *certInfoPtr,
						  const void *certObject, const int certObjectLength )
	{
	TRUST_INFO *newElement;
	BOOLEAN recreateCert = FALSE;
	int objectLength = certObjectLength;

	/* If we're adding a cert, check whether it has a context attached and
	   if it does, whether it's a public-key context.  If there's no context
	   attached (it's a data-only cert) or the attached context is a 
	   private-key context (which we don't want to leave hanging around in
	   memory, or which could be in a removable crypto device), we don't try 
	   and use the cert but instead add the cert data and re-instantiate a 
	   new cert with attached public-key context if required */
	if( certObject == NULL )
		{
		if( certInfoPtr->iCryptContext == CRYPT_ERROR )
			/* There's no context associated with this cert, we'll have to
			   recreate it later */
			recreateCert = TRUE;
		else
			{
			int status;

			status = krnlSendMessage( certInfoPtr->objectHandle, 
									  RESOURCE_IMESSAGE_CHECK, NULL,
									  RESOURCE_MESSAGE_CHECK_PKC_PRIVATE );
			if( cryptStatusOK( status ) )
				/* The context associated with the cert is a private-key
				   context, recreate it later as a public-key context */
				recreateCert = TRUE;
			}
		}

	/* Allocate memory for the new element and copy the information across */
	if( ( newElement  = ( TRUST_INFO * ) malloc( sizeof( TRUST_INFO ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newElement, 0, sizeof( TRUST_INFO ) );
	if( certObject != NULL || recreateCert )
		{
		void *subjectDNptr;
		int subjectDNsize, objectLength = certObjectLength;

		/* If we're using the data from an existing cert object, the subject
		   DN data is already known */
		if( recreateCert )
			{
			subjectDNptr = certInfoPtr->subjectDNptr;
			subjectDNsize = certInfoPtr->subjectDNsize;
			certObject = certInfoPtr->certificate;
			objectLength = certInfoPtr->certificateSize;
			}
		else
			{
			STREAM stream;
			int value;

			/* Parse the certificate to locate the start of the encoded 
			   subject DN */
			sMemConnect( &stream, certObject, certObjectLength );
			readSequence( &stream, NULL );	/* Outer wrapper */
			readSequence( &stream, NULL );	/* Inner wrapper */
			if( peekTag( &stream ) == MAKE_CTAG( 0 ) )
				readUniversal( &stream );	/* Version */
			readUniversal( &stream );		/* Serial number */
			readUniversal( &stream );		/* Sig.algo */
			readUniversal( &stream );		/* Issuer DN */
			readUniversal( &stream );		/* Validity */
			subjectDNptr = sMemBufPtr( &stream );
			value = readSequence( &stream, &subjectDNsize );
			subjectDNsize += value;
			sMemDisconnect( &stream );
			if( cryptStatusError( value ) )
				{
				/* Make sure we parsed the cert OK */
				free( newElement );
				return( CRYPT_ERROR_BADDATA );
				}
			}

		/* The trusted cert is being read from config data, remember it for
		   later use */
		if( ( newElement->certObject = malloc( objectLength ) ) == NULL )
			{
			free( newElement );
			return( CRYPT_ERROR_MEMORY );
			}
		memcpy( newElement->certObject, certObject, objectLength );
		newElement->certObjectLength = objectLength;
		newElement->iCryptCert = CRYPT_ERROR;

		/* Generate the checksum and hash of the cert's subject name */
		newElement->sCheck = checksumName( subjectDNptr, subjectDNsize );
		hashName( newElement->sHash, subjectDNptr, subjectDNsize );
		}
	else
		{
		/* The trusted key exists as a context, remember it for later */
		assert( certInfoPtr->iCryptContext != CRYPT_ERROR );
		krnlSendNotifier( certInfoPtr->objectHandle, 
						  RESOURCE_IMESSAGE_INCREFCOUNT );
		newElement->iCryptCert = certInfoPtr->objectHandle;

		/* Generate the checksum and hash of the cert's subject name */
		newElement->sCheck = checksumName( certInfoPtr->subjectDNptr,
										   certInfoPtr->subjectDNsize );
		hashName( newElement->sHash, certInfoPtr->subjectDNptr, 
				  certInfoPtr->subjectDNsize );
		}

	/* Add it to the list */
	if( trustInfoIndex[ newElement->sCheck ] == NULL )
		trustInfoIndex[ newElement->sCheck ] = newElement;
	else
		{
		TRUST_INFO *trustInfoPtr;

		/* Add the new element to the end of the list */
		for( trustInfoPtr = trustInfoIndex[ newElement->sCheck ];
			 trustInfoPtr->next != NULL; trustInfoPtr = trustInfoPtr->next );
		trustInfoPtr->next = newElement;
		}

	return( CRYPT_OK );
	}

static void deleteTrustEntry( TRUST_INFO *trustInfoPtr )
	{
	TRUST_INFO *prevInfoPtr;
	const int sCheck = trustInfoPtr->sCheck;

	assert( trustInfoIndex[ sCheck ] != NULL );

	/* Unlink the trust info index */
	prevInfoPtr = trustInfoIndex[ sCheck ];
	if( prevInfoPtr == trustInfoPtr )
		/* Unlink from the start of the list */
		trustInfoIndex[ sCheck ] = trustInfoPtr->next;
	else
		{
		/* Unlink from the middle/end of the list */
		while( prevInfoPtr->next != trustInfoPtr )
			prevInfoPtr = prevInfoPtr->next;
		prevInfoPtr->next = trustInfoPtr->next;
		}

	/* Free the trust info entry */
	if( trustInfoPtr->iCryptCert != CRYPT_ERROR )
		krnlSendNotifier( trustInfoPtr->iCryptCert,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
	if( trustInfoPtr->certObject != NULL )
		{
		zeroise( trustInfoPtr->certObject, trustInfoPtr->certObjectLength );
		free( trustInfoPtr->certObject );
		}
	memset( trustInfoPtr, 0, sizeof( TRUST_INFO ) );
	free( trustInfoPtr );
	}

/* Find the trust info entry for a given DN */

static TRUST_INFO *findTrustEntry( const void *name, const int nameLength )
	{
	const int trustInfoPos = checksumName( name, nameLength );
	TRUST_INFO *trustInfoPtr = trustInfoIndex[ trustInfoPos ];
	BYTE sHash[ 20 ];

	/* Perform a quick check using a checksum of the name to weed out most 
	   entries */
	if( trustInfoPtr == NULL )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?