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

📄 cmp.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*						 cryptlib CMP Session Management					*
*						Copyright Peter Gutmann 1999-2003					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "asn1_rw.h"
  #include "asn1s_rw.h"
  #include "session.h"
  #include "cmp.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../misc/asn1_rw.h"
  #include "../misc/asn1s_rw.h"
  #include "../session/session.h"
  #include "../session/cmp.h"
#else
  #include "crypt.h"
  #include "misc/asn1_rw.h"
  #include "misc/asn1s_rw.h"
  #include "session/session.h"
  #include "session/cmp.h"
#endif /* Compiler-specific includes */

/* CMP requires a variety of authentication contexts, which are mapped to 
   session info contexts as follows:

			|	iAuthIn		|	iAuthOut
	--------+---------------+-------------------
	Client	|	CA cert		|	Client privKey
			|				|		or MAC
	Server	|	Client cert	|	CA privKey
			|		or MAC	|

   In addition general user information on the server side is stored in the 
   cmpUserInfo object */

#ifdef USE_CMP

/* If we're reading predefined requests/responses from disk instead of 
   communicating with the client/server, skip the network reads/writes */

#ifdef SKIP_IO
  #define readPkiDatagram( dummy )	CRYPT_OK
  #define writePkiDatagram( dummy )	CRYPT_OK
#endif /* SKIP_IO */

/* The following macro can be used to enable dumping of PDUs to disk.  As a
   safeguard, this only works in the Win32 debug version to prevent it from
   being accidentally enabled in any release version */

#if defined( __WIN32__ ) && !defined( NDEBUG )
/* #define DUMP_SERVER_MESSAGES */
  #define DEBUG_DUMP_CMP( type, level, sessionInfo ) \
		  debugDump( type, level, sessionInfo )
#else
  #define DEBUG_DUMP_CMP( type, level, sessionInfo )
#endif /* Win32 debug */

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

#if defined( __WIN32__ ) && !defined( NDEBUG )

/* Dump a message to disk for diagnostic purposes.  The CMP messages are
   complex enough that we can't use the normal DEBUG_DUMP() macro but have
   to use a special-purpose function that uses meaningful names for all
   of the files that are created */

static void debugDump( const int type, const int phase,
					   const SESSION_INFO *sessionInfoPtr )
	{
	static const FAR_BSS char *irStrings[] = \
		{ "cmpi1_ir", "cmpi2_ip", "cmpi3_conf", "cmpi4_confack" };
	static const FAR_BSS char *crStrings[] = \
		{ "cmpc1_cr", "cmpc2_cp", "cmpc3_conf", "cmpc4_confack" };
	static const FAR_BSS char *kurStrings[] = \
		{ "cmpk1_kur", "cmpk2_kup", "cmpk3_conf", "cmpk4_confack" };
	static const FAR_BSS char *rrStrings[] = \
		{ "cmpr1_rr", "cmpr2_rp" };
	static const FAR_BSS char *gmStrings[] = \
		{ "cmpg1_gr", "cmpg2_gp" };
	static const FAR_BSS char *errorStrings[] = \
		{ "cmpe1_error" };
	static const FAR_BSS char *unkStrings[] = \
		{ "cmp_unknown1", "cmp_unknown2", "cmp_unknown3", "cmp_unknown4" };
	const char **fnStringPtr = ( type == CTAG_PB_IR ) ? irStrings : \
							   ( type == CTAG_PB_CR ) ? crStrings : \
							   ( type == CTAG_PB_KUR ) ? kurStrings : \
							   ( type == CTAG_PB_RR ) ? rrStrings : \
							   ( type == CTAG_PB_GENM ) ? gmStrings : \
							   ( type == CTAG_PB_ERROR ) ? errorStrings : \
							  unkStrings;
	FILE *filePtr;
	char fileName[ 1024 ];

#ifndef DUMP_SERVER_MESSAGES
	/* Server messages have complex names based on the server DN, so we only 
	   dump them if explicitly requested */
	if( sessionInfoPtr->flags & SESSION_ISSERVER )
		return;
#endif /* !DUMP_SERVER_MESSAGES */

/*	GetTempPath( 512, fileName ); */
	strcpy( fileName, "/tmp/" );
	if( sessionInfoPtr->flags & SESSION_ISSERVER )
		{
		RESOURCE_DATA msgData;
		const int pathLength = strlen( fileName );
		int i;

		setMessageData( &msgData, fileName + pathLength, 1024 - pathLength );
		krnlSendMessage( sessionInfoPtr->privateKey, IMESSAGE_GETATTRIBUTE_S, 
						 &msgData, CRYPT_CERTINFO_DN );
		for( i = 0; i < msgData.length; i++ )
			{
			const int ch = fileName[ pathLength + i ];

			if( ch == ' ' || ch == '\'' || ch == '"' || ch == '?' || \
				ch == '*' || ch == '[' || ch == ']' || ch == '`' || \
				ch == ',' || ch < ' ' || ch > 'z' )
				fileName[ pathLength + i ] = '_';
			}
		strcat( fileName, "_" );
		}
	strcat( fileName, fnStringPtr[ phase - 1 ] );
	strcat( fileName, ".der" );

	filePtr = fopen( fileName, "wb" );
	if( filePtr != NULL )
		{
		fwrite( sessionInfoPtr->receiveBuffer, 1,
				sessionInfoPtr->receiveBufEnd, filePtr );
		fclose( filePtr );
		}
	}
