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

📄 cryptdbx.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						 cryptlib Key Database Routines						*
*						Copyright Peter Gutmann 1995-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "crypt.h"
#ifdef INC_ALL
  #include "asn1.h"
  #include "keyset.h"
#else
  #include "keymgmt/asn1.h"
  #include "misc/keyset.h"
#endif /* Compiler-specific includes */

/* Prototypes for misc key read functions */

int getKeysetType( STREAM *stream );

/* Some keysets aren't supported on some platforms so we alias the calls out */

#if !( defined( __WINDOWS__ ) || defined( __UNIX__ ) )
  #define setAccessMethodDBMS( x, y )		CRYPT_ARGERROR_NUM1
#endif /* !( __WINDOWS__ || __UNIX__ ) */
#ifndef DBX_LDAP
  #define setAccessMethodLDAP( x )			CRYPT_ARGERROR_NUM1
#endif /* DBX_LDAP */
#ifndef NET_TCP
  #define setAccessMethodHTTP( x )			CRYPT_ARGERROR_NUM1
#endif /* NET_TCP */

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

/* Initialise and down any databases we're working with */

void dbxInitODBC( void );
void dbxEndODBC( void );
void dbxInitLDAP( void );
void dbxEndLDAP( void );

void initKeysets( void )
	{
#if defined( __WINDOWS__ ) && !defined( NT_DRIVER )
  #ifdef DBX_ODBC
	dbxInitODBC();
  #endif /* DBX_ODBC */
  #ifdef DBX_LDAP
	dbxInitLDAP();
  #endif /* DBX_LDAP */
#endif /* __WINDOWS__ && !NT_DRIVER */
	}

void shutdownKeysets( void )
	{
#if defined( __WINDOWS__ ) && !defined( NT_DRIVER )
  #ifdef DBX_ODBC
	dbxEndODBC();
  #endif /* DBX_ODBC */
  #ifdef DBX_LDAP
	dbxEndLDAP();
  #endif /* DBX_LDAP */
#endif /* __WINDOWS__ && !NT_DRIVER */
	}

/****************************************************************************
*																			*
*								Keyset API Functions						*
*																			*
****************************************************************************/

/* Handle a message sent to a keyset object */

