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

📄 sign.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
							  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 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 };

		setMessageCreateObjectInfo( &createInfo, queryInfo.hashAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_DEV_CREATEOBJECT,
								  &createInfo, OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, 
						 ( BYTE * ) setTag, sizeof( BYTE ) );
		krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, 
						 ( ( BYTE * ) queryInfo.attributeStart ) + 1, 
						 queryInfo.attributeLength - 1 );
		krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH, 
						 "", 0 );
		iCmsHashContext = createInfo.cryptHandle;
		}

	/* Check the signature */
	status = checkSignature( signature, signatureLength, sigCheckContext, 
							 iCmsHashContext, SIGNATURE_CMS );
	if( queryInfo.attributeStart == NULL )
		/* No signed attributes, we're done */
		return( status );
	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 */
	setMessageCreateObjectIndirectInfo( &createInfo, 
						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 );
	setMessageData( &msgData, hashValue, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, CRYPT_CERTINFO_CMS_MESSAGEDIGEST );
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( iHashContext, IMESSAGE_COMPARE, &msgData, 
								  MESSAGE_COMPARE_HASH );
		if( status == CRYPT_ERROR )
			/* A failed comparison is reported as a generic CRYPT_ERROR,
			   convert it into a signature error if necessary */
			status = CRYPT_ERROR_SIGNATURE;
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( createInfo.cryptHandle, 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 = createInfo.cryptHandle;
	else
		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );

	return( status );
	}

/****************************************************************************
*																			*
*							Create/Check a PGP Signature					*
*																			*
****************************************************************************/

#ifdef USE_PGP

/* Write a PGP signature packet header:
		-- Start of hashed data --
		byte	version = 4
		byte	sigType
		byte	sigAlgo
		byte	hashAlgo
		byte[2]	length of auth.attributes
		byte[]	authenticated attributes
		-- End of hashed data --
		byte[2]	length of unauth.attributes = 0
	  [	byte[2]	hash check ]
	  [	mpi(s)	signature  ]

   PGP processes the authenticated attributes in an odd way, first hashing 
   part of the packet from the version number to the end of the authenticated
   attributes, then some more stuff, and finally signing that.  Because of
   this complex way of handling things, we can't write the signature packet 
   in one go but instead have to write the part that's hashed, hash it, and 
   then go back and reassemble the whole thing from the pre-hashed data and 
   the length, hash check, and signature */

static int writePgpSigPacketHeader( void *dataBuffer, const int dataBufSize,
									const CRYPT_CONTEXT iSignContext, 
									const CRYPT_CONTEXT iHashContext,
									const int iAndSlength )
	{
	CRYPT_ALGO_TYPE hashAlgo, signAlgo;
	STREAM stream;
	RESOURCE_DATA msgData;
	BYTE keyID[ PGP_KEYID_SIZE ];
	BYTE iAndSHeader[ 64 ];
	BYTE buffer[ 8 ], *bufPtr = buffer;
	const time_t currentTime = getApproxTime();
	int length, iAndSHeaderLength = 0, status;

	/* Get the signature information */
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE, 
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM2 : status );
	status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE, 
							  &signAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, keyID, PGP_KEYID_SIZE );
		status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
		}
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : status );

	/* Write the issuerAndSerialNumber packet header if necessary.  Since 
	   this is a variable-length packet we need to pre-encode it before we 
	   can write the main packet data:

		byte[]		length
		byte		subpacketType
		byte[4]		flags = 0
		byte[2]		typeLength
		byte[2]		valueLength
		byte[]		type
		byte[]		value

	   Note that type and value are reversed, this is required by the spec */
	if( iAndSlength > 0 )
		{
		STREAM headerStream;

		sMemOpen( &headerStream, iAndSHeader, 64 );
		pgpWriteLength( &headerStream, 1 + 4 + 2 + 2 + 21 + iAndSlength );
		sputc( &headerStream, PGP_SUBPACKET_TYPEANDVALUE );
		swrite( &headerStream, "\x00\x00\x00\x00", 4 );
		sputc( &headerStream, 0 );
		sputc( &headerStream, 21 );
		sputc( &headerStream, ( iAndSlength >> 8 ) & 0xFF );
		sputc( &headerStream, iAndSlength & 0xFF );
		swrite( &headerStream, "issuerAndSerialNumber", 21 );
		iAndSHeaderLength = stell( &headerStream );
		assert( sStatusOK( &headerStream ) );
		sMemDisconnect( &headerStream );
		}

	/* Write the general header information */
	sMemOpen( &stream, dataBuffer, dataBufSize );
	sputc( &stream, PGP_VERSION_OPENPGP );
	sputc( &stream, PGP_SIG_DATA );
	sputc( &stream, cryptlibToPgpAlgo( signAlgo ) );
	sputc( &stream, cryptlibToPgpAlgo( hashAlgo ) );

	/* Write the authenticated attributes.  The signer ID is optional, but
	   if we omit it GPG fails the signature check so we always include it */
	length = 1 + 1 + 4 + 1 + 1 + PGP_KEYID_SIZE;
	if( iAndSlength )
		length += iAndSHeaderLength + iAndSlength;
	sputc( &stream, ( length >> 8 ) & 0xFF );
	sputc( &stream, length & 0xFF );
	sputc( &stream, 1 + 4 );
	sputc( &stream, PGP_SUBPACKET_TIME );
	mputLong( bufPtr, currentTime );
	swrite( &stream, buffer, 4 );
	sputc( &stream, 1 + PGP_KEYID_SIZE );
	sputc( &stream, PGP_SUBPACKET_KEYID );
	swrite( &stream, keyID, PGP_KEYID_SIZE );
	if( iAndSlength )
		{
		swrite( &stream, iAndSHeader, iAndSHeaderLength );
		if( dataBuffer == NULL )
			{ setMessageData( &msgData, NULL, 0 ); }
		else
			{ setMessageData( &msgData, sMemBufPtr( &stream ), 
							  sMemDataLeft( &stream ) - 2 ); }
		status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, 
								  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		if( cryptStatusError( status ) )
			{
			sMemClose( &stream );
			return( status );
			}
		sSkip( &stream, msgData.length );
		}

	/* Write the unauthenticated attributes */
	sputc( &stream, 0 );
	status = sputc( &stream, 0 );

	/* Clean up */
	length = stell( &stream );
	sMemDisconnect( &stream );
	return( cryptStatusError( status ) ? status : length );
	}

