⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trustmgr.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*					  Certificate Trust Management Routines					*
*						Copyright Peter Gutmann 1998-2004					*
*																			*
****************************************************************************/

/* The following code is actually part of the user rather than certificate
   routines, but it pertains to certificates so we include it here.  Trust
   info mutex handling is done in the user object, so there are no mutexes
   required here.

   The interpretation of what represents a "trusted cert" is somewhat complex
   and open-ended, it's not clear whether what's being trusted is the key
   in the cert, the cert, or the owner of the cert (corresponding to
   subjectKeyIdentifier, issuerAndSerialNumber/certHash, or subject DN).  The
   generally accepted form is to trust the subject, so we check for this in
   the cert.  The modification for trusting the key in the cert is fairly
   simple to make if required */

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

/* The size of the table of trust information.  This must be a power of 2 */

#define TRUSTINFO_SIZE		256

/* The size of the hashed identifier info */

#define HASH_SIZE			20

/* Trusted certificate information */

typedef struct TI {
	/* Identification information, the checksum and hash of the cert
	   subjectName and subjectKeyIdentifier */
	int sCheck, kCheck;
	BYTE sHash[ HASH_SIZE ], kHash[ HASH_SIZE ];

	/* The trusted certificate.  When we read trusted certs from a config
	   file, the cert is stored in the encoded form to save creating a pile
	   of cert objects that 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
	   directly from the user, 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;

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Hash data */

static void hashData( BYTE *hash, const void *data, const int dataLength )
	{
	static HASHFUNCTION hashFunction = NULL;

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

	/* Hash the data */
	if( dataLength <= 0 )
		memset( hash, 0, HASH_SIZE );
	else
		hashFunction( NULL, hash, ( BYTE * ) data, dataLength, HASH_ALL );
	}

/****************************************************************************
*																			*
*							Retrieve Trusted Cert Info						*
*																			*
****************************************************************************/

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

void *findTrustEntry( void *trustInfoPtr, const CRYPT_CERTIFICATE iCryptCert,
					  const BOOLEAN getIssuerEntry )
	{
	TRUST_INFO **trustInfoIndex = ( TRUST_INFO ** ) trustInfoPtr;
	const TRUST_INFO *trustInfoCursor;
	DYNBUF nameDB;
	BYTE sHash[ HASH_SIZE ];
	BOOLEAN nameHashed = FALSE;
	int sCheck, status;

	/* If we're trying to get a trusted issuer cert and we're already at a 
	   self-signed (CA root) cert, don't return it.  This check is necessary 
	   because self-signed certs have issuer name == subject name, so once 
	   we get to a self-signed cert's subject DN an attempt to fetch its 
	   issuer would just repeatedly fetch the same cert */
	if( getIssuerEntry )
		{
		int value;

		status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE, &value, 
								  CRYPT_CERTINFO_SELFSIGNED );
		if( cryptStatusError( status ) || value )
			return( NULL );
		}

	/* Set up the information needed to find the trusted cert */
	status = dynCreate( &nameDB, iCryptCert, getIssuerEntry ? \
						CRYPT_IATTRIBUTE_ISSUER : CRYPT_IATTRIBUTE_SUBJECT );
	if( cryptStatusError( status ) )
		return( NULL );
	sCheck = checksumData( dynData( nameDB ), dynLength( nameDB ) );
	trustInfoCursor = trustInfoIndex[ sCheck & ( TRUSTINFO_SIZE - 1 ) ];

	/* Check to see whether something with the requested DN is present */
	while( trustInfoCursor != NULL )
		{
		/* Perform a quick check using a checksum of the name to weed out
		   most entries */
		if( trustInfoCursor->sCheck == sCheck )
			{
			if( !nameHashed )
				{
				hashData( sHash, dynData( nameDB ), dynLength( nameDB ) );
				nameHashed = TRUE;
				}
			if( !memcmp( trustInfoCursor->sHash, sHash, HASH_SIZE ) )
				{
				dynDestroy( &nameDB );
				return( ( TRUST_INFO * ) trustInfoCursor );
				}
			}
		trustInfoCursor = trustInfoCursor->next;
		}

	dynDestroy( &nameDB );
	return( NULL );
	}

/* Retrieve trusted certificates */

