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

📄 sign.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
	  header and trailer around it */
	sMemOpen( &stream, signature, 
			  1 + pgpSizeofLength( extraDataLength + 2 + \
								   signatureDataLength ) + \
			  extraDataLength + 2 + signatureDataLength );
	pgpWritePacketHeader( &stream, PGP_PACKET_SIGNATURE, 
						  extraDataLength + 2 + signatureDataLength );
	swrite( &stream, extraData, extraDataLength );
	swrite( &stream, hash, 2 );			/* Hash check */
	status = swrite( &stream, signatureData, signatureDataLength );
	if( cryptStatusOK( status ) )
		*signatureLength = stell( &stream );
	sMemDisconnect( &stream );
	zeroise( extraDataPtr, extraDataLength );
	zeroise( signatureData, CRYPT_MAX_PKCSIZE + 128 );
	if( extraDataPtr != extraData )
		clFree( "createSignaturePGP", extraDataPtr );

	return( status );
	}

/* Check a PGP signature */

static int checkSignaturePGP( const void *signature, const int signatureLength,
							  const CRYPT_CONTEXT sigCheckContext,
							  const CRYPT_CONTEXT iHashContext )
	{
	QUERY_INFO queryInfo;
	STREAM stream;
	int status;

	/* Determine whether there are any authenticated attributes attached to 
	   the signature */
	memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
	sMemConnect( &stream, signature, signatureLength );
	status = sigReadTable[ SIGNATURE_PGP ]( &stream, &queryInfo );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		{
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		return( status );
		}

	/* After hashing the content, PGP also hashes in extra authenticated
	   attributes */
	status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, 
							  queryInfo.attributeStart, 
							  queryInfo.attributeLength );
	if( cryptStatusOK( status ) && queryInfo.attributeLength != 5 )
		{
		BYTE buffer[ 8 ], *bufPtr = buffer + 2;

		/* In addition to the standard authenticated attributes, OpenPGP
		   hashes in even more stuff at the end */
		buffer[ 0 ] = 0x04;
		buffer[ 1 ] = 0xFF;
		mputLong( bufPtr, queryInfo.attributeLength );
		status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, 
								  buffer, 6 );
		}
	zeroise( &queryInfo, sizeof( QUERY_INFO ) );
	if( cryptStatusOK( status ) )
		krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
	if( cryptStatusError( status ) )
		return( status );

	/* Check the signature */
	return( checkSignature( signature, signatureLength, sigCheckContext, 
							iHashContext, SIGNATURE_PGP ) );
	}
#endif /* USE_PGP */

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

/* Create/check an extended signature type */

