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

📄 sign.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Write the unsigned attributes.  Note that the only unsigned attribute 
	   in use at this time is a (not-quite) countersignature containing a 
	   timestamp, so the following code always assumes that the attribute is 
	   a timestamp.  First, we write the [1] IMPLICT SET OF attribute 
	   wrapper */
	writeConstructed( stream, unsignedAttributeSize, 1 );
	writeSequence( stream, sizeofOID( OID_TSP_TSTOKEN ) + \
						   sizeofObject( timeStampSize ) );
	writeOID( stream, OID_TSP_TSTOKEN );
	writeSet( stream, timeStampSize );

	/* Copy the timestamp data directly into the stream */
	return( exportAttributeToStream( stream, unsignedAttrObject, 
									 CRYPT_IATTRIBUTE_ENC_TIMESTAMP ) );
	}

/* Create CMS signed attributes */

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

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

	/* 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, IMESSAGE_DELETEATTRIBUTE, NULL, 
					 CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
	setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
	if( encodedAttributes == NULL )
		status = krnlSendMessage( iMessageHash, IMESSAGE_GETATTRIBUTE,
								  &msgData.length, CRYPT_CTXINFO_BLOCKSIZE );
	else
		status = krnlSendMessage( iMessageHash, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( 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 */
	if( encodedAttributes != NULL )
		{
		const time_t currentTime = getReliableTime( iTimeSource );

		if( currentTime > MIN_TIME_VALUE )
			{
			setMessageData( &msgData, ( void * ) &currentTime, 
							sizeof( time_t ) );
			krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE_S,
							 &msgData, CRYPT_CERTINFO_CMS_SIGNINGTIME );
			}
		}

	/* 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( encodedAttributes == NULL )
		{ setMessageData( &msgData, NULL, 0 ); }
	else
		setMessageData( &msgData, encodedAttributes, ENCODED_ATTRIBUTE_SIZE );
	status = krnlSendMessage( iCmsAttributes, IMESSAGE_CRT_EXPORT, &msgData, 
							  CRYPT_ICERTFORMAT_DATA );
	if( cryptStatusError( status ) )
		return( status );
	*encodedAttributeSize = msgData.length;
	if( encodedAttributes == NULL )
		/* If it's a length check, just generate a dummy hash value and 
		   exit */
		return( krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, "", 0 ) );
	temp = encodedAttributes[ 0 ];
	encodedAttributes[ 0 ] = BER_SET;
	krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, 
					 encodedAttributes, *encodedAttributeSize );
	status = krnlSendMessage( iAttributeHash, IMESSAGE_CTX_HASH, 
							  "", 0 );
	encodedAttributes[ 0 ] = temp;

	return( status );
	}

/* Create a CMS countersignature */

static int createCmsCountersignature( const void *dataSignature, 
									  const int dataSignatureSize,
									  const CRYPT_ALGO_TYPE hashAlgo,
									  const CRYPT_SESSION iTspSession )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	STREAM stream;
	int length, status;

	/* Hash the signature data to create the hash value to countersign.
	   The CMS spec requires that the signature is calculated on the 
	   contents octets (in other words the V of the TLV) of the signature, 
	   so we have to skip the signature algorithm and OCTET STRING wrapper */
	setMessageCreateObjectInfo( &createInfo, hashAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
#if 1	/* Standard CMS countersignature */
	sMemConnect( &stream, dataSignature, dataSignatureSize );
	readUniversal( &stream );
	status = readOctetStringHole( &stream, &length, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, 
								  sMemBufPtr( &stream ), length );
	sMemDisconnect( &stream );
#else	/* Broken TSP not-quite-countersignature */
	krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, 
					 ( void * ) dataSignature, dataSignatureSize );
#endif /* 1 */
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, 
								  "", 0 );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iTspSession, IMESSAGE_SETATTRIBUTE, 
								  &createInfo.cryptHandle,
								  CRYPT_SESSINFO_TSP_MSGIMPRINT );
	krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
	if( cryptStatusError( status ) )
		return( status );

	/* Send the result to the TSA for countersigning */
	return( krnlSendMessage( iTspSession, IMESSAGE_SETATTRIBUTE, 
							 MESSAGE_VALUE_TRUE, CRYPT_SESSINFO_ACTIVE ) );
	}

/* Create a CMS signature */