#endif /* Windows debug mode only */

/* Map request to response types */

static const struct {
	const int request, response;
	const int cryptlibRequest;
	} reqRespMapTbl[] = {
	{ CTAG_PB_IR, CTAG_PB_IP, CRYPT_REQUESTTYPE_INITIALISATION },
	{ CTAG_PB_CR, CTAG_PB_CP, CRYPT_REQUESTTYPE_CERTIFICATE },
	{ CTAG_PB_P10CR, CTAG_PB_CP, CRYPT_REQUESTTYPE_CERTIFICATE },
	{ CTAG_PB_POPDECC, CTAG_PB_POPDECR, CRYPT_ERROR },
	{ CTAG_PB_KUR, CTAG_PB_KUP, CRYPT_REQUESTTYPE_KEYUPDATE },
	{ CTAG_PB_KRR, CTAG_PB_KRP, CRYPT_ERROR },
	{ CTAG_PB_RR, CTAG_PB_RP, CRYPT_REQUESTTYPE_REVOCATION },
	{ CTAG_PB_CCR, CTAG_PB_CCP, CRYPT_ERROR },
	{ CTAG_PB_GENM, CTAG_PB_GENP, CRYPT_REQUESTTYPE_PKIBOOT },
	{ CTAG_PB_LAST, CTAG_PB_LAST, CRYPT_ERROR }
	};

int reqToResp( const int reqType )
	{
	int i;

	for( i = 0; reqRespMapTbl[ i ].request != reqType && \
				reqRespMapTbl[ i ].request != CTAG_PB_LAST; i++ );
	return( reqRespMapTbl[ i ].response );
	}
static int reqToClibReq( const int reqType )
	{
	int i;

	for( i = 0; reqRespMapTbl[ i ].request != reqType && \
				reqRespMapTbl[ i ].request != CTAG_PB_LAST; i++ );
	return( reqRespMapTbl[ i ].cryptlibRequest );
	}
static int clibReqToReq( const int reqType )
	{
	int i;

	for( i = 0; reqRespMapTbl[ i ].cryptlibRequest != reqType && \
				reqRespMapTbl[ i ].request != CTAG_PB_LAST; i++ );
	return( reqRespMapTbl[ i ].request );
	}

/* Initialise the MAC info used to protect the messages */

int initMacInfo( const CRYPT_CONTEXT iMacContext, const void *userPassword, 
				 const int userPasswordLength, const void *salt, 
				 const int saltLength, const int iterations )
	{
	MECHANISM_DERIVE_INFO mechanismInfo;
	RESOURCE_DATA msgData;
	BYTE macKey[ CRYPT_MAX_HASHSIZE ];
	const void *passwordPtr = userPassword;
	int passwordLength = userPasswordLength, status;

	/* Turn the user password into an HMAC key using the CMP/Entrust password
	   derivation mechanism */
	setMechanismDeriveInfo( &mechanismInfo, macKey, CMP_HMAC_KEYSIZE,
							passwordPtr, passwordLength, CRYPT_ALGO_SHA,
							( void * ) salt, saltLength, iterations );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, 
							  &mechanismInfo, MECHANISM_CMP );
	if( cryptStatusError( status ) )
		return( status );

	/* Load the key into the MAC context */
	setMessageData( &msgData, macKey, CMP_HMAC_KEYSIZE );
	status = krnlSendMessage( iMacContext, IMESSAGE_SETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_KEY );
	zeroise( macKey, CRYPT_MAX_HASHSIZE );
	return( status );
	}

/* Initialise and destroy the protocol state information */

#define PROTOCOLINFO_SET_USERID		0x01
#define PROTOCOLINFO_SET_TRANSID	0x02
#define PROTOCOLINFO_SET_MACINFO	0x04
#define PROTOCOLINFO_SET_MACCTX		0x08
#define PROTOCOLINFO_SET_ALL		( PROTOCOLINFO_SET_USERID | \
									  PROTOCOLINFO_SET_TRANSID | \
									  PROTOCOLINFO_SET_MACINFO | \
									  PROTOCOLINFO_SET_MACCTX )

static void initProtocolInfo( CMP_PROTOCOL_INFO *protocolInfo, 
							  const BOOLEAN isCryptlib )
	{
	memset( protocolInfo, 0, sizeof( CMP_PROTOCOL_INFO ) );
	protocolInfo->iMacContext = protocolInfo->iAltMacContext = CRYPT_ERROR;
	protocolInfo->authContext = CRYPT_ERROR;
	if( isCryptlib )
		protocolInfo->isCryptlib = TRUE;
	}