static int keysetMessageFunction( const CRYPT_KEYSET cryptKeyset,
								  const RESOURCE_MESSAGE_TYPE message,
								  void *messageDataPtr,
								  const int messageValue )
	{
	KEYSET_INFO *keysetInfoPtr;

	getCheckInternalResource( cryptKeyset, keysetInfoPtr, OBJECT_TYPE_KEYSET );

	/* Process the destroy object message */
	if( message == RESOURCE_MESSAGE_DESTROY )
		{
		/* If the keyset is active, perform any required cleanup functions */
		if( keysetInfoPtr->isOpen )
			{
			/* Shut down the keyset if required */
			if( keysetInfoPtr->shutdownFunction != NULL )
				keysetInfoPtr->shutdownFunction( keysetInfoPtr );

			/* If the keyset is implemented as a file, close it (the keyset-
			   specific handler sees only an I/O stream and doesn't perform 
			   any file-level functions).  Because we cache all information 
			   in a PKCS #15 keyset and close the stream immediately 
			   afterwards if we've opened it in read-only mode, we only 
			   close the stream for a PKCS #15 keyset if it's been opened in 
			   R/W mode (note the distinction between the keyset being active
			   and the stream being active, for PKCS #15 the keyset can be
			   active without being associated with an open stream) */
			if( keysetInfoPtr->type == CRYPT_KEYSET_FILE && \
				!( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 && \
				   keysetInfoPtr->options == CRYPT_KEYOPT_READONLY ) )
				{
				/* Since the update may have changed the overall size, we
				   need to clear any leftover data from the previous 
				   version of the keyset before we close the file */
				if( keysetInfoPtr->isDirty )
					fileClearToEOF( &keysetInfoPtr->keysetFile.stream );
				sFileClose( &keysetInfoPtr->keysetFile.stream );

				/* If it's a newly-created empty keyset file (this can occur 
				   if there's some sort of error on writing and no keys are 
				   ever written to the keyset) or one in which all the keys
				   have been deleted, remove it */
				if( keysetInfoPtr->isEmpty )
					fileUnlink( keysetInfoPtr->keysetFile.fileName );
				}
			}

		/* Delete the objects locking variables and the object itself */
		unlockResource( keysetInfoPtr );
		deleteResourceLock( keysetInfoPtr );
		zeroise( keysetInfoPtr, sizeof( KEYSET_INFO ) );
		free( keysetInfoPtr );

		return( CRYPT_OK );
		}

	/* Process attribute get/set/delete messages */
	if( message == RESOURCE_MESSAGE_SETATTRIBUTE )
		{
		assert( messageValue == CRYPT_IATTRIBUTE_INITIALISED );

		/* It's an initialisation message, there's nothing to do */
		unlockResourceExit( keysetInfoPtr, CRYPT_OK );
		}
	if( message == RESOURCE_MESSAGE_SETATTRIBUTE_S )
		{
		RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int status;

		/* If it's encoded cryptlib-specific data, pass it through to the 
		   keyset */
		if( messageValue == CRYPT_IATTRIBUTE_CONFIGDATA || \
			messageValue == CRYPT_IATTRIBUTE_USERINDEX || \
			messageValue == CRYPT_IATTRIBUTE_USERID || \
			messageValue == CRYPT_IATTRIBUTE_USERINFO )
			{
			assert( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );
			assert( keysetInfoPtr->setItemFunction != NULL );

			status = keysetInfoPtr->setItemFunction( keysetInfoPtr,
							CRYPT_UNUSED, KEYMGMT_ITEM_DATA,
							msgData->data, msgData->length, messageValue );
			if( cryptStatusOK( status ) && \
				messageValue != CRYPT_IATTRIBUTE_USERID )
				{
				/* The update succeeded, remember that the data in the keyset 
				   has changed, unless it's a userID which just modifies 
				   existing data */
				keysetInfoPtr->isDirty = TRUE;
				keysetInfoPtr->isEmpty = FALSE;
				}
			unlockResourceExit( keysetInfoPtr, status );
			}

		assert( messageValue == CRYPT_KEYINFO_QUERY || \
				messageValue == CRYPT_KEYINFO_QUERY_REQUESTS );

		/* Make sure this access type is valid for this keyset */
		if( keysetInfoPtr->getFirstItemFunction == NULL )
			unlockResourceExit( keysetInfoPtr, CRYPT_ARGERROR_VALUE );
		if( messageValue == CRYPT_KEYINFO_QUERY_REQUESTS && \
			keysetInfoPtr->certMgmtFunction == NULL )
			unlockResourceExit( keysetInfoPtr, CRYPT_ARGERROR_VALUE );

		/* If we're in the middle of an existing query the user needs to 
		   cancel it before starting another one */
		if( keysetInfoPtr->queryInProgress && 
			( msgData->length != 6 || \
			  strnicmp( msgData->data, "cancel", msgData->length ) ) )
			return( CRYPT_ERROR_INCOMPLETE );

		/* Send the query to the data source */
		status = keysetInfoPtr->getFirstItemFunction( keysetInfoPtr, NULL,
						NULL, CRYPT_KEYID_NAME, msgData->data, msgData->length,
						( messageValue == CRYPT_KEYINFO_QUERY_REQUESTS ) ? \
							KEYMGMT_ITEM_REQUEST : KEYMGMT_ITEM_PUBLICKEY, 
						KEYMGMT_FLAG_NONE );
		unlockResourceExit( keysetInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_GETATTRIBUTE )
		{
		int *valuePtr = ( int * ) messageDataPtr;

		switch( messageValue )
			{
			case CRYPT_ATTRIBUTE_ERRORTYPE:
				*valuePtr = keysetInfoPtr->errorType;
				break;

			case CRYPT_ATTRIBUTE_ERRORLOCUS:
				*valuePtr = keysetInfoPtr->errorLocus;
				break;
			
			case CRYPT_ATTRIBUTE_INT_ERRORCODE:
				*valuePtr = keysetInfoPtr->errorCode;
				break;

			default:
				assert( NOTREACHED );
			}
		unlockResourceExit( keysetInfoPtr, CRYPT_OK );
		}
	if( message == RESOURCE_MESSAGE_GETATTRIBUTE_S )
		{
		RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;
		int status;

		/* If it's encoded cryptlib-specific data, fetch it from to the 
		   keyset */
		if( messageValue == CRYPT_IATTRIBUTE_CONFIGDATA || \
			messageValue == CRYPT_IATTRIBUTE_USERINDEX || \
			messageValue == CRYPT_IATTRIBUTE_USERINFO || \
			messageValue == CRYPT_IATTRIBUTE_TRUSTEDCERT || \
			messageValue == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT )
			{
			assert( keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 );

			status = keysetInfoPtr->getItemFunction( keysetInfoPtr,
										NULL, KEYMGMT_ITEM_DATA,
										CRYPT_KEYID_NONE, NULL, 0,
										msgData->data, &msgData->length, 
										messageValue );
			unlockResourceExit( keysetInfoPtr, status );
			}

		assert( messageValue == CRYPT_ATTRIBUTE_INT_ERRORMESSAGE );

		if( !*keysetInfoPtr->errorMessage )
			status = CRYPT_ERROR_NOTFOUND;
		else
			status = attributeCopy( msgData, keysetInfoPtr->errorMessage,
									strlen( keysetInfoPtr->errorMessage ) );
		unlockResourceExit( keysetInfoPtr, status );
		}

	/* Process messages which check a keyset */
	if( message == RESOURCE_MESSAGE_CHECK )
		{
		if( ( messageValue == RESOURCE_MESSAGE_CHECK_PKC_PRIVATE || \
			  messageValue == RESOURCE_MESSAGE_CHECK_PKC_DECRYPT || \
			  messageValue == RESOURCE_MESSAGE_CHECK_PKC_SIGN ) && \
			( keysetInfoPtr->type == KEYSET_DBMS || \
			  keysetInfoPtr->type == KEYSET_LDAP || \
			  keysetInfoPtr->type == KEYSET_HTTP ) )
			/* Public-key keysets can't contain objects which can perform 
			   private-key ops */
			unlockResourceExit( keysetInfoPtr, CRYPT_ARGERROR_OBJECT );

		unlockResourceExit( keysetInfoPtr, CRYPT_OK );
		}

	/* Process object-specific messages */
	if( message == RESOURCE_MESSAGE_KEY_GETKEY )
		{
		MESSAGE_KEYMGMT_INFO *getkeyInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
		CRYPT_KEYID_TYPE keyIDtype = getkeyInfo->keyIDtype;
		BYTE keyIDbuffer[ KEYID_SIZE ];
		const void *keyID = getkeyInfo->keyID;
		int keyIDlength = getkeyInfo->keyIDlength, status;

		assert( keyIDtype != CRYPT_KEYID_NONE && \
				keyID != NULL && getkeyInfo->keyIDlength > 0 );
		assert( keysetInfoPtr->getItemFunction != NULL );
		assert( messageValue != KEYMGMT_ITEM_PRIVATEKEY || \
				keysetInfoPtr->type == KEYSET_FILE );
		assert( ( messageValue != KEYMGMT_ITEM_SECRETKEY && \
				  messageValue != KEYMGMT_ITEM_DATA ) || \
				( keysetInfoPtr->type == KEYSET_FILE && \
				  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) );
		assert( ( messageValue != KEYMGMT_ITEM_REQUEST && \
				  messageValue != KEYMGMT_ITEM_REVOCATIONINFO && \
				  messageValue != KEYMGMT_ITEM_PKIUSER ) || \
				keysetInfoPtr->type == KEYSET_DBMS );
		assert( ( messageValue != KEYMGMT_ITEM_REQUEST && \
				  messageValue != KEYMGMT_ITEM_PKIUSER ) || \
				keysetInfoPtr->certMgmtFunction != NULL );

		/* If we're in the middle of a query, we can't do anything else */
		if( keysetInfoPtr->queryInProgress )
			return( CRYPT_ERROR_INCOMPLETE );

		/* If we've been passed a full issuerAndSerialNumber as a key ID and 
		   the keyset needs an issuerID, convert it */
		if( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
			( keysetInfoPtr->type == KEYSET_DBMS || \
			  ( keysetInfoPtr->type == KEYSET_FILE && \
			    keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) ) )
			{
			HASHFUNCTION hashFunction;
			int hashSize;

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

			/* Hash the full iAndS to get an issuerID and use that for the keyID */
			hashFunction( NULL, keyIDbuffer, ( BYTE * ) keyID, keyIDlength, 
						  HASH_ALL );
			keyIDtype = CRYPT_IKEYID_ISSUERID;
			keyID = keyIDbuffer;
			keyIDlength = hashSize;
			}

		/* Get the key */
		status = keysetInfoPtr->getItemFunction( keysetInfoPtr,
								&getkeyInfo->cryptHandle, messageValue,
								keyIDtype, keyID, keyIDlength, 
								getkeyInfo->auxInfo, &getkeyInfo->auxInfoLength, 
								getkeyInfo->flags );
		unlockResourceExit( keysetInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_KEY_SETKEY )
		{
		MESSAGE_KEYMGMT_INFO *setkeyInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
		int status;

		assert( messageValue != KEYMGMT_ITEM_PRIVATEKEY || \
				keysetInfoPtr->type == KEYSET_FILE );
		assert( ( messageValue != KEYMGMT_ITEM_SECRETKEY && \
				  messageValue != KEYMGMT_ITEM_DATA ) || \
				( keysetInfoPtr->type == KEYSET_FILE && \
				  keysetInfoPtr->subType == KEYSET_SUBTYPE_PKCS15 ) );
		assert( ( messageValue != KEYMGMT_ITEM_REQUEST && \
				  messageValue != KEYMGMT_ITEM_REVOCATIONINFO && \
				  messageValue != KEYMGMT_ITEM_PKIUSER ) || \
				( keysetInfoPtr->type == KEYSET_DBMS ) );
		assert( ( messageValue != KEYMGMT_ITEM_REQUEST && \
				  messageValue != KEYMGMT_ITEM_PKIUSER ) || \
				keysetInfoPtr->certMgmtFunction != NULL );

		/* Make sure we can write to the keyset.  This covers all 
		   possibilities (both keyset types for which writing isn't 
		   supported, and individual keysets which we can't write to because 
		   of things like file permissions), so once we pass this check we 
		   know we can write to the keyset */
		if( keysetInfoPtr->options == CRYPT_KEYOPT_READONLY )
			unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_PERMISSION );
		if( keysetInfoPtr->setItemFunction == NULL )
			unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_NOTAVAIL );

		/* Cert stores can't have certificates or CRLs inserted directly 
		   into them (there's a specific check for allowed item types in the
		   cert store-specific code, but we perform a quick check here for
		   explicitly disallowed items so we can return a more appropriate
		   permission error rather than a generic bad item error) */
		if( keysetInfoPtr->keysetDBMS.isCertStore && \
			( messageValue == KEYMGMT_ITEM_PUBLICKEY || \
			  messageValue == KEYMGMT_ITEM_REVOCATIONINFO ) )
			unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_PERMISSION );

		/* If we're in the middle of a query, we can't do anything else */
		if( keysetInfoPtr->queryInProgress )
			return( CRYPT_ERROR_INCOMPLETE );

		/* Set the key */
		status = keysetInfoPtr->setItemFunction( keysetInfoPtr, 
							setkeyInfo->cryptHandle, messageValue, 
							setkeyInfo->auxInfo, setkeyInfo->auxInfoLength, 
							setkeyInfo->flags );
		if( cryptStatusOK( status ) )
			{
			/* The update succeeded, remember that the data in the keyset has 
			   changed */
			keysetInfoPtr->isDirty = TRUE;
			keysetInfoPtr->isEmpty = FALSE;
			}
		unlockResourceExit( keysetInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_KEY_DELETEKEY )
		{
		MESSAGE_KEYMGMT_INFO *deletekeyInfo = \
								( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
		CRYPT_KEYID_TYPE keyIDtype = deletekeyInfo->keyIDtype;
		BYTE keyIDbuffer[ KEYID_SIZE ];
		const void *keyID = deletekeyInfo->keyID;
		int keyIDlength = deletekeyInfo->keyIDlength, status;

		/* Make sure we can write to the keyset.  This covers all 
		   possibilities (both keyset types for which writing isn't supported, 
		   and individual keysets which we can't write to because of things 
		   like file permissions), so once we pass this check we know we can 
		   write to the keyset */
		if( keysetInfoPtr->options == CRYPT_KEYOPT_READONLY )
			unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_PERMISSION );
		if( keysetInfoPtr->deleteItemFunction == NULL )
			unlockResourceExit( keysetInfoPtr, CRYPT_ERROR_NOTAVAIL );

		/* If we're in the middle of a query, we can't do anything else */
		if( keysetInfoPtr->queryInProgress )

⌨️ 快捷键说明

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