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

📄 cmp.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Decrypt the returned cert */
	status = krnlSendMessage( iSessionKey, RESOURCE_IMESSAGE_CTX_DECRYPT,
							  sMemBufPtr( stream ), encCertLength );
	krnlSendNotifier( iSessionKey, RESOURCE_IMESSAGE_DECREFCOUNT );
	return( status );
	}

/* Get information on a user from a cert store */

static int getUserInformation( SESSION_INFO *sessionInfoPtr,
							   const void *userID, const int userIDsize,
							   const BOOLEAN isPublicKey )
	{
	MESSAGE_KEYMGMT_INFO getkeyInfo;
	int status;

	assert( sessionInfoPtr->iAuthInContext == CRYPT_ERROR );

	/* Get the user info or public key from the cert store */
	setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_KEYID,
						   userID, userIDsize, NULL, 0, isPublicKey ? \
							KEYMGMT_FLAG_USAGE_SIGN : KEYMGMT_FLAG_NONE );
	status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
							  RESOURCE_IMESSAGE_KEY_GETKEY,
							  &getkeyInfo, isPublicKey ? \
								KEYMGMT_ITEM_PUBLICKEY : KEYMGMT_ITEM_PKIUSER );
	if( cryptStatusOK( status ) )
		sessionInfoPtr->iAuthInContext = getkeyInfo.cryptHandle;
	return( status );
	}

/****************************************************************************
*																			*
*								MAC Routines								*
*																			*
****************************************************************************/

/* The CMP spec never defines any keysize for the CMP/Entrust MAC, but
   everyone seems to use 160 bits for this */

#define HMAC_KEYSIZE		20

/* Initialise and destroy the protocol state information */

static int initProtocolInfo( CMP_PROTOCOL_INFO *protocolInfo,
							 const void *userID, const int userIDlength,
							 const BOOLEAN useMAC )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int status;

	/* Initialise the handshake state info values.  If this is state held
	   by the responder, some of the data will already have been set up
	   from the contents of the initiator's message so we only start from
	   scratch if this is completely new data */
	if( userID != NULL )
		{
		memset( protocolInfo, 0, sizeof( CMP_PROTOCOL_INFO ) );
		memcpy( protocolInfo->userID, userID, userIDlength );
		protocolInfo->userIDsize = userIDlength;
		getNonce( protocolInfo->transID, CMP_NONCE_SIZE );
		protocolInfo->transIDsize = CMP_NONCE_SIZE;
		}
	getNonce( protocolInfo->senderNonce, CMP_NONCE_SIZE );
	protocolInfo->senderNonceSize = CMP_NONCE_SIZE;
	protocolInfo->iMacContext = \
		protocolInfo->iAltMacContext = CRYPT_ERROR;
	protocolInfo->useMACsend = protocolInfo->useMACreceive = useMAC;

	/* If we're not using a MAC for message protection, we're done */
	if( !useMAC )
		return( CRYPT_OK );

	/* Set up the MAC values.  We only set up the salt if we're the initiator
	   since the responder will get their salt from the incoming message */
	if( userID != NULL )
		{
		getNonce( protocolInfo->salt, CMP_NONCE_SIZE );
		protocolInfo->saltSize = CMP_NONCE_SIZE;
		}
#ifdef SKIP_IO
	puts( "CMP: Using fixed salt to allow MAC to verify." );
	memcpy( protocolInfo->salt,
			"\xDD\xEF\xCF\xC9\x93\x1F\x28\xA7\x55\x5A\x14\x9F\x13\x90\xE2\x60",
			16 );
#endif /* SKIP_IO */
	protocolInfo->iterations = CMP_PASSWORD_ITERATIONS;

	/* Create the MAC context used to protect the messages */
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_HMAC_SHA );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusOK( status ) )
		protocolInfo->iMacContext = createInfo.cryptHandle;

	return( status );
	}

