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

📄 lib_sign.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		}
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( sigCheckKey, RESOURCE_MESSAGE_GETDEPENDENT,
								  &sigCheckContext, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );

	/* Try and determine the length of the signature data.  This should be 
	   specified as a user parameter, unfortunately the early cryptlib API 
	   didn't take length parameters when it wasn't absolutely necessary so
	   we have to take a guess at a safe size limit and hope that the data
	   isn't all done with an indefinite encoding */
	signatureLength = getObjectLength( signature, 512 );
	if( cryptStatusError( signatureLength ) )
		return( CRYPT_ERROR_PARAM1 );

	/* Call the low-level signature check function to check the signature */
	status = checkSignature( signature, signatureLength, sigCheckContext, 
							 hashContext, SIGNATURE_CRYPTLIB );
	if( cryptArgError( status ) )
		/* If we get an argument error from the mechanism-level code, map the
		   mechanism parameter number to the function argument number */
		status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
				 CRYPT_ERROR_PARAM3 : CRYPT_ERROR_PARAM2;
	return( status );
	}

/****************************************************************************
*																			*
*							Extended Create/Check a Signature 				*
*																			*
****************************************************************************/

/* The maximum size for the encoded CMS signed attributes */

#define ENCODED_ATTRIBUTE_SIZE	512

/* Create a CMS signature */

