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

📄 sign.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*							Signature Routines								*
*						Copyright Peter Gutmann 1993-2002					*
*																			*
****************************************************************************/

#include <string.h>
#include <stdlib.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "pgp.h"
  #include "asn1_rw.h"
  #include "asn1s_rw.h"
  #include "misc_rw.h"
  #include "objinfo.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../envelope/pgp.h"
  #include "asn1_rw.h"
  #include "asn1s_rw.h"
  #include "misc_rw.h"
  #include "objinfo.h"
#else
  #include "crypt.h"
  #include "envelope/pgp.h"
  #include "misc/asn1_rw.h"
  #include "misc/asn1s_rw.h"
  #include "misc/misc_rw.h"
  #include "misc/objinfo.h"
#endif /* Compiler-specific includes */

/****************************************************************************
*																			*
*							Low-level Signature Functions 					*
*																			*
****************************************************************************/

/* Generic signature creation and checking functions, called from higher-
   level functions within this module, with two external wrapper points for 
   X.509 and raw signatures */

static int createSignature( void *signature, int *signatureLength,
							const int sigMaxLength, 
							const CRYPT_CONTEXT iSignContext,
							const CRYPT_CONTEXT iHashContext,
							const SIGNATURE_TYPE signatureType )
	{
	CRYPT_ALGO_TYPE signAlgo, hashAlgo;
	MECHANISM_SIGN_INFO mechanismInfo;
	STREAM stream;
	const WRITESIG_FUNCTION writeSigFunction = sigWriteTable[ signatureType ];
	BYTE signatureData[ CRYPT_MAX_PKCSIZE ];
	int length, status;

	assert( signature == NULL || isWritePtr( signature, sigMaxLength ) );

	/* Make sure that the requested signature format is available */
	if( writeSigFunction == NULL )
		return( CRYPT_ERROR_NOTAVAIL );

	/* Extract general information */
	status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE, &signAlgo, 
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : status );
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE, 
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM2 : status );

	/* If we're just doing a length check, write dummy data to a null stream
	   and return its length */
	if( signature == NULL )
		{
 		STREAM nullStream;

		assert( signatureType != SIGNATURE_SSH );

		/* Determine how long the signature will be.  In the case of the DLP-
		   based PKCs written in cryptlib format it's just an estimate since 
		   it can change by up to two bytes depending on whether the 
		   signature values have the high bit set or not, which requires 
		   zero-padding of the ASN.1-encoded integers.  This is rather nasty 
		   because it means we can't tell how large a signature will be 
		   without actually creating it.

		   The 6/10 bytes at the start are for the ASN.1 SEQUENCE and 2 * 
		   INTEGER encoding */
		if( signAlgo == CRYPT_ALGO_DSA )
			length = ( signatureType == SIGNATURE_PGP ) ? \
					 2 * ( 2 + 20 ) : 6 + ( 2 * ( 20 + 1 ) );
		else
			{
			/* Calculate the eventual signature size */
			setMechanismSignInfo( &mechanismInfo, NULL, 0, iHashContext, 
								  iSignContext );
			status = krnlSendMessage( iSignContext, IMESSAGE_DEV_SIGN, 
									  &mechanismInfo, MECHANISM_PKCS1 );
			length = mechanismInfo.signatureLength;
			clearMechanismInfo( &mechanismInfo );
			if( cryptStatusError( status ) )
				/* The mechanism messages place the acted-on object (in this
				   case the hash context) first while the higher-level 
				   functions place the signature context next to the 
				   signature data, in other words before the hash context.
				   Because of this we have to reverse parameter error values
				   when translating from the mechanism to the signature
				   function level */
				return( ( status == CRYPT_ARGERROR_NUM1 ) ? \
							CRYPT_ARGERROR_NUM2 : \
						( status == CRYPT_ARGERROR_NUM2 ) ? \
							CRYPT_ARGERROR_NUM1 : status );
			}

		/* Write the data to a null stream to determine its size */
		sMemOpen( &nullStream, NULL, 0 );
		status = writeSigFunction( &nullStream, iSignContext, hashAlgo, 
								   signAlgo, signatureData, length );
		*signatureLength = stell( &nullStream );
		sMemClose( &nullStream );

		return( status );
		}

	/* DLP signatures are handled somewhat specially */
	if( isDlpAlgo( signAlgo ) )
		{
		DLP_PARAMS dlpParams;
		RESOURCE_DATA msgData;
		BYTE hash[ CRYPT_MAX_HASHSIZE ];

		/* Extract the hash value from the context */
		setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		if( cryptStatusError( status ) )
			return( status );

		/* DSA is only defined for hash algorithms with a block size of 160
		   bits */
		if( msgData.length != 20 )
			return( CRYPT_ARGERROR_NUM1 );

		/* Sign the data */
		setDLPParams( &dlpParams, hash, 20, signatureData, CRYPT_MAX_PKCSIZE );
		if( signatureType == SIGNATURE_PGP )
			dlpParams.formatType = CRYPT_FORMAT_PGP;			
		if( signatureType == SIGNATURE_SSH )
			dlpParams.formatType = CRYPT_IFORMAT_SSH;			
		status = krnlSendMessage( iSignContext, IMESSAGE_CTX_SIGN, &dlpParams, 
								  sizeof( DLP_PARAMS ) );
		length = dlpParams.outLen;
		}
	else
		{
		setMechanismSignInfo( &mechanismInfo, signatureData, CRYPT_MAX_PKCSIZE,
							  iHashContext, iSignContext );
		status = krnlSendMessage( iSignContext, IMESSAGE_DEV_SIGN, 
								  &mechanismInfo, MECHANISM_PKCS1 );
		if( cryptStatusError( status ) )
			/* The mechanism messages place the acted-on object (in this case 
			   the hash context) first while the higher-level functions place 
			   the signature context next to the signature data, in other 
			   words before the hash context.  Because of this we have to 
			   reverse parameter error values when translating from the 
			   mechanism to the signature function level */
			status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
						CRYPT_ARGERROR_NUM2 : \
					 ( status == CRYPT_ARGERROR_NUM2 ) ? \
						CRYPT_ARGERROR_NUM1 : status;
		else
			length = mechanismInfo.signatureLength;
		clearMechanismInfo( &mechanismInfo );
		}
	if( cryptStatusError( status ) )
		{
		zeroise( signatureData, CRYPT_MAX_PKCSIZE );
		return( status );
		}

	/* Write the signature record to the output */
	sMemOpen( &stream, signature, sigMaxLength );
	status = writeSigFunction( &stream, iSignContext, hashAlgo, signAlgo, 
							   signatureData, length );
	if( cryptStatusOK( status ) )
		*signatureLength = stell( &stream );
	sMemDisconnect( &stream );

	/* Clean up */
	zeroise( signatureData, CRYPT_MAX_PKCSIZE );
	return( status );
	}