static void destroyProtocolInfo( CMP_PROTOCOL_INFO *protocolInfo )
	{
	/* Destroy any active contexts */
	if( protocolInfo->iMacContext != CRYPT_ERROR )
		krnlSendNotifier( protocolInfo->iMacContext,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
	if( protocolInfo->iAltMacContext != CRYPT_ERROR )
		krnlSendNotifier( protocolInfo->iMacContext,
						  RESOURCE_IMESSAGE_DECREFCOUNT );

	zeroise( protocolInfo, sizeof( CMP_PROTOCOL_INFO ) );
	}

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

static 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 decodedPassword[ CRYPT_MAX_TEXTSIZE ];
	BYTE macKey[ CRYPT_MAX_HASHSIZE ];
	const void *passwordPtr = userPassword;
	int passwordLength = userPasswordLength, status;

	/* If it's a cryptlib-style password, decode it into its binary value.
	   We don't need to check the return value since the validity has already
	   been checked when the password was set*/
	if( isUserValue( userPassword, userPasswordLength ) )
		{
		passwordLength = decodeUserValue( decodedPassword, userPassword,
										  userPasswordLength );
		passwordPtr = decodedPassword;
		}

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

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

/* Read/write the CMP/Entrust MAC information:

	macInfo ::= SEQUENCE {
		algoID			OBJECT IDENTIFIER (entrustMAC),
		algoParams		SEQUENCE {
			salt		OCTET STRING,
			pwHashAlgo	AlgorithmIdentifier (SHA-1)
			iterations	INTEGER,
			macAlgo		AlgorithmIdentifier (HMAC-SHA1)
			}
		} */

static void writeMacInfo( STREAM *stream,
						  const CMP_PROTOCOL_INFO *protocolInfo )
	{
	int paramSize;

	/* Determine how big the payload will be */
	paramSize = ( int ) sizeofObject( protocolInfo->saltSize ) + \
				sizeofAlgoID( CRYPT_ALGO_SHA ) + \
				sizeofShortInteger( CMP_PASSWORD_ITERATIONS ) + \
				sizeofAlgoID( CRYPT_ALGO_HMAC_SHA );

	/* Write the wrapper */
	writeSequence( stream, sizeofOID( OID_ENTRUST_MAC ) + \
						   ( int ) sizeofObject( paramSize ) );
	writeOID( stream, OID_ENTRUST_MAC );

	/* Write the payload */
	writeSequence( stream, paramSize );
	writeOctetString( stream, protocolInfo->salt, protocolInfo->saltSize,
					  DEFAULT_TAG );
	writeAlgoID( stream, CRYPT_ALGO_SHA );
	writeShortInteger( stream, CMP_PASSWORD_ITERATIONS, DEFAULT_TAG );
	writeAlgoID( stream, CRYPT_ALGO_HMAC_SHA );
	}

static int readMacInfo( STREAM *stream, CMP_PROTOCOL_INFO *protocolInfo,
						const void *password, const int passwordLength )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BYTE salt[ CRYPT_MAX_HASHSIZE ];
	long value;
	int saltLength, iterations, status;

	/* Read the various parameter fields */
	readSequence( stream, NULL );
	status = readOID( stream, OID_ENTRUST_MAC );
	if( cryptStatusError( status ) )
		{
		/* If we don't find this OID we have to specifically report it as an
		   unknown algorithm problem rather than a generic bad data error */
		protocolInfo->pkiFailInfo = CMPFAILINFO_BADALG;
		return( status );
		}
	readSequence( stream, NULL );
	readOctetString( stream, salt, &saltLength, CRYPT_MAX_HASHSIZE );
	readUniversal( stream );
	readShortInteger( stream, &value );
	status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );
	iterations = ( int ) value;
	if( iterations > CMP_MAX_PASSWORD_ITERATIONS )
		{
		/* Prevent DoS attacks due to excessive iteration counts (bad
		   algorithm is about the most appropriate error we can return
		   here) */
		protocolInfo->pkiFailInfo = CMPFAILINFO_BADALG;
		return( CRYPT_ERROR_BADDATA );
		}

	/* If we're the responder and the MAC parameters aren't set yet, set
	   them based on the initiator's values.  If we're using MAC protection
	   and the parameters match our original MAC, reuse the MAC context*/
	if( !protocolInfo->saltSize )
		{
		status = initMacInfo( protocolInfo->iMacContext, password,
							  passwordLength, salt, saltLength, iterations );
		memcpy( protocolInfo->salt, salt, saltLength );
		protocolInfo->saltSize = saltLength;
		protocolInfo->iterations = iterations;
		return( status );
		}
	if( protocolInfo->iterations && \
		saltLength == protocolInfo->saltSize && \
		!memcmp( salt, protocolInfo->salt, saltLength ) && \
		iterations == protocolInfo->iterations )
		{
		protocolInfo->useAltMAC = FALSE;
		return( CRYPT_OK );
		}
	protocolInfo->useAltMAC = TRUE;	/* Use the alternative MAC context */

	/* If we've got an alternative MAC context using the returned parameters
	   already set up from a previous message, reuse this */
	if( protocolInfo->iAltMacContext != CRYPT_ERROR && \
		saltLength == protocolInfo->altSaltSize && \
		!memcmp( salt, protocolInfo->altSalt, saltLength ) && \
		iterations == protocolInfo->altIterations )
		return( CRYPT_OK );

	/* This is a new set of parameters, create a new MAC context with them */
	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_HMAC_SHA );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	status = initMacInfo( createInfo.cryptHandle, password, passwordLength,
						  salt, saltLength, iterations );
	if( cryptStatusOK( status ) )
		{
		if( protocolInfo->iAltMacContext != CRYPT_ERROR )
			krnlSendNotifier( protocolInfo->iAltMacContext,
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		protocolInfo->iAltMacContext = createInfo.cryptHandle;
		memcpy( protocolInfo->altSalt, salt, saltLength );
		protocolInfo->altSaltSize = saltLength;
		protocolInfo->altIterations = iterations;
		}
	else
		krnlSendNotifier( createInfo.cryptHandle,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
	return( status );
	}

/* Hash/MAC the message header and body */

static int hashMessageContents( const CRYPT_CONTEXT iHashContext,
								const void *data, const int length )
	{
	STREAM stream;
	BYTE buffer[ 8 ];

	/* Delete the hash/MAC value, which resets the context */
	krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_DELETEATTRIBUTE,
					 NULL, CRYPT_CTXINFO_HASHVALUE );

	/* Write the pseudoheader used for hashing/MACing the header and body and
	   hash/MAC it */
	sMemOpen( &stream, buffer, 8 );
	writeSequence( &stream, length );
	krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH, buffer,
					 stell( &stream ) );
	sMemClose( &stream );
	krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
					 ( void * ) data, length );
	return( krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_CTX_HASH,
							 buffer, 0 ) );
	}

/****************************************************************************
*																			*
*								PKI Body Functions							*
*																			*
****************************************************************************/

/* Write assorted PKI body messages */

static int writeRequestBody( STREAM *stream,
							 const SESSION_INFO *sessionInfoPtr,
							 const CMP_PROTOCOL_INFO *protocolInfo )
	{
	const CRYPT_ATTRIBUTE_TYPE attrType = \
				( protocolInfo->operation == CTAG_PB_RR ) ? \
				CRYPT_IATTRIBUTE_ENC_OBJDATA : CRYPT_IATTRIBUTE_ENC_CERT;
	RESOURCE_DATA msgData;
	int status;

	UNUSED( protocolInfo );

	/* Find out how big the payload will be.  Since revocation requests are
	   unsigned entities we have to vary the attribute type we're reading
	   based on whether we're submitting a signed or unsigned object in the
	   request */
	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( sessionInfoPtr->iCertRequest,
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
							  attrType );
	if( cryptStatusError( status ) )
		return( status );

⌨️ 快捷键说明

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