CRYPT_CERTIFICATE getTrustedCert( void *trustInfoPtr )
	{
	TRUST_INFO *trustInfo = trustInfoPtr;
	int status;

	/* If the cert hasn't already been instantiated yet, do so now */
	if( trustInfo->iCryptCert == CRYPT_ERROR )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Instantiate the cert */
		setMessageCreateObjectIndirectInfo( &createInfo, trustInfo->certObject,
											trustInfo->certObjectLength,
											CRYPT_CERTTYPE_CERTIFICATE );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
								  &createInfo, OBJECT_TYPE_CERTIFICATE );
		assert( cryptStatusOK( status ) );
		if( cryptStatusError( status ) )
			return( status );

		/* The cert was successfully instantiated, free its encoded form */
		zeroise( trustInfo->certObject, trustInfo->certObjectLength );
		clFree( "getTrustedCert", trustInfo->certObject );
		trustInfo->certObject = NULL;
		trustInfo->certObjectLength = 0;
		trustInfo->iCryptCert = createInfo.cryptHandle;
		}

	/* Return the trusted cert */
	return( trustInfo->iCryptCert );
	}

int enumTrustedCerts( void *trustInfoPtr, const CRYPT_CERTIFICATE iCryptCtl, 
					  const CRYPT_KEYSET iCryptKeyset )
	{
	TRUST_INFO **trustInfoIndex = ( TRUST_INFO ** ) trustInfoPtr;
	int i;

	assert( iCryptCtl == CRYPT_UNUSED || iCryptKeyset == CRYPT_UNUSED );

	/* If there's no destination for the trusted certs supplied, it's a 
	   presence check only */
	if( iCryptCtl == CRYPT_UNUSED && iCryptKeyset == CRYPT_UNUSED )
		{
		for( i = 0; i < TRUSTINFO_SIZE; i++ )
			if( trustInfoIndex[ i ] != NULL )
				return( CRYPT_OK );

		return( CRYPT_ERROR_NOTFOUND );
		}

	for( i = 0; i < TRUSTINFO_SIZE; i++ )
		{
		TRUST_INFO *trustInfoCursor;

		for( trustInfoCursor = trustInfoIndex[ i ]; trustInfoCursor != NULL; \
			 trustInfoCursor = trustInfoCursor->next )	
			{
			const CRYPT_CERTIFICATE iCryptCert = \
										getTrustedCert( trustInfoCursor );
			int status;

			if( cryptStatusError( iCryptCert ) )
				return( iCryptCert );
			if( iCryptCtl != CRYPT_UNUSED )
				{
				/* We're sending trusted certs to a cert trust list */
				status = krnlSendMessage( iCryptCtl, IMESSAGE_SETATTRIBUTE,
										  ( void * ) &iCryptCert,
										  CRYPT_IATTRIBUTE_CERTCOLLECTION );
				if( cryptStatusError( status ) )
					return( status );
				}
			else
				{
				MESSAGE_KEYMGMT_INFO setkeyInfo;

				/* We're sending trusted certs to a keyset */
				setMessageKeymgmtInfo( &setkeyInfo, CRYPT_KEYID_NONE, NULL, 0,
									   NULL, 0, KEYMGMT_FLAG_NONE );
				setkeyInfo.cryptHandle = iCryptCert;
				status = krnlSendMessage( iCryptKeyset, IMESSAGE_KEY_SETKEY, 
										  &setkeyInfo, 
										  KEYMGMT_ITEM_PUBLICKEY );
				}
			if( cryptStatusError( status ) )
				return( status );
			}
		}
	
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Add/Update Trusted Cert Info					*
*																			*
****************************************************************************/

/* Add and delete a trust entry */

static int addEntry( void *trustInfoPtr, const CRYPT_CERTIFICATE iCryptCert, 
					 const void *certObject, const int certObjectLength )
	{
	TRUST_INFO **trustInfoIndex = ( TRUST_INFO ** ) trustInfoPtr;
	TRUST_INFO *newElement;
	BOOLEAN recreateCert = FALSE;
	int trustInfoEntry;

	/* 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 )
		{
		CRYPT_CONTEXT iCryptContext;
		int status;

		status = krnlSendMessage( iCryptCert, IMESSAGE_GETDEPENDENT,
								  &iCryptContext, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			/* There's no context associated with this cert, we'll have to
			   recreate it later */
			recreateCert = TRUE;
		else
			{
			status = krnlSendMessage( iCryptContext, IMESSAGE_CHECK, NULL,
									  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 * ) \
				clAlloc( "addEntry", sizeof( TRUST_INFO ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newElement, 0, sizeof( TRUST_INFO ) );
	if( certObject == NULL )
		{
		DYNBUF subjectDB, subjectKeyDB;
		BOOLEAN hasSKID = FALSE;
		int status;

⌨️ 快捷键说明

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