static int createSignedAttributes( CRYPT_CONTEXT iAttributeHash,
								   BYTE *encodedAttributes,
								   int *encodedAttributeSize,
								   const CRYPT_CERTIFICATE iCmsAttributes,
								   const CRYPT_CONTEXT iMessageHash,
								   const BOOLEAN lengthCheckOnly )
	{
	RESOURCE_DATA msgData;
	BYTE temp, hash[ CRYPT_MAX_HASHSIZE ];
	int status;

	/* Extract the message hash information and add it as a messageDigest 
	   attribute, replacing any existing value if necessary.  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 */
	krnlSendMessage( iCmsAttributes, RESOURCE_IMESSAGE_DELETEATTRIBUTE,
					 NULL, CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
	setResourceData( &msgData, hash, CRYPT_MAX_HASHSIZE );
	if( lengthCheckOnly )
		status = krnlSendMessage( iMessageHash, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE,
								  &msgData.length, CRYPT_CTXINFO_BLOCKSIZE );
	else
		status = krnlSendMessage( iMessageHash, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCmsAttributes, 
								  RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
								  CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
	if( cryptStatusError( status ) )
		return( status );

	/* Export the attributes into an encoded signedAttributes data block,
	   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 */
	if( lengthCheckOnly )
		{
		setResourceData( &msgData, NULL, 0 );
		}
	else
		setResourceData( &msgData, encodedAttributes, ENCODED_ATTRIBUTE_SIZE );
	status = krnlSendMessage( iCmsAttributes, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_ENC_OBJDATA );
	if( cryptStatusError( status ) )
		return( status );
	*encodedAttributeSize = msgData.length;
	temp = encodedAttributes[ 0 ];
	encodedAttributes[ 0 ] = BER_SET;
	krnlSendMessage( iAttributeHash, RESOURCE_IMESSAGE_CTX_HASH, 
					 encodedAttributes, *encodedAttributeSize );
	status = krnlSendMessage( iAttributeHash, RESOURCE_IMESSAGE_CTX_HASH, 
							  "", 0 );
	encodedAttributes[ 0 ] = temp;

	return( status );
	}

static int createSignatureCMS( void *signature, int *signatureLength,
							   const CRYPT_CONTEXT signContext,
							   const CRYPT_CONTEXT iHashContext,
							   const CRYPT_CERTIFICATE extraData,
							   const CRYPT_SESSION iTspSession )
	{
	CRYPT_CONTEXT iCmsHashContext = iHashContext;
	CRYPT_CERTIFICATE iCmsAttributes = extraData, iSigningCert;
	CRYPT_ALGO hashAlgo;
	STREAM stream;
	BYTE encodedAttributes[ ENCODED_ATTRIBUTE_SIZE ];
	BYTE dataSignature[ CRYPT_MAX_PKCSIZE ];
	const BOOLEAN lengthOnly = ( signature == NULL ) ? TRUE : FALSE;
	int encodedAttributeSize, dataSignatureSize, length, status;

	/* Get the message hash algo and signing cert */
	status = krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( signContext, RESOURCE_IMESSAGE_GETDEPENDENT, 
								  &iSigningCert, OBJECT_TYPE_CERTIFICATE );
	else
		if( status == CRYPT_ARGERROR_OBJECT )
			/* Remap the error code to refer to the correct parameter */
			status = CRYPT_ARGERROR_NUM1;
	if( cryptStatusError( status ) )
		return( status );

	/* If we're using signed attributes, set them up to be added to the 
	   signature info */
	if( extraData != CRYPT_UNUSED )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		if( extraData == CRYPT_USE_DEFAULT )
			{
			/* If there are no attributes included as extra data, generate 
			   them ourselves */
			setMessageCreateObjectInfo( &createInfo, 
										CRYPT_CERTTYPE_CMS_ATTRIBUTES );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
									  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
									  &createInfo, OBJECT_TYPE_CERTIFICATE );
			if( cryptStatusError( status ) )
				return( status );
			iCmsAttributes = createInfo.cryptHandle;
			}

		/* Generate the signed attributes and hash them into the CMS hash
		   context */
		setMessageCreateObjectInfo( &createInfo, hashAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			{
			if( extraData == CRYPT_USE_DEFAULT )
				krnlSendNotifier( iCmsAttributes, 
								  RESOURCE_IMESSAGE_DECREFCOUNT );
			return( status );
			}
		status = createSignedAttributes( createInfo.cryptHandle, 
								encodedAttributes, &encodedAttributeSize,
								iCmsAttributes, iHashContext, lengthOnly );
		if( extraData == CRYPT_USE_DEFAULT )
			krnlSendNotifier( iCmsAttributes, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			return( status );
			}
		iCmsHashContext = createInfo.cryptHandle;
		}
	else
		/* No signed attributes present */
		encodedAttributeSize = 0;

	/* Create the signature */
	status = createSignature( lengthOnly ? NULL : dataSignature,
							  &dataSignatureSize, signContext, 
							  iCmsHashContext, SIGNATURE_CMS );
	if( iCmsHashContext != iHashContext )
		krnlSendNotifier( iCmsHashContext, RESOURCE_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 )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;
		STREAM stream;
		BYTE headerBuffer[ 8 ];
		int headerLength;

		/* Create the OCTET STRING wrapper for the signature */
		sMemOpen( &stream, headerBuffer, 8 );
		writeTag( &stream, BER_OCTETSTRING );
		writeLength( &stream, dataSignatureSize );
		headerLength = stell( &stream );
		sMemDisconnect( &stream );

		/* Hash the signature value to create the hash value to 
		   countersign and send the result to the TSA */
		setMessageCreateObjectInfo( &createInfo, hashAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_CTX_HASH, 
						 headerBuffer, headerLength );
		krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_CTX_HASH, 
						 dataSignature, dataSignatureSize );
		status = krnlSendMessage( createInfo.cryptHandle, 
								  RESOURCE_IMESSAGE_CTX_HASH, "", 0 );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( iTspSession, 
									  RESOURCE_IMESSAGE_SETATTRIBUTE, 
									  &createInfo.cryptHandle,
									  CRYPT_SESSINFO_TSP_MSGIMPRINT );
		krnlSendNotifier( createInfo.cryptHandle, 
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( iTspSession, 
									  RESOURCE_IMESSAGE_SETATTRIBUTE, 
									  MESSAGE_VALUE_TRUE,
									  CRYPT_SESSINFO_ACTIVE );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Write the signerInfo record */
	sMemOpen( &stream, signature, lengthOnly ? 0 : STREAMSIZE_UNKNOWN );
	status = writeSignerInfo( &stream, iSigningCert, hashAlgo, 
							  encodedAttributes, encodedAttributeSize,
							  dataSignature, dataSignatureSize, 
							  lengthOnly ? CRYPT_UNUSED : iTspSession );
	length = stell( &stream );
	sMemDisconnect( &stream );
	if( iTspSession != CRYPT_UNUSED && lengthOnly )
		/* If we're countersigning the signature with a timestamp, inflate
		   the total size to the nearest multiple of MIN_BUFFER_SIZE, the 
		   envelope auxData buffer size (that is, 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 which 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 */
		length = roundUp( length, MIN_BUFFER_SIZE ) + MIN_BUFFER_SIZE;
	if( !cryptStatusError( status ) )
		*signatureLength = length;

	return( status );
	}

/* Check a CMS signature */

static int checkSignatureCMS( const void *signature, const int signatureLength,
							  const CRYPT_CONTEXT sigCheckContext,
							  const CRYPT_CONTEXT iHashContext, 
							  CRYPT_CERTIFICATE *iExtraData,
							  const CRYPT_HANDLE iSigCheckKey )
	{
	CRYPT_CONTEXT iCmsHashContext = iHashContext;
	CRYPT_ALGO hashAlgo;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	QUERY_INFO queryInfo;
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE hashValue[ CRYPT_MAX_HASHSIZE ];
	int status;

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

	/* Get the message hash algo */
	status = krnlSendMessage( iHashContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		/* Remap the error code to refer to the correct parameter if 
		   necessary */
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : 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 = queryObject( &stream, &queryInfo );
	if( queryInfo.formatType != CRYPT_FORMAT_CMS )
		status = CRYPT_ERROR_BADDATA;
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	setResourceData( &msgData, queryInfo.iAndSStart, queryInfo.iAndSLength );
	if( krnlSendMessage( iSigCheckKey, RESOURCE_IMESSAGE_COMPARE, &msgData, 
						 RESOURCE_MESSAGE_COMPARE_ISSUERANDSERIALNUMBER ) != CRYPT_OK )
		return( CRYPT_ERROR_WRONGKEY );
	if( queryInfo.hashAlgo != hashAlgo )
		return( CRYPT_ARGERROR_NUM1 );

	/* If there are signedAttributes present, hash the data, substituting a 
	   SET OF tag for the IMPLICIT [ 0 ] tag at the start */
	if( queryInfo.attributeStart != NULL )
		{
		static const BYTE setTag[] = { BER_SET };
		MESSAGE_CREATEOBJECT_INFO createInfo;

		setMessageCreateObjectInfo( &createInfo, queryInfo.hashAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_CTX_HASH, 
						 ( BYTE * ) setTag, sizeof( BYTE ) );

⌨️ 快捷键说明

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