static int createSignatureCMS( void *signature, int *signatureLength,
							   const int sigMaxLength,
							   const CRYPT_CONTEXT signContext,
							   const CRYPT_CONTEXT iHashContext,
							   const CRYPT_CERTIFICATE extraData,
							   const CRYPT_SESSION iTspSession,
							   const CRYPT_FORMAT_TYPE formatType )
	{
	CRYPT_CONTEXT iCmsHashContext = iHashContext;
	CRYPT_CERTIFICATE iCmsAttributes = extraData, iSigningCert;
	CRYPT_ALGO_TYPE hashAlgo;
	STREAM stream;
	BYTE encodedAttributes[ ENCODED_ATTRIBUTE_SIZE ];
	BYTE dataSignature[ CRYPT_MAX_PKCSIZE + 128 ];
	int encodedAttributeSize, dataSignatureSize, length, status;

	/* Get the message hash algo and signing cert */
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM2 : status );
	status = krnlSendMessage( signContext, IMESSAGE_GETDEPENDENT, 
							  &iSigningCert, OBJECT_TYPE_CERTIFICATE );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : 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;
		int value;

		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,
									  IMESSAGE_DEV_CREATEOBJECT,
									  &createInfo, OBJECT_TYPE_CERTIFICATE );
			if( cryptStatusError( status ) )
				return( status );
			iCmsAttributes = createInfo.cryptHandle;
			}

		/* If it's an S/MIME (vs.pure CMS) signature, add the 
		   sMIMECapabilities if they're not already present to further bloat 
		   things up */
		if( formatType == CRYPT_FORMAT_SMIME && \
			cryptStatusError( \
				krnlSendMessage( iCmsAttributes, IMESSAGE_GETATTRIBUTE, &value, 
								 CRYPT_CERTINFO_CMS_SMIMECAPABILITIES ) ) )
			{
			krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
					MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_CMS_SMIMECAP_3DES );
			if( algoAvailable( CRYPT_ALGO_CAST ) )
				krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
					MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_CMS_SMIMECAP_CAST128 );
			if( algoAvailable( CRYPT_ALGO_IDEA ) )
				krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
					MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_CMS_SMIMECAP_IDEA );
			if( algoAvailable( CRYPT_ALGO_AES ) )
				krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
					MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_CMS_SMIMECAP_AES );
			if( algoAvailable( CRYPT_ALGO_RC2 ) )
				krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
					MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_CMS_SMIMECAP_RC2 );
			if( algoAvailable( CRYPT_ALGO_SKIPJACK ) )
				krnlSendMessage( iCmsAttributes, IMESSAGE_SETATTRIBUTE, 
					MESSAGE_VALUE_UNUSED, CRYPT_CERTINFO_CMS_SMIMECAP_SKIPJACK );
			}

		/* Generate the signed 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( cryptStatusError( status ) )
			{
			if( extraData == CRYPT_USE_DEFAULT )
				krnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );
			return( status );
			}
		status = createCmsSignedAttributes( createInfo.cryptHandle, 
						( signature == NULL ) ? NULL : encodedAttributes, 
						&encodedAttributeSize, iCmsAttributes, iHashContext,
						signContext );
		if( extraData == CRYPT_USE_DEFAULT )
			krnlSendNotifier( iCmsAttributes, IMESSAGE_DECREFCOUNT );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			return( status );
			}
		iCmsHashContext = createInfo.cryptHandle;
		}
	else
		/* No signed attributes present */
		encodedAttributeSize = 0;

	/* Create the signature */
	status = createSignature( ( signature == NULL ) ? NULL : dataSignature,
							  &dataSignatureSize, CRYPT_MAX_PKCSIZE + 128, 
							  signContext, iCmsHashContext, 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( dataSignature, dataSignatureSize,
											hashAlgo, iTspSession );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Write the signerInfo record */
	sMemOpen( &stream, signature, ( signature == NULL ) ? 0 : sigMaxLength );
	status = writeCmsSignerInfo( &stream, iSigningCert, hashAlgo, 
								 encodedAttributes, encodedAttributeSize,
								 dataSignature, dataSignatureSize, 
								 ( signature == NULL ) ? CRYPT_UNUSED : iTspSession );
	length = stell( &stream );
	sMemDisconnect( &stream );
	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 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 */
		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;
		}
	if( cryptStatusOK( 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_TYPE 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, IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				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( queryInfo.formatType != CRYPT_FORMAT_CMS && \
		queryInfo.formatType != CRYPT_FORMAT_SMIME )
		status = CRYPT_ERROR_BADDATA;
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		return( status );
	setMessageData( &msgData, queryInfo.iAndSStart, queryInfo.iAndSLength );
	status = krnlSendMessage( iSigCheckKey, IMESSAGE_COMPARE, &msgData, 

⌨️ 快捷键说明

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