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

📄 cmp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						 cryptlib CMP Session Management					*
*						Copyright Peter Gutmann 1999-2007					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "crypt.h"
  #include "asn1.h"
  #include "asn1_ext.h"
  #include "session.h"
  #include "cmp.h"
#else
  #include "crypt.h"
  #include "misc/asn1.h"
  #include "misc/asn1_ext.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, type )	CRYPT_OK
  #define writePkiDatagram( dummy, type )	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 + 8 ];

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

/*	GetTempPath( 512, fileName ); */
	strlcpy_s( fileName, 1024, "/tmp/" );
	if( isServer( sessionInfoPtr ) )
		{
		MESSAGE_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 ] = '_';
			}
		strlcat_s( fileName, 1024, "_" );
		}
	strlcat_s( fileName, 1024, fnStringPtr[ phase - 1 ] );
	strlcat_s( fileName, 1024, ".der" );

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

/* Map request to response types */

static const MAP_TABLE reqRespMapTbl[] = {
	{ CTAG_PB_IR, CTAG_PB_IP },
	{ CTAG_PB_CR, CTAG_PB_CP },
	{ CTAG_PB_P10CR, CTAG_PB_CP },
	{ CTAG_PB_POPDECC, CTAG_PB_POPDECR },
	{ CTAG_PB_KUR, CTAG_PB_KUP },
	{ CTAG_PB_KRR, CTAG_PB_KRP },
	{ CTAG_PB_RR, CTAG_PB_RP },
	{ CTAG_PB_CCR, CTAG_PB_CCP },
	{ CTAG_PB_GENM, CTAG_PB_GENP },
	{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
	};

static const MAP_TABLE reqClibReqMapTbl[] = {
	{ CTAG_PB_IR, CRYPT_REQUESTTYPE_INITIALISATION },
	{ CTAG_PB_CR, CRYPT_REQUESTTYPE_CERTIFICATE },
	{ CTAG_PB_P10CR, CRYPT_REQUESTTYPE_CERTIFICATE },
	{ CTAG_PB_KUR, CRYPT_REQUESTTYPE_KEYUPDATE },
	{ CTAG_PB_RR, CRYPT_REQUESTTYPE_REVOCATION },
	{ CTAG_PB_GENM, CRYPT_REQUESTTYPE_PKIBOOT },
	{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
	};

static const MAP_TABLE clibReqReqMapTbl[] = {
	{ CRYPT_REQUESTTYPE_INITIALISATION, CTAG_PB_IR },
	{ CRYPT_REQUESTTYPE_CERTIFICATE, CTAG_PB_CR },
	{ CRYPT_REQUESTTYPE_CERTIFICATE, CTAG_PB_P10CR },
	{ CRYPT_REQUESTTYPE_KEYUPDATE, CTAG_PB_KUR },
	{ CRYPT_REQUESTTYPE_REVOCATION, CTAG_PB_RR },
	{ CRYPT_REQUESTTYPE_PKIBOOT, CTAG_PB_GENM },
	{ CRYPT_ERROR, CRYPT_ERROR }, { CRYPT_ERROR, CRYPT_ERROR }
	};

int reqToResp( const int reqType )
	{
	int value, status;

	status = mapValue( reqType, &value, reqRespMapTbl, 
					   FAILSAFE_ARRAYSIZE( reqRespMapTbl, MAP_TABLE ) );
	return( cryptStatusError( status ) ? status : value );
	}
static int reqToClibReq( const int reqType )
	{
	int value, status;

	status = mapValue( reqType, &value, reqClibReqMapTbl, 
					   FAILSAFE_ARRAYSIZE( reqClibReqMapTbl, MAP_TABLE ) );
	return( cryptStatusError( status ) ? status : value );
	}
static int clibReqToReq( const int reqType )
	{
	int value, status;

	status = mapValue( reqType, &value, clibReqReqMapTbl, 
					   FAILSAFE_ARRAYSIZE( clibReqReqMapTbl, MAP_TABLE ) );
	return( cryptStatusError( status ) ? status : value );
	}

/* 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;
	MESSAGE_DATA msgData;
	BYTE macKey[ CRYPT_MAX_HASHSIZE + 8 ];
	const void *passwordPtr = userPassword;
	int passwordLength = userPasswordLength, status;

	assert( isHandleRangeValid( iMacContext ) );
	assert( isReadPtr( userPassword, userPasswordLength ) );
	assert( isReadPtr( salt, saltLength ) );
	assert( iterations >= 1 );

	/* 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_SHA1,
							( void * ) salt, saltLength, iterations );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE, 
							  &mechanismInfo, MECHANISM_DERIVE_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 )
	{
	MESSAGE_DATA msgData;
	int status;

	assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );

	/* 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 )
	{
	assert( isWritePtr( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) ) );

	/* 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->iAltMacContext, 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 )
	{
	CMP_INFO *cmpInfo = sessionInfoPtr->sessionCMP;

⌨️ 快捷键说明

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