C_RET cryptCreateSignatureEx( C_OUT void C_PTR signature, 
							  C_OUT int C_PTR signatureLength,
							  C_IN CRYPT_FORMAT_TYPE formatType,
							  C_IN CRYPT_CONTEXT signContext,
							  C_IN CRYPT_CONTEXT hashContext,
							  C_IN CRYPT_HANDLE extraData )
	{
	BOOLEAN isCertChain = FALSE;
	int certType, status;

	/* Perform basic error checking */
	if( signature != NULL )
		{
		if( checkBadPtrWrite( signature, MIN_CRYPT_OBJECTSIZE ) )
			return( CRYPT_ERROR_PARAM1 );
		memset( signature, 0, MIN_CRYPT_OBJECTSIZE );
		}
	if( checkBadPtrWrite( signatureLength, sizeof( int ) ) )
		return( CRYPT_ERROR_PARAM2 );
	*signatureLength = 0;
	if( formatType <= CRYPT_FORMAT_NONE || \
		formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
		return( CRYPT_ERROR_PARAM3 );
	status = krnlSendMessage( signContext, MESSAGE_CHECK, NULL,
							  MESSAGE_CHECK_PKC_SIGN );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM4 : status );
	if( formatType == CRYPT_FORMAT_CMS || \
		formatType == CRYPT_FORMAT_SMIME )
		{
		}
	status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
							  MESSAGE_CHECK_HASH );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM5 : status );

	/* If the signing context has a cert chain attached, the currently-
	   selected cert may not be the leaf cert.  To ensure that we use the
	   correct cert, we lock the chain (which both protects us from having 
	   the user select a different cert while we're using it, and saves the 
	   selection state for when we later unlock it) and explicitly select 
	   the leaf cert */
	status = krnlSendMessage( signContext, IMESSAGE_GETATTRIBUTE,
							  &certType, CRYPT_CERTINFO_CERTTYPE );
	if( cryptStatusOK( status ) && certType == CRYPT_CERTTYPE_CERTCHAIN )
		{
		status = krnlSendMessage( signContext, IMESSAGE_SETATTRIBUTE,
								  MESSAGE_VALUE_TRUE, 
								  CRYPT_IATTRIBUTE_LOCKED );
		if( cryptStatusError( status ) )
			return( status );
		krnlSendMessage( signContext, IMESSAGE_SETATTRIBUTE,
						 MESSAGE_VALUE_CURSORFIRST,
						 CRYPT_CERTINFO_CURRENT_CERTIFICATE );
		isCertChain = TRUE;
		}

	/* Call the low-level signature create function to create the signature.
	   Unfortunately the early cryptlib API didn't take length parameters 
	   when it wasn't absolutely necessary so we can't specify the maximum
	   data length when generating the signature but have to use
	   STREAMSIZE_UNKNOWN for the output */
	switch( formatType )
		{
		case CRYPT_FORMAT_AUTO:
		case CRYPT_FORMAT_CRYPTLIB:
			/* If it's a cryptlib-format signature, there can't be any extra
			   signing attributes present */
			if( extraData != CRYPT_USE_DEFAULT )
				{
				status = CRYPT_ERROR_PARAM6;
				break;
				}

			status = createSignature( signature, signatureLength, 
									  STREAMSIZE_UNKNOWN, signContext, 
									  hashContext, SIGNATURE_CRYPTLIB );
			break;

		case CRYPT_FORMAT_CMS:
		case CRYPT_FORMAT_SMIME:
			/* Make sure that the signing context has a cert attached to 
			   it */
			status = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,
									  &certType, CRYPT_CERTINFO_CERTTYPE );
			if( cryptStatusError( status ) ||
				( certType != CRYPT_CERTTYPE_CERTIFICATE && \
				  certType != CRYPT_CERTTYPE_CERTCHAIN ) )
				{
				status = CRYPT_ERROR_PARAM4;
				break;
				}

			/* Make sure that the extra data object is in order */
			if( extraData != CRYPT_USE_DEFAULT )
				{
				status = krnlSendMessage( extraData, MESSAGE_GETATTRIBUTE,
										  &certType, CRYPT_CERTINFO_CERTTYPE );
				if( cryptStatusError( status ) || \
					certType != CRYPT_CERTTYPE_CMS_ATTRIBUTES )
					{
					status = CRYPT_ERROR_PARAM6;
					break;
					}
				}

			status = createSignatureCMS( signature, signatureLength, 
										 STREAMSIZE_UNKNOWN, signContext, 
										 hashContext, extraData, 
										 CRYPT_UNUSED, formatType );
			break;

#ifdef USE_PGP
		case CRYPT_FORMAT_PGP:
			status = createSignaturePGP( signature, signatureLength, 
										 STREAMSIZE_UNKNOWN, signContext, 
										 hashContext );
			break;
#endif /* USE_PGP */

		default:
			assert( NOTREACHED );
			status = CRYPT_ERROR_PARAM3;
		}
	if( isCertChain )
		/* We're signing with a cert chain, restore its state and unlock it 
		   to allow others access */
		krnlSendMessage( signContext, IMESSAGE_SETATTRIBUTE, 
						 MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
	if( cryptArgError( status ) )
		/* Remap the error code to refer to the correct parameter */
		status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
				 CRYPT_ERROR_PARAM4 : CRYPT_ERROR_PARAM5;
	return( status );
	}

C_RET cryptCreateSignature( C_OUT void C_PTR signature, 
							C_OUT int C_PTR signatureLength,
							C_IN CRYPT_CONTEXT signContext,
							C_IN CRYPT_CONTEXT hashContext )
	{
	int status;

	status = cryptCreateSignatureEx( signature, signatureLength,
									 CRYPT_FORMAT_CRYPTLIB,
									 signContext, hashContext,
									 CRYPT_USE_DEFAULT );
	if( cryptStatusError( status ) )
		{
		/* Remap parameter errors to the correct position */
		if( status == CRYPT_ERROR_PARAM4 )
			status = CRYPT_ERROR_PARAM3;
		if( status == CRYPT_ERROR_PARAM5 )
			status = CRYPT_ERROR_PARAM4;
		}
	return( status );
	}

