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

📄 sign_cms.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
		{ CRYPT_ALGO_NONE, CRYPT_ATTRIBUTE_NONE },
		};
	int value, i, status;

	REQUIRES_V( isHandleRangeValid( iCmsAttributes ) );

	/* If there are already sMIMECapabilities present don't try and add 
	   anything further */
	status = krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE, 
							  &value, CRYPT_CERTINFO_CMS_SMIMECAPABILITIES );
	if( cryptStatusOK( status ) )
		return;

	/* Add an sMIMECapability for each supported algorithm.  Since these are 
	   no-value attributes it's not worth aborting the signature generation 
	   if the attempt to add them fails so we don't bother checking the
	   return value */
	for( i = 0; smimeCapInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE && \
				i < FAILSAFE_ARRAYSIZE( smimeCapInfo, SMIMECAP_INFO );
		 i++ )
		{
		if( smimeCapInfo[ i ].cryptAlgo )
			{
			( void ) krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
									  MESSAGE_VALUE_UNUSED, 
									  smimeCapInfo[ i ].smimeCapability );
			}
		}
	ENSURES_V( i < FAILSAFE_ARRAYSIZE( smimeCapInfo, SMIMECAP_INFO ) );
	}

/****************************************************************************
*																			*
*							Create CMS Attributes 							*
*																			*
****************************************************************************/