static int setProtocolInfo( CMP_PROTOCOL_INFO *protocolInfo, 
							const void *userID, const int userIDlength, 
							const int flags )
	{
	RESOURCE_DATA msgData;
	int status;

	/* Set state info */
	setMessageData( &msgData, protocolInfo->senderNonce, CMP_NONCE_SIZE );
	krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
					 &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
	protocolInfo->senderNonceSize = CMP_NONCE_SIZE;

	/* Set fixed identification information */
	if( flags & PROTOCOLINFO_SET_USERID )
		{
		assert( isReadPtr( userID, userIDlength ) );
		memcpy( protocolInfo->userID, userID, userIDlength );
		protocolInfo->userIDsize = userIDlength;
		}
	if( flags & PROTOCOLINFO_SET_TRANSID )
		{
		setMessageData( &msgData, protocolInfo->transID, CMP_NONCE_SIZE );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusError( status ) )
			return( status );
		protocolInfo->transIDsize = CMP_NONCE_SIZE;
		}

	/* Set the MAC info and context */
	if( flags & PROTOCOLINFO_SET_MACINFO )
		{
		setMessageData( &msgData, protocolInfo->salt, CMP_NONCE_SIZE );
		krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
						 &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		protocolInfo->saltSize = CMP_NONCE_SIZE;
		protocolInfo->iterations = CMP_PASSWORD_ITERATIONS;
		}
	if( flags & PROTOCOLINFO_SET_MACCTX )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		assert( protocolInfo->iMacContext == CRYPT_ERROR && \
				protocolInfo->iAltMacContext == CRYPT_ERROR );
		setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_HMAC_SHA );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		protocolInfo->iMacContext = createInfo.cryptHandle;
		protocolInfo->useMACsend = protocolInfo->useMACreceive = TRUE;
		}

	return( CRYPT_OK );
	}

static void destroyProtocolInfo( CMP_PROTOCOL_INFO *protocolInfo )
	{
	/* Destroy any active MAC contexts.  The authContext is just a reference 
	   to the appropriate context in the session info so we don't destroy it 
	   here */
	if( protocolInfo->iMacContext != CRYPT_ERROR )
		krnlSendNotifier( protocolInfo->iMacContext, IMESSAGE_DECREFCOUNT );
	if( protocolInfo->iAltMacContext != CRYPT_ERROR )
		krnlSendNotifier( protocolInfo->iMacContext, IMESSAGE_DECREFCOUNT );

	zeroise( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) );
	}

/* Set up user authentication information (either a MAC context or a public 
   key) based on a request submitted by the client.  This is done whenever 
   the client starts a new transaction with a new user ID or cert ID */

int initServerAuthentMAC( SESSION_INFO *sessionInfoPtr, 
						  CMP_PROTOCOL_INFO *protocolInfo )
	{
	MESSAGE_KEYMGMT_INFO getkeyInfo;
	int status;

	assert( protocolInfo->userIDsize == 9 );

	/* Set up general authentication information and if there's user info 
	   still present from a previous transaction, clear it */
	status = setProtocolInfo( protocolInfo, NULL, 0, 
							  PROTOCOLINFO_SET_MACCTX );
	if( cryptStatusError( status ) )
		return( status );
	if( sessionInfoPtr->cmpUserInfo != CRYPT_ERROR )
		{
		krnlSendNotifier( sessionInfoPtr->cmpUserInfo, 
						  IMESSAGE_DECREFCOUNT );
		sessionInfoPtr->cmpUserInfo = CRYPT_ERROR;
		}

	/* Get the user info for the user identified by the user ID from the 
	   cert store.  If we get a not-found error we report it as "signer not 
	   trusted", which can also mean "signer unknown" */
	setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID,
						   protocolInfo->userID, protocolInfo->userIDsize, 
						   NULL, 0, KEYMGMT_FLAG_NONE );
	status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
							  IMESSAGE_KEY_GETKEY, &getkeyInfo, 
							  KEYMGMT_ITEM_PKIUSER );
	if( cryptStatusError( status ) )
		{
		protocolInfo->pkiFailInfo = CMPFAILINFO_SIGNERNOTTRUSTED;
		retExt( sessionInfoPtr, status, 
				"Couldn't find PKI user information for requested user" );
		}
	sessionInfoPtr->cmpUserInfo = getkeyInfo.cryptHandle;
	protocolInfo->userIDchanged = FALSE;

	/* Get the password from the PKI user object if necessary */
	if( sessionInfoPtr->passwordLength <= 0 )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, sessionInfoPtr->password, 
						CRYPT_MAX_TEXTSIZE );
		status = krnlSendMessage( sessionInfoPtr->cmpUserInfo,
								  IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_CERTINFO_PKIUSER_ISSUEPASSWORD );
		if( cryptStatusError( status ) )
			retExt( sessionInfoPtr, status, 
					"Couldn't read PKI user data from PKI user object" );
		sessionInfoPtr->passwordLength = msgData.length;
		sessionInfoPtr->flags |= SESSION_ISENCODEDPW;
		}

	return( CRYPT_OK );
	}

int initServerAuthentSign( SESSION_INFO *sessionInfoPtr, 

⌨️ 快捷键说明

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