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

📄 sign_cms.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	BYTE *bufPtr = ( signature == NULL ) ? NULL : buffer;
	const int bufSize = ( signature == NULL ) ? 0 : CRYPT_MAX_PKCSIZE + 128;
	int dataSignatureSize, length = DUMMY_INIT, status;

	assert( ( signature == NULL && sigMaxLength == 0 ) || \
			isReadPtr( signature, sigMaxLength ) );
	assert( isWritePtr( signatureLength, sizeof( int ) ) );

	REQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \
			  ( signature != NULL && \
			    sigMaxLength > MIN_CRYPT_OBJECTSIZE && \
				sigMaxLength < MAX_INTLENGTH ) );
	REQUIRES( isHandleRangeValid( signContext ) );
	REQUIRES( isHandleRangeValid( iHashContext ) );
	REQUIRES( ( extraData == CRYPT_UNUSED ) || \
			  ( extraData == CRYPT_USE_DEFAULT ) || \
			  isHandleRangeValid( extraData ) );
	REQUIRES( ( iTspSession == CRYPT_UNUSED ) || \
			  isHandleRangeValid( iTspSession ) );
	REQUIRES( formatType == CRYPT_FORMAT_CMS || \
			  formatType == CRYPT_FORMAT_SMIME );

	/* Clear return value */
	*signatureLength = 0;

	initCmsAttributeInfo( &cmsAttributeInfo, formatType, extraData, \
						  iHashContext, signContext, iTspSession );

	/* Get the message hash algo and signing cert */
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );
	status = krnlSendMessage( signContext, IMESSAGE_GETDEPENDENT,
							  &iSigningCert, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );

	/* If we're using signed attributes, set them up to be added to the
	   signature info */
	if( cmsAttributeInfo.iCmsAttributes != CRYPT_UNUSED )
		{
		status = createCmsAttributes( &cmsAttributeInfo, &iCmsHashContext, 
									  hashAlgo, ( signature == NULL ) ? \
									  TRUE : FALSE );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Create the signature */
	status = createSignature( bufPtr, bufSize, &dataSignatureSize, 
							  signContext, iCmsHashContext, CRYPT_UNUSED, 
							  SIGNATURE_CMS );
	if( iCmsHashContext != iHashContext )
		krnlSendNotifier( iCmsHashContext, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		return( status );

	/* If we're countersigning the signature (typically done via a
	   timestamp), create the countersignature */
	if( iTspSession != CRYPT_UNUSED && signature != NULL )
		{
		status = createCmsCountersignature( buffer, dataSignatureSize,
											hashAlgo, iTspSession );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Write the signerInfo record */
	sMemOpenOpt( &stream, signature, ( signature == NULL ) ? 0 : sigMaxLength );
	status = writeCmsSignerInfo( &stream, iSigningCert, hashAlgo,
								 cmsAttributeInfo.encodedAttributes, 
								 cmsAttributeInfo.encodedAttributeSize,
								 buffer, dataSignatureSize,
								 ( signature == NULL ) ? CRYPT_UNUSED : iTspSession );
	if( cryptStatusOK( status ) )
		length = stell( &stream );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	if( iTspSession != CRYPT_UNUSED && signature == NULL )
		{
		/* If we're countersigning the signature with a timestamp and doing
		   a length check only, inflate the total size to the nearest
		   multiple of the envelope parameter MIN_BUFFER_SIZE, which is the
		   size of the envelope's auxData buffer used to contain the
		   signature.  In other words we're always going to trigger an
		   increase in the auxBuffer size because its initial size is
		   MIN_BUFFER_SIZE, so when we grow it we grow it to a nice round
		   value rather than just ( length + MIN_BUFFER_SIZE ).  The actual
		   size increase is just a guess since we can't really be sure how
		   much bigger it'll get without contacting the TSA, however this
		   should be big enough to hold a simple SignedData value without
		   attached certs.  If a TSA gets the implementation wrong and
		   returns a timestamp with an attached cert chain and the chain is
		   too large the worst that'll happen is that we'll get a
		   CRYPT_ERROR_OVERFLOW when we try and read the TSA data from the
		   session object.  Note that this behaviour is envelope-specific
		   and assumes that we're being called from the enveloping code, 
		   this is curently the only location from which we can be called 
		   because a timestamp only makes sense as a countersignature on CMS 
		   data.  It's somewhat ugly because it asumes internal knowledge
		   of the envelope abstraction but there isn't really any clean way
		   to handle this because we can't tell in advance how much data the
		   TSA will send us */
		if( MIN_BUFFER_SIZE - length <= 1024 )
			length = roundUp( length, MIN_BUFFER_SIZE ) + MIN_BUFFER_SIZE;
		else
			{
			/* It should fit in the buffer, don't bother expanding it */
			length = 1024;
			}
		}
	*signatureLength = length;

	return( CRYPT_OK );
	}

/* Check a CMS signature */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int checkSignatureCMS( IN_BUFFER( signatureLength ) const void *signature, 
					   IN_LENGTH_SHORT const int signatureLength,
					   IN_HANDLE const CRYPT_CONTEXT sigCheckContext,
					   IN_HANDLE const CRYPT_CONTEXT iHashContext,
					   OUT_OPT_HANDLE_OPT CRYPT_CERTIFICATE *iExtraData,
					   IN_HANDLE const CRYPT_HANDLE iSigCheckKey )
	{
	CRYPT_CERTIFICATE iLocalExtraData;
	CRYPT_CONTEXT iCmsHashContext = iHashContext;
	CRYPT_ALGO_TYPE hashAlgo;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	QUERY_INFO queryInfo;
	MESSAGE_DATA msgData;
	STREAM stream;
	static const BYTE setTag[] = { BER_SET };
	BYTE hashValue[ CRYPT_MAX_HASHSIZE + 8 ];
	int status;

	assert( isReadPtr( signature, signatureLength ) );
	assert( ( iExtraData == NULL ) || \
			isWritePtr( iExtraData, sizeof( CRYPT_CERTIFICATE ) ) );

	REQUIRES( signatureLength > 40 && signatureLength < MAX_INTLENGTH );
	REQUIRES( isHandleRangeValid( sigCheckContext ) );
	REQUIRES( isHandleRangeValid( iHashContext ) );
	REQUIRES( isHandleRangeValid( iSigCheckKey ) );

	if( iExtraData != NULL )
		*iExtraData = CRYPT_ERROR;

	/* Get the message hash algo */
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );

	/* Unpack the SignerInfo record and make sure that the supplied key is
	   the correct one for the sig.check and the supplied hash context
	   matches the algorithm used in the signature */
	sMemConnect( &stream, signature, signatureLength );
	status = queryAsn1Object( &stream, &queryInfo );
	if( cryptStatusOK( status ) && \
		( queryInfo.formatType != CRYPT_FORMAT_CMS && \
		  queryInfo.formatType != CRYPT_FORMAT_SMIME ) )
		status = CRYPT_ERROR_BADDATA;
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	REQUIRES( rangeCheck( queryInfo.iAndSStart, queryInfo.iAndSLength,
						  queryInfo.size ) );
	setMessageData( &msgData, \
					( BYTE * ) signature + queryInfo.iAndSStart, \
					queryInfo.iAndSLength );
	status = krnlSendMessage( iSigCheckKey, IMESSAGE_COMPARE, &msgData,
							  MESSAGE_COMPARE_ISSUERANDSERIALNUMBER );
	if( cryptStatusError( status ) )
		{
		/* A failed comparison is reported as a generic CRYPT_ERROR,
		   convert it into a wrong-key error if necessary */
		return( ( status == CRYPT_ERROR ) ? \
				CRYPT_ERROR_WRONGKEY : status );
		}
	if( queryInfo.hashAlgo != hashAlgo )
		return( CRYPT_ARGERROR_NUM2 );

	/* If there are no signed attributes present, just check the signature 
	   and exit */
	if( queryInfo.attributeStart <= 0 )
		{
		return( checkSignature( signature, signatureLength, sigCheckContext,
								iCmsHashContext, CRYPT_UNUSED, 
								SIGNATURE_CMS ) );
		}

	/* There are signedAttributes present, hash the data, substituting a SET 
	   OF tag for the IMPLICIT [ 0 ] tag at the start */
	REQUIRES( rangeCheck( queryInfo.attributeStart, 
						  queryInfo.attributeLength, queryInfo.size ) );
	setMessageCreateObjectInfo( &createInfo, queryInfo.hashAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	iCmsHashContext = createInfo.cryptHandle;
	status = krnlSendMessage( iCmsHashContext, IMESSAGE_CTX_HASH,
							  ( BYTE * ) setTag, sizeof( BYTE ) );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCmsHashContext, IMESSAGE_CTX_HASH,
						( BYTE * ) signature + queryInfo.attributeStart + 1,
						queryInfo.attributeLength - 1 );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCmsHashContext, IMESSAGE_CTX_HASH, "", 0 );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCmsHashContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Check the signature */
	status = checkSignature( signature, signatureLength, sigCheckContext,
							 iCmsHashContext, CRYPT_UNUSED, SIGNATURE_CMS );
	krnlSendNotifier( iCmsHashContext, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		return( status );

	/* Import the attributes and make sure that the data hash value given in
	   the signed attributes matches the user-supplied hash */
	REQUIRES( rangeCheck( queryInfo.attributeStart, 
						  queryInfo.attributeLength, queryInfo.size ) );
	setMessageCreateObjectIndirectInfo( &createInfo,
						( BYTE * ) signature + queryInfo.attributeStart,
						queryInfo.attributeLength,
						CRYPT_CERTTYPE_CMS_ATTRIBUTES );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
							  &createInfo, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( status );
	iLocalExtraData = createInfo.cryptHandle;
	setMessageData( &msgData, hashValue, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( iLocalExtraData, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( iHashContext, IMESSAGE_COMPARE, &msgData,
								  MESSAGE_COMPARE_HASH );
		if( cryptStatusError( status ) )
			status = CRYPT_ERROR_SIGNATURE;
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iLocalExtraData, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* If the user wants to look at the authenticated attributes, make them
	   externally visible, otherwise delete them */
	if( iExtraData != NULL )
		*iExtraData = iLocalExtraData;
	else
		krnlSendNotifier( iLocalExtraData, IMESSAGE_DECREFCOUNT );

	return( CRYPT_OK );
	}

⌨️ 快捷键说明

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