/* Finalise processing of and hash the CMS attributes */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int hashCmsAttributes( INOUT CMS_ATTRIBUTE_INFO *cmsAttributeInfo,
							  IN_HANDLE const CRYPT_CONTEXT iAttributeHash,
							  const BOOLEAN lengthCheckOnly )
	{
	MESSAGE_DATA msgData;
	BYTE temp, hash[ CRYPT_MAX_HASHSIZE + 8 ];
	int status;

	assert( isWritePtr( cmsAttributeInfo, sizeof( CMS_ATTRIBUTE_INFO ) ) );
	assert( isWritePtr( cmsAttributeInfo->encodedAttributes, \
						cmsAttributeInfo->maxEncodedAttributeSize ) );

	REQUIRES( isHandleRangeValid( cmsAttributeInfo->iCmsAttributes ) );
	REQUIRES( isHandleRangeValid( cmsAttributeInfo->iMessageHash ) );
	REQUIRES( isHandleRangeValid( iAttributeHash ) );

	/* Extract the message hash information and add it as a messageDigest
	   attribute, replacing any existing value if necessary (we don't bother
	   checking the return value because the attribute may or may not be 
	   present, and a failure to delete it will be detected immediately
	   afterwards when we try and set it).  If we're doing a call just to 
	   get the length of the exported data we use a dummy hash value since 
	   the hashing may not have completed yet */
	( void ) krnlSendMessage( cmsAttributeInfo->iCmsAttributes, 
							  IMESSAGE_DELETEATTRIBUTE, NULL,
							  CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
	setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
	if( lengthCheckOnly )
		{
		memset( hash, 0, CRYPT_MAX_HASHSIZE );	/* Keep mem.checkers happy */
		status = krnlSendMessage( cmsAttributeInfo->iMessageHash, 
								  IMESSAGE_GETATTRIBUTE, &msgData.length, 
								  CRYPT_CTXINFO_BLOCKSIZE );
		}
	else
		{
		status = krnlSendMessage( cmsAttributeInfo->iMessageHash, 
								  IMESSAGE_GETATTRIBUTE_S, &msgData, 
								  CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( cmsAttributeInfo->iCmsAttributes, 
								  IMESSAGE_SETATTRIBUTE_S, &msgData, 
								  CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* If we're creating the attributes for a real signature rather than 
	   just as part of a size check and there's a reliable time source
	   present, use the time from that instead of the built-in system time.
	   Although this seems like a trivial thing it's likely that the 
	   presence of a high-assurance time source means that the accuracy of
	   timekeeping is considered critical so we fail the signature 
	   generation if we can't set the time from the reliable source */
	if( !lengthCheckOnly )
		{
		const time_t currentTime = \
				getReliableTime( cmsAttributeInfo->iTimeSource );

		if( currentTime > MIN_TIME_VALUE )
			{
			setMessageData( &msgData, ( void * ) &currentTime,
							sizeof( time_t ) );
			( void ) krnlSendMessage( cmsAttributeInfo->iCmsAttributes, 
									  IMESSAGE_DELETEATTRIBUTE, NULL,
									  CRYPT_CERTINFO_CMS_SIGNINGTIME );
			status = krnlSendMessage( cmsAttributeInfo->iCmsAttributes, 
									  IMESSAGE_SETATTRIBUTE_S, &msgData, 
									  CRYPT_CERTINFO_CMS_SIGNINGTIME );
			if( cryptStatusError( status ) )
				return( status );
			}
		}

	/* Export the attributes into an encoded signedAttributes data block */
	if( lengthCheckOnly )
		{ setMessageData( &msgData, NULL, 0 ); }
	else
		{ 
		setMessageData( &msgData, cmsAttributeInfo->encodedAttributes,
						cmsAttributeInfo->maxEncodedAttributeSize );
		}
	status = krnlSendMessage( cmsAttributeInfo->iCmsAttributes, 
							  IMESSAGE_CRT_EXPORT, &msgData,
							  CRYPT_ICERTFORMAT_DATA );
	if( cryptStatusError( status ) )
		return( status );
	cmsAttributeInfo->encodedAttributeSize = msgData.length;

	/* If it's a length check, just generate a dummy hash value and exit */
	if( lengthCheckOnly )
		return( krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, "", 0 ) );

	/* Replace the IMPLICIT [ 0 ] tag at the start with a SET OF tag to 
	   allow the attributes to be hashed, hash them into the attribute hash 
	   context, and replace the original tag */
	temp = cmsAttributeInfo->encodedAttributes[ 0 ];
	cmsAttributeInfo->encodedAttributes[ 0 ] = BER_SET;
	status = krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH,
							  cmsAttributeInfo->encodedAttributes,
							  cmsAttributeInfo->encodedAttributeSize );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, "", 0 );
	cmsAttributeInfo->encodedAttributes[ 0 ] = temp;
	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int createCmsAttributes( INOUT CMS_ATTRIBUTE_INFO *cmsAttributeInfo,
								OUT_HANDLE_OPT CRYPT_CONTEXT *iCmsHashContext,
								IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
								const BOOLEAN lengthCheckOnly )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	BOOLEAN createdLocalAttributes = FALSE, createdHashContext = FALSE;
	int status;

	assert( isWritePtr( cmsAttributeInfo, sizeof( CMS_ATTRIBUTE_INFO ) ) );
	assert( isWritePtr( cmsAttributeInfo->attributeBuffer, \
						cmsAttributeInfo->maxEncodedAttributeSize ) );
	assert( isWritePtr( iCmsHashContext, sizeof( CRYPT_CONTEXT ) ) );

	REQUIRES( cmsAttributeInfo->formatType == CRYPT_FORMAT_CMS || \
			  cmsAttributeInfo->formatType == CRYPT_FORMAT_SMIME );
	REQUIRES( ( cmsAttributeInfo->iCmsAttributes == CRYPT_USE_DEFAULT ) || \
			  isHandleRangeValid( cmsAttributeInfo->iCmsAttributes ) );
	REQUIRES( isHandleRangeValid( cmsAttributeInfo->iMessageHash ) );
	REQUIRES( isHandleRangeValid( cmsAttributeInfo->iTimeSource ) );
	REQUIRES( ( cmsAttributeInfo->iTspSession == CRYPT_UNUSED ) || \
			  isHandleRangeValid( cmsAttributeInfo->iTspSession ) );
	REQUIRES( cmsAttributeInfo->encodedAttributes == NULL && \
			  cmsAttributeInfo->encodedAttributeSize == 0 );
	REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
			  hashAlgo <= CRYPT_ALGO_LAST_HASH );

	/* Clear return value */
	*iCmsHashContext = CRYPT_ERROR;

	/* Set up the attribute buffer */
	cmsAttributeInfo->encodedAttributes = cmsAttributeInfo->attributeBuffer;

	/* If the user hasn't supplied the attributes, generate them ourselves */
	if( cmsAttributeInfo->iCmsAttributes == CRYPT_USE_DEFAULT )
		{
		setMessageCreateObjectInfo( &createInfo,
									CRYPT_CERTTYPE_CMS_ATTRIBUTES );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CERTIFICATE );
		if( cryptStatusError( status ) )
			return( status );
		cmsAttributeInfo->iCmsAttributes = createInfo.cryptHandle;
		createdLocalAttributes = TRUE;
		}

	/* If it's an S/MIME (vs.pure CMS) signature add the sMIMECapabilities 
	   to further bloat things up.  Since these are no-value attributes 
	   it's not worth aborting the signature generation if the attempt to 
	   add them fails so we don't bother checking a return value */
	if( cmsAttributeInfo->formatType == CRYPT_FORMAT_SMIME )
		addSmimeCapabilities( cmsAttributeInfo->iCmsAttributes );

	/* Generate the attributes and hash them into the CMS hash context */
	setMessageCreateObjectInfo( &createInfo, hashAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusOK( status ) )
		{
		createdHashContext = TRUE;
		status = hashCmsAttributes( cmsAttributeInfo, createInfo.cryptHandle, 
									lengthCheckOnly );
		}
	if( createdLocalAttributes )
		{
		krnlSendNotifier( cmsAttributeInfo->iCmsAttributes, 
						  IMESSAGE_DECREFCOUNT );
		cmsAttributeInfo->iCmsAttributes = CRYPT_UNUSED;
		}
	if( cryptStatusError( status ) )
		{
		if( createdHashContext )
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Return the hash of the attributes to the caller */
	*iCmsHashContext = createInfo.cryptHandle;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Create/Check a CMS Signature 					*
*																			*
****************************************************************************/

/* Create a CMS signature.  The extraData parameter contains the information 
   for signed attributes, and can take one of three values:

	Cert.object handle: Signed attributes to use.

	CRYPT_USE_DEFAULT: Generate default signing attributes when we create 
					   the signature.

	CRYPT_UNUSED: Don't use signing attributes */

CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int createSignatureCMS( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \
							void *signature, 
						IN_LENGTH_Z const int sigMaxLength, 
						OUT_LENGTH_Z int *signatureLength,
						IN_HANDLE const CRYPT_CONTEXT signContext,
						IN_HANDLE const CRYPT_CONTEXT iHashContext,
						IN_HANDLE_OPT const CRYPT_CERTIFICATE extraData,
						IN_HANDLE_OPT const CRYPT_SESSION iTspSession,
						IN_ENUM( CRYPT_FORMAT ) \
							const CRYPT_FORMAT_TYPE formatType )
	{
	CRYPT_CONTEXT iCmsHashContext = iHashContext;
	CRYPT_CERTIFICATE iSigningCert;
	CRYPT_ALGO_TYPE hashAlgo;
	STREAM stream;
	CMS_ATTRIBUTE_INFO cmsAttributeInfo;
	BYTE buffer[ CRYPT_MAX_PKCSIZE + 128 + 8 ];

⌨️ 快捷键说明

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