static int checkSignature( const void *signature, const int signatureLength,
						   const CRYPT_CONTEXT iSigCheckContext,
						   const CRYPT_CONTEXT iHashContext,
						   const SIGNATURE_TYPE signatureType )
	{
	CRYPT_ALGO_TYPE signAlgo, hashAlgo;
	MECHANISM_SIGN_INFO mechanismInfo;
	const READSIG_FUNCTION readSigFunction = sigReadTable[ signatureType ];
	QUERY_INFO queryInfo;
	STREAM stream;
	void *signatureData;
	int signatureDataLength, status;

	/* Make sure that the requested signature format is available */
	if( readSigFunction == NULL )
		return( CRYPT_ERROR_NOTAVAIL );

	/* Extract general information */
	status = krnlSendMessage( iSigCheckContext, IMESSAGE_GETATTRIBUTE,
							  &signAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM1 : status );
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE, 
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ARGERROR_NUM2 : status );

	/* Read the signature record up to the start of the signature itself */
	memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
	sMemConnect( &stream, signature, signatureLength );
	status = readSigFunction( &stream, &queryInfo );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		{
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		return( status );
		}

	/* Make sure that we've been given the correct algorithms.  Raw 
	   signatures specify the algorithm information elsewhere, so the check 
	   is done elsewhere when we process the signature data */
	if( signatureType != SIGNATURE_RAW )
		{
		if( signAlgo != queryInfo.cryptAlgo )
			status = CRYPT_ERROR_SIGNATURE;
		if( signatureType != SIGNATURE_SSH && \
			hashAlgo != queryInfo.hashAlgo )
			status = CRYPT_ERROR_SIGNATURE;
		if( cryptStatusError( status ) )
			{
			zeroise( &queryInfo, sizeof( QUERY_INFO ) );
			return( status );
			}
		}

	/* Make sure that we've been given the correct key if the signature 
	   format supports this type of check.  SIGNATURE_CMS supports a check 
	   with MESSAGE_COMPARE_ISSUERANDSERIALNUMBER but this has already been 
	   done while procesing the other CMS data before we were called so we 
	   don't need to do it again */
	if( signatureType == SIGNATURE_CRYPTLIB )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, queryInfo.keyID, queryInfo.keyIDlength );
		status = krnlSendMessage( iSigCheckContext, IMESSAGE_COMPARE, 
								  &msgData, MESSAGE_COMPARE_KEYID );
		if( cryptStatusError( status ) )
			{
			/* A failed comparison is reported as a generic CRYPT_ERROR,
			   convert it into a wrong-key error if necessary */
			zeroise( &queryInfo, sizeof( QUERY_INFO ) );
			return( ( status == CRYPT_ERROR ) ? \
					CRYPT_ERROR_WRONGKEY : status );
			}
		}
	if( signatureType == SIGNATURE_PGP )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, queryInfo.keyID, queryInfo.keyIDlength );
		status = krnlSendMessage( iSigCheckContext, IMESSAGE_COMPARE, 
								  &msgData, 
								  ( queryInfo.version == PGP_VERSION_2 ) ? \
									MESSAGE_COMPARE_KEYID_PGP : \
									MESSAGE_COMPARE_KEYID_OPENPGP );
		if( cryptStatusError( status ) )
			{
			/* A failed comparison is reported as a generic CRYPT_ERROR,
			   convert it into a wrong-key error if necessary */
			zeroise( &queryInfo, sizeof( QUERY_INFO ) );
			return( ( status == CRYPT_ERROR ) ? \
					CRYPT_ERROR_WRONGKEY : status );
			}
		}
	signatureData = queryInfo.dataStart;
	signatureDataLength = queryInfo.dataLength;
	zeroise( &queryInfo, sizeof( QUERY_INFO ) );

	/* DLP signatures are handled somewhat specially */
	if( isDlpAlgo( signAlgo ) )
		{
		DLP_PARAMS dlpParams;
		RESOURCE_DATA msgData;
		BYTE hash[ CRYPT_MAX_HASHSIZE ];

		/* Extract the hash value from the context */
		setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		if( cryptStatusError( status ) )
			return( status );

		/* DSA is only defined for hash algorithms with a block size of 160 
		   bits */
		if( msgData.length != 20 )
			return( CRYPT_ARGERROR_NUM1 );

		/* Check the signature validity using the encoded signature data and
		   hash */
		setDLPParams( &dlpParams, hash, 20, NULL, 0 );
		dlpParams.inParam2 = signatureData;
		dlpParams.inLen2 = signatureDataLength;
		if( signatureType == SIGNATURE_PGP )
			dlpParams.formatType = CRYPT_FORMAT_PGP;
		if( signatureType == SIGNATURE_SSH )
			dlpParams.formatType = CRYPT_IFORMAT_SSH;
		status = krnlSendMessage( iSigCheckContext, IMESSAGE_CTX_SIGCHECK,
								  &dlpParams, sizeof( DLP_PARAMS ) );
		}
	else
		{
		setMechanismSignInfo( &mechanismInfo, signatureData, 
							  signatureDataLength, iHashContext, 
							  iSigCheckContext );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_DEV_SIGCHECK, &mechanismInfo, 
								  MECHANISM_PKCS1 );
		if( cryptStatusError( status ) )
			/* The mechanism messages place the acted-on object (in this case 
			   the hash context) first while the higher-level functions place 
			   the signature context next to the signature data, in other 
			   words before the hash context.  Because of this we have to 
			   reverse parameter error values when translating from the 
			   mechanism to the signature function level */
			status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
						CRYPT_ARGERROR_NUM2 : \
					 ( status == CRYPT_ARGERROR_NUM2 ) ? \
						CRYPT_ARGERROR_NUM1 : status;

		clearMechanismInfo( &mechanismInfo );
		}

⌨️ 快捷键说明

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