static int createSignaturePGP( void *signature, int *signatureLength,
							   const int sigMaxLength, 
							   const CRYPT_CONTEXT iSignContext,
							   const CRYPT_CONTEXT iHashContext )
	{
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE hash[ CRYPT_MAX_HASHSIZE ], signatureData[ CRYPT_MAX_PKCSIZE + 128 ];
	BYTE extraData[ 1024 ], *extraDataPtr = extraData;
	int extraDataLength = 1024, signatureDataLength, iAndSlength = 0, status;

	/* If it's a length check only, determine how large the signature data
	   will be */
	if( signature == NULL )
		{
		setMessageData( &msgData, NULL, 0 );
		status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, 
								  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
		if( cryptStatusOK( status ) )
			iAndSlength = msgData.length;
		status = extraDataLength = \
			writePgpSigPacketHeader( NULL, 0, iSignContext, iHashContext, 
									 iAndSlength );
		if( !cryptStatusError( status ) )
			status = createSignature( NULL, &signatureDataLength, 0,
									  iSignContext, iHashContext, 
									  SIGNATURE_PGP );
		if( cryptStatusError( status ) )
			return( status );
		*signatureLength = 1 + pgpSizeofLength( extraDataLength + 2 + \
												signatureDataLength ) + \
						   extraDataLength + 2 + signatureDataLength;

		return( CRYPT_OK );
		}

	/* Check whether there's an issuerAndSerialNumber present and allocate a
	   larger buffer for it if necessary.  Note that we can't use a dynBuf 
	   for this because we're allocating a buffer larger than the attribute,
	   not the same size as the attribute */
	setMessageData( &msgData, NULL, 0 );
	status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( cryptStatusOK( status ) )
		{
		if( msgData.length > extraDataLength - 128 )
			{
			extraDataLength = 128 + msgData.length;
			if( ( extraDataPtr = clDynAlloc( "createSignaturePGP", \
											 extraDataLength ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			}
		iAndSlength = msgData.length;
		}

	/* Complete the hashing and create the signature.  In theory this could 
	   get ugly because there could be multiple one-pass signature packets 
	   present, however PGP handles multiple signatures by nesting them so 
	   this isn't a problem.

	   PGP processes the authenticated attributes in an odd way, first 
	   hashing part of the packet from the version number to the end of the 
	   authenticated attributes, then some more stuff, and finally signing 
	   that.  Because of this complex way of handling things, we can't write 
	   the signature packet in one go but instead have to write the part 
	   we can create now, hash the portion that's hashed (all but the last
	   16 bits, the length of the unathenticated attributes), and then go 
	   back and assemble the whole thing including the length and signature 
	   later on from the individual parts */
	status = extraDataLength = \
		writePgpSigPacketHeader( extraData, extraDataLength, iSignContext, 
								 iHashContext, iAndSlength );
	if( !cryptStatusError( status ) )
		{
		status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, 
								  extraData, extraDataLength - 2 );
		if( status == CRYPT_ERROR_COMPLETE )
			/* Unlike standard signatures, PGP requires that the hashing
			   not be wrapped up before the signature is generated, since
			   it needs to hash in further data before it can generate
			   the signature.  Since completing the hashing is likely to be 
			   a common error, we specifically check for this and return an
			   appropriate error code */
			status = CRYPT_ARGERROR_NUM2;
		}
	if( cryptStatusOK( status ) )
		{
		BYTE buffer[ 8 ], *bufPtr = buffer + 2;

		/* Hash in even more stuff at the end */
		buffer[ 0 ] = 0x04;
		buffer[ 1 ] = 0xFF;
		mputLong( bufPtr, extraDataLength - 2 );
		status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, 6 );
		}
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		}
	if( cryptStatusOK( status ) )
		{
		status = createSignature( signatureData, &signatureDataLength, 
								  CRYPT_MAX_PKCSIZE + 128, iSignContext, 
								  iHashContext, SIGNATURE_PGP );
		if( cryptStatusOK( status ) && \
			sigMaxLength != STREAMSIZE_UNKNOWN && \
			( 1 + pgpSizeofLength( extraDataLength + 1024 ) + \
			  extraDataLength + 16 + signatureDataLength ) > sigMaxLength )
			status = CRYPT_ERROR_OVERFLOW;
		}
	if( cryptStatusError( status ) )
		{
		zeroise( extraDataPtr, extraDataLength );
		if( extraDataPtr != extraData )
			clFree( "createSignaturePGP", extraDataPtr );
		return( status );
		}

	/* Write the signature packet:
	  [	signature packet header ]
		byte[2]	hash check
		mpi		signature

	  Since we've already had to write half the packet earlier on in order
	  to hash it, we copy this pre-encoded information across and add the

⌨️ 快捷键说明

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