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

📄 cms_envpre.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						cryptlib CMS Pre-enveloping Routines				*
*					    Copyright Peter Gutmann 1996-2008					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "envelope.h"
  #include "asn1.h"
  #include "asn1_ext.h"
#else
  #include "envelope/envelope.h"
  #include "misc/asn1.h"
  #include "misc/asn1_ext.h"
#endif /* Compiler-specific includes */

#ifdef USE_ENVELOPES

/****************************************************************************
*																			*
*						Encrypted Content Pre-processing					*
*																			*
****************************************************************************/

/* Pre-process information for encrypted enveloping */

CHECK_RETVAL_SPECIAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processKeyexchangeAction( INOUT ENVELOPE_INFO *envelopeInfoPtr,
									 INOUT ACTION_LIST *actionListPtr,
									 IN_HANDLE_OPT \
										const CRYPT_DEVICE iCryptDevice )
	{
	CRYPT_ALGO_TYPE cryptAlgo = DUMMY_INIT;
	int status;
#ifdef USE_KEA
	BYTE originatorDomainParams[ CRYPT_MAX_HASHSIZE + 8 ];
	int originatorDomainParamSize = 0;
#endif /* USE_KEA */

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isWritePtr( actionListPtr, sizeof( ACTION_LIST ) ) );
	
	REQUIRES( actionListPtr != NULL && \
			  ( actionListPtr->action == ACTION_KEYEXCHANGE_PKC || \
				actionListPtr->action == ACTION_KEYEXCHANGE ) );
	REQUIRES( iCryptDevice == CRYPT_UNUSED || \
			  isHandleRangeValid( iCryptDevice ) );

	/* If the session key/MAC context is tied to a device make sure that the 
	   key exchange object is in the same device */
	if( iCryptDevice != CRYPT_UNUSED )
		{
		CRYPT_DEVICE iKeyexDevice;

		status = krnlSendMessage( actionListPtr->iCryptHandle,
								  MESSAGE_GETDEPENDENT, &iKeyexDevice,
								  OBJECT_TYPE_DEVICE );
		if( cryptStatusError( status ) || iCryptDevice != iKeyexDevice )
			{
			setErrorInfo( envelopeInfoPtr, 
						  ( envelopeInfoPtr->usage == ACTION_CRYPT ) ? \
							CRYPT_ENVINFO_SESSIONKEY : CRYPT_ENVINFO_INTEGRITY,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}

#ifdef USE_KEA
	/* If there's an originator chain present get the originator's domain
	   parameters */
	if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
		{
		MESSAGE_DATA msgData;

		setMessageData( &msgData, originatorDomainParams,
						 CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,
								  IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_KEY_KEADOMAINPARAMS );
		if( cryptStatusError( status ) )
			return( status );
		originatorDomainParamSize = msgData.length;
		}

	/* If it's a key agreement action make sure that there's originator info 
	   present and that the domain parameters match */
	if( actionListPtr->action == ACTION_KEYEXCHANGE_PKC && \
		cryptStatusOK( krnlSendMessage( actionListPtr->iCryptHandle,
										IMESSAGE_CHECK, NULL,
										MESSAGE_CHECK_PKC_KA_EXPORT ) ) )
		{
		MESSAGE_DATA msgData;
		BYTE domainParams[ CRYPT_MAX_HASHSIZE + 8 ];

		if( originatorDomainParamSize <= 0 )
			{
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_ORIGINATOR,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}
		setMessageData( &msgData, domainParams, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( actionListPtr->iCryptHandle,
								  IMESSAGE_GETATTRIBUTE_S, &msgData,
								  CRYPT_IATTRIBUTE_KEY_KEADOMAINPARAMS );
		if( cryptStatusError( status ) )
			return( status );
		if( ( originatorDomainParamSize != msgData.length ) || \
			memcmp( originatorDomainParams, domainParams,
					originatorDomainParamSize ) )
			{
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_ORIGINATOR,
						  CRYPT_ERRTYPE_CONSTRAINT );
			return( CRYPT_ERROR_INVALID );
			}
		}
#endif /* USE_KEA */

	/* Remember that we now have a controlling action and connect the
	   controller to the subject */
	REQUIRES( envelopeInfoPtr->actionList != NULL );
	envelopeInfoPtr->actionList->flags &= ~ACTION_NEEDSCONTROLLER;
	actionListPtr->associatedAction = envelopeInfoPtr->actionList;

	/* Evaluate the size of the exported action.  If it's a conventional key
	   exchange we force the use of the CMS format since there's no reason 
	   to use the cryptlib format */
	status = iCryptExportKey( NULL, 0, &actionListPtr->encodedSize, 
						( actionListPtr->action == ACTION_KEYEXCHANGE ) ? \
							CRYPT_FORMAT_CMS : envelopeInfoPtr->type,
						envelopeInfoPtr->actionList->iCryptHandle,
						actionListPtr->iCryptHandle );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( actionListPtr->iCryptHandle,
								  IMESSAGE_GETATTRIBUTE, &cryptAlgo,
								  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );

	/* If there are any key exchange actions that will result in indefinite-
	   length encodings present we can't use a definite-length encoding for 
	   the key exchange actions */
	return( ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? OK_SPECIAL : CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int cmsPreEnvelopeEncrypt( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	CRYPT_DEVICE iCryptDevice = CRYPT_UNUSED;
	ACTION_LIST *actionListPtr;
	BOOLEAN hasIndefSizeActions = FALSE;
	int totalSize, iterationCount, status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( envelopeInfoPtr->usage == ACTION_CRYPT || \
			  envelopeInfoPtr->usage == ACTION_MAC );

#ifdef USE_KEA
	/* If there's originator info present find out what it'll take to encode 
	   it into the envelope header */
	if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
		{
		MESSAGE_DATA msgData;
		int status;

		/* Determine how big the originator certificate chain will be */
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( envelopeInfoPtr->iExtraCertChain,
								  IMESSAGE_CRT_EXPORT, &msgData,
								  CRYPT_ICERTFORMAT_CERTSET );
		if( cryptStatusError( status ) )
			return( status );
		envelopeInfoPtr->extraDataSize = msgData.length;

		/* If we have very long originator certificate chains the auxBuffer 
		   may not be large enough to contain the resulting chain, so we have to
		   expand it to handle the chain */
		if( envelopeInfoPtr->auxBufSize < envelopeInfoPtr->extraDataSize + 64 )
			{
			REQUIRES( envelopeInfoPtr->auxBuffer == NULL );
			if( ( envelopeInfoPtr->auxBuffer = \
					clDynAlloc( "preEnvelopeEncrypt", \
								envelopeInfoPtr->extraDataSize + 64 ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			envelopeInfoPtr->auxBufSize = envelopeInfoPtr->extraDataSize + 64;
			}
		}
#endif /* USE_KEA */

	/* If there are no key exchange actions present we're done */
	if( envelopeInfoPtr->preActionList == NULL )
		return( CRYPT_OK );

	/* Create the session/MAC key if necessary */
	if( envelopeInfoPtr->actionList == NULL )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Make sure that we can still add another action */
		if( !moreActionsPossible( envelopeInfoPtr->actionList ) )
			return( CRYPT_ERROR_OVERFLOW );

		/* Create a default encryption action and add it to the action
		   list */
		setMessageCreateObjectInfo( &createInfo,
							( envelopeInfoPtr->usage == ACTION_CRYPT ) ? \
								envelopeInfoPtr->defaultAlgo : \
								envelopeInfoPtr->defaultMAC );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		status = krnlSendNotifier( createInfo.cryptHandle, 
								   IMESSAGE_CTX_GENKEY );
		if( cryptStatusOK( status ) )
			{
			status = addAction( &envelopeInfoPtr->actionList,
								envelopeInfoPtr->memPoolState,
								envelopeInfoPtr->usage,
								createInfo.cryptHandle );
			}
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			return( status );
			}
		}
	else
		{
		/* If the session key/MAC context is tied to a device get its handle 
		   so that we can check that all key exchange objects are also in the 
		   same device */
		status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle,
								  MESSAGE_GETDEPENDENT, &iCryptDevice,
								  OBJECT_TYPE_DEVICE );
		if( cryptStatusError( status ) )
			iCryptDevice = CRYPT_UNUSED;
		}
	REQUIRES( envelopeInfoPtr->actionList != NULL );

	/* Notify the kernel that the session key/MAC context is attached to the
	   envelope.  This is an internal object used only by the envelope so we 
	   tell the kernel not to increment its reference count when it attaches 
	   it */
	status = krnlSendMessage( envelopeInfoPtr->objectHandle, 
							  IMESSAGE_SETDEPENDENT,
							  &envelopeInfoPtr->actionList->iCryptHandle,
							  SETDEP_OPTION_NOINCREF );
	if( cryptStatusError( status ) )
		return( status );

	/* Now walk down the list of key exchange actions evaluating their size
	   and connecting each one to the session key/MAC action */
	totalSize = 0; 
	for( actionListPtr = envelopeInfoPtr->preActionList, iterationCount = 0;
		 actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED; 
		 actionListPtr = actionListPtr->next, iterationCount++ )
		{
		status = processKeyexchangeAction( envelopeInfoPtr, actionListPtr,
										   iCryptDevice );
		if( cryptStatusError( status ) )
			{
			/* An OK_SPECIAL state means that this keyex action will result 
			   in an indefinite-length encoding */
			if( status != OK_SPECIAL )
				return( status );
			hasIndefSizeActions = TRUE;
			}
		totalSize += actionListPtr->encodedSize;
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
	envelopeInfoPtr->cryptActionSize = hasIndefSizeActions ? \
									   CRYPT_UNUSED : totalSize;
	ENSURES( ( envelopeInfoPtr->cryptActionSize == CRYPT_UNUSED ) || \
			 ( envelopeInfoPtr->cryptActionSize > 0 && \
			   envelopeInfoPtr->cryptActionSize < MAX_INTLENGTH ) );

	/* If we're MACing the data, hashing is now active */
	if( envelopeInfoPtr->usage == ACTION_MAC )
		envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;

⌨️ 快捷键说明

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