static CRYPT_FORMAT_TYPE getFormatType( const void *data )
	{
	STREAM stream;
	const BYTE *dataPtr = data;
#ifdef USE_PGP
	long length;
#endif /* USE_PGP */
	int status;

	/* Figure out what we've got.  A PKCS #7/CMS/SMIME signature begins:
		cryptlibSignature ::= SEQUENCE {
			version		INTEGER (3),
			keyID [ 0 ]	OCTET STRING
	   while a CMS signature begins:
		cmsSignature ::= SEQUENCE {
			version		INTEGER (1),
			digestAlgo	SET OF {
	   which allows us to determine which type of object we have */
	if( *dataPtr == BER_SEQUENCE )
		{
		CRYPT_FORMAT_TYPE formatType = CRYPT_FORMAT_NONE;

		sMemConnect( &stream, data, 16 );
		status = readSequence( &stream, NULL );
		if( cryptStatusOK( status ) )
			{
			long version;

			if( cryptStatusOK( readShortInteger( &stream, &version ) ) )
				formatType = ( version == 1 ) ? CRYPT_FORMAT_CMS : \
							 ( version == 3 ) ? CRYPT_FORMAT_CRYPTLIB : \
							 CRYPT_FORMAT_NONE;
			}
		sMemDisconnect( &stream );

		return( formatType );
		}

#ifdef USE_PGP
	/* It's not ASN.1 data, check for PGP data */
	sMemConnect( &stream, data, 16 );
	status = pgpReadPacketHeader( &stream, NULL, &length );
	if( cryptStatusOK( status ) && length > 30 && length < 8192 )
		{
		sMemDisconnect( &stream );
		return( CRYPT_FORMAT_PGP );
		}
	sMemDisconnect( &stream );
#endif /* USE_PGP */

	return( CRYPT_FORMAT_NONE );
	}

C_RET cryptCheckSignatureEx( C_IN void C_PTR signature,
							 C_IN CRYPT_HANDLE sigCheckKey,
							 C_IN CRYPT_CONTEXT hashContext,
							 C_OUT CRYPT_HANDLE C_PTR extraData )
	{
	CRYPT_FORMAT_TYPE formatType;
	CRYPT_CONTEXT sigCheckContext;
	int signatureLength, status;

	/* Perform basic error checking */
	if( signature != NULL && checkBadPtrRead( signature, MIN_CRYPT_OBJECTSIZE ) )
		return( CRYPT_ERROR_PARAM1 );
	if( ( formatType = getFormatType( signature ) ) == CRYPT_FORMAT_NONE )
		return( CRYPT_ERROR_BADDATA );
	status = krnlSendMessage( sigCheckKey, MESSAGE_GETDEPENDENT,
							  &sigCheckContext, OBJECT_TYPE_CONTEXT );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( sigCheckContext, IMESSAGE_CHECK, 
								  NULL, MESSAGE_CHECK_PKC_SIGCHECK );
	if( cryptStatusOK( status ) )
		{
		status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
								  MESSAGE_CHECK_HASH );
		if( status == CRYPT_ARGERROR_OBJECT )
			status = CRYPT_ERROR_PARAM3;
		}
	else
		if( status == CRYPT_ARGERROR_OBJECT )
			status = CRYPT_ERROR_PARAM2;
	if( cryptStatusError( status ) )
		return( status );
	if( formatType == CRYPT_FORMAT_CMS )
		{
		int certType;

		/* Make sure that the sig check key includes a cert */
		status = krnlSendMessage( sigCheckKey, MESSAGE_GETATTRIBUTE,
								  &certType, CRYPT_CERTINFO_CERTTYPE );
		if( cryptStatusError( status ) ||
			( certType != CRYPT_CERTTYPE_CERTIFICATE && \
			  certType != CRYPT_CERTTYPE_CERTCHAIN ) )
			return( CRYPT_ERROR_PARAM2 );
		}

	/* 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 (this is at least better
	   than when generating the signature, where we're forced to use
	   STREAMSIZE_UNKNOWN for the output) */
#ifdef USE_PGP
	if( formatType == CRYPT_FORMAT_PGP )
		{
		STREAM stream;
		

⌨️ 快捷键说明

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