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

📄 sign.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
		BYTE buffer[ 8 ], *bufPtr = buffer + 2;

		/* Hash in even more stuff at the end.  This is a complex jumble of 
		   items  constituting a version number, an 0xFF, and another length.
		   This was motivated by a concern that something that meant one 
		   thing in a version n sig could mean something different when 
		   interpreted as a version n+1 sig.  For this reason a hash-
		   convention version (v4) was added, along with a disambiguator 
		   0xFF that will never be found at that position in older (v3) 
		   hash-convention sigs (the 0x04 is in fact redundant, but may be 
		   needed at some point if the hash convention moves to a v5 
		   format).  The length has something to do with parsing the packet 
		   from the end, so that out-of-band data doesn't  run into payload 
		   data */
		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, CRYPT_UNUSED, SIGNATURE_PGP );
		if( cryptStatusOK( status ) && \
			( 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
	  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, CRYPT_UNUSED, 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_IN int signatureMaxLength,
							  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, value, status;

	/* Perform basic error checking.  We have to use an internal message to
	   check for signing capability because the DLP algorithms have 
	   specialised data-formatting requirements that can't normally be 
	   directly accessed via external messages, and even the non-DLP
	   algorithms may be internal-use-only if there's a cert attached to 
	   the context.  If we're performing a sign operation this is OK since 
	   they're being used from cryptlib-internal routines, but to make sure
	   that the context is OK we first check its external accessibility by
	   performing a dummy attribute read */
	if( signature != NULL )
		{
		if( signatureMaxLength < MIN_CRYPT_OBJECTSIZE )
			return( CRYPT_ERROR_PARAM2 );
		if( !isWritePtr( signature, signatureMaxLength ) )
			return( CRYPT_ERROR_PARAM1 );
		memset( signature, 0, MIN_CRYPT_OBJECTSIZE );
		}
	if( !isWritePtr( signatureLength, sizeof( int ) ) )
		return( CRYPT_ERROR_PARAM3 );
	*signatureLength = 0;
	if( formatType <= CRYPT_FORMAT_NONE || \
		formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
		return( CRYPT_ERROR_PARAM4 );
	status = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE, 
							  &value, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM5 : status );
	status = krnlSendMessage( signContext, IMESSAGE_CHECK, NULL, 
							  MESSAGE_CHECK_PKC_SIGN );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM5 : status );
	status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
							  MESSAGE_CHECK_HASH );
	if( cryptStatusError( status ) )
		return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
				CRYPT_ERROR_PARAM6 : 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 */
	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_PARAM7;
				break;
				}

			status = createSignature( signature, signatureLength, 
									  signatureMaxLength, signContext, 
									  hashContext, CRYPT_UNUSED, 
									  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_PARAM5;
				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_PARAM7;
					break;
					}
				}

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

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

		default:
			assert( NOTREACHED );
			status = CRYPT_ERROR_PARAM4;
		}
	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_PARAM5 : CRYPT_ERROR_PARAM6;
	return( status );
	}

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

	status = cryptCreateSignatureEx( signature, signatureMaxLength,
									 signatureLength, CRYPT_FORMAT_CRYPTLIB,
									 signContext, hashContext,
									 CRYPT_USE_DEFAULT );
	if( cryptStatusError( status ) )
		{
		/* Remap parameter errors to the correct position */
		if( status == CRYPT_ERROR_PARAM5 )
			status = CRYPT_ERROR_PARAM4;
		if( status == CRYPT_ERROR_PARAM6 )
			status = CRYPT_ERROR_PARAM5;
		}
	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 = pgpR

⌨️ 快捷键说明

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