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

📄 sign_pgp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*							PGP Signature Routines							*
*						Copyright Peter Gutmann 1993-2007					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "crypt.h"
  #include "mech.h"
  #include "pgp_rw.h"
#else
  #include "crypt.h"
  #include "mechs/mech.h"
  #include "misc/pgp_rw.h"
#endif /* Compiler-specific includes */

#ifdef USE_PGP

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Write a PGP signature packet header:

		-- Start of hashed data --
		byte	version = 4
		byte	sigType
		byte	sigAlgo
		byte	hashAlgo
		uint16	length of auth.attributes
		byte[]	authenticated attributes
		-- End of hashed data --
		uint16	length of unauth.attributes = 0
	  [	byte[2]	hash check ]
	  [	mpi(s)	signature  ]

   See the comment in createSignaturePGP() for the use of this function */

CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
static int writePgpSigPacketHeader( OUT_BUFFER_OPT( dataMaxLen, *dataLen ) \
										void *data, 
									IN_LENGTH_SHORT_Z const int dataMaxLen,
									OUT_LENGTH_SHORT_Z int *dataLen,
									IN_HANDLE const CRYPT_CONTEXT iSignContext,
									IN_HANDLE const CRYPT_CONTEXT iHashContext,
									IN_LENGTH_SHORT_Z const int iAndSlength )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	STREAM stream;
	MESSAGE_DATA msgData;
	BYTE keyID[ PGP_KEYID_SIZE + 8 ];
	BYTE iAndSHeader[ 64 + 8 ];
	const time_t currentTime = getApproxTime();
	int pgpHashAlgo, pgpSignAlgo, iAndSHeaderLength = 0, length, status;

	assert( ( data == NULL && dataMaxLen == 0 ) || \
			isWritePtr( data, dataMaxLen ) );
	assert( isWritePtr( dataLen, sizeof( int ) ) );

	REQUIRES( ( data == NULL && dataMaxLen == 0 ) || \
			  ( data != NULL && \
				dataMaxLen > MIN_CRYPT_OBJECTSIZE && \
				dataMaxLen < MAX_INTLENGTH_SHORT ) );
	REQUIRES( isHandleRangeValid( iSignContext ) );
	REQUIRES( isHandleRangeValid( iHashContext ) );
	REQUIRES( iAndSlength >= 0 && iAndSlength < MAX_INTLENGTH_SHORT );

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

	/* Get the signature information */
	status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );
	if( cryptStatusError( cryptlibToPgpAlgo( cryptAlgo, &pgpHashAlgo ) ) )
		return( CRYPT_ARGERROR_NUM2 );
	status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,
							  &cryptAlgo, 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( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );
	if( cryptStatusError( cryptlibToPgpAlgo( cryptAlgo, &pgpSignAlgo ) ) )
		return( CRYPT_ARGERROR_NUM1 );

	/* 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
		uint32		flags = 0
		uint16		typeLength
		uint16		valueLength
		byte[]		type
		byte[]		value */
	if( iAndSlength > 0 )
		{
		STREAM headerStream;

		sMemOpen( &headerStream, iAndSHeader, 64 );
		pgpWriteLength( &headerStream, \
						1 + UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + \
						21 + iAndSlength );
		sputc( &headerStream, PGP_SUBPACKET_TYPEANDVALUE );
		writeUint32( &headerStream, 0 );
		writeUint16( &headerStream, 21 );
		writeUint16( &headerStream, iAndSlength );
		status = swrite( &headerStream, "issuerAndSerialNumber", 21 );
		if( cryptStatusOK( status ) )
			iAndSHeaderLength = stell( &headerStream );
		sMemDisconnect( &headerStream );

		ENSURES( cryptStatusOK( status ) );
		}

	/* Write the general header information */
	sMemOpenOpt( &stream, data, dataMaxLen );
	sputc( &stream, PGP_VERSION_OPENPGP );
	sputc( &stream, PGP_SIG_DATA );
	sputc( &stream, pgpSignAlgo );
	status = sputc( &stream, pgpHashAlgo );
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		return( status );
		}

	/* Write the authenticated attributes:

		uint16		authAttrLength
		byte		subpacketLength = 1 + UINT32_SIZE
		byte		ID = PGP_SUBPACKET_TIME
		uint32		time
		byte		subpacketLength = 1 + PGP_KEYID_SIZE
		byte		ID = PGP_SUBPACKET_KEYID
		byte[8]		signerID
	  [	byte[]		typeAndValue packet for iAndS ]
	
	   The signer ID is optional, but if we omit it GPG fails the signature 
	   check so we always include it */
	length = ( 1 + 1 + UINT32_SIZE ) + ( 1 + 1 + PGP_KEYID_SIZE );
	if( iAndSlength > 0 )
		length += iAndSHeaderLength + iAndSlength;
	writeUint16( &stream, length );
	sputc( &stream, 1 + UINT32_SIZE );		/* Time */
	sputc( &stream, PGP_SUBPACKET_TIME );
	writeUint32Time( &stream, currentTime );
	sputc( &stream, 1 + PGP_KEYID_SIZE );	/* Signer ID */
	sputc( &stream, PGP_SUBPACKET_KEYID );
	status = swrite( &stream, keyID, PGP_KEYID_SIZE );
	if( cryptStatusOK( status ) && iAndSlength > 0 )
		{									/* TypeAndValue */
		status = swrite( &stream, iAndSHeader, iAndSHeaderLength );
		if( cryptStatusOK( status ) )
			{
			status = exportAttributeToStream( &stream, iSignContext,
								CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
			}
		}
	if( cryptStatusError( status ) )
		{
		sMemClose( &stream );
		return( status );
		}

	/* Write the unauthenticated attributes:

		uint16		unauthAttrLength = 0 */
	status = writeUint16( &stream, 0 );
	if( cryptStatusOK( status ) )
		*dataLen = stell( &stream );
	sMemDisconnect( &stream );

	return( status );
	}

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

/* Create a PGP signature */

CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int createSignaturePGP( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \
							void *signature, 
						IN_LENGTH_Z const int sigMaxLength, 
						OUT_LENGTH_Z int *signatureLength, 
						IN_HANDLE const CRYPT_CONTEXT iSignContext,
						IN_HANDLE const CRYPT_CONTEXT iHashContext )
	{
	MESSAGE_DATA msgData;
	STREAM stream;
	BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
	BYTE signatureData[ CRYPT_MAX_PKCSIZE + 128 + 8 ];
	BYTE extraData[ 1024 + 8 ], *extraDataPtr = extraData;
	BYTE extraTrailer[ 8 + 8 ];
	int extraDataLength = 1024, extraTrailerLength = DUMMY_INIT;
	int signatureDataLength, iAndSlength = 0, totalLength = DUMMY_INIT;
	int status;

	assert( ( signature == NULL && sigMaxLength == 0 ) || \
			isWritePtr( signature, sigMaxLength ) );
	assert( isWritePtr( signatureLength, sizeof( int ) ) );

	REQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \
			  ( signature != NULL && \
				sigMaxLength > MIN_CRYPT_OBJECTSIZE && \
				sigMaxLength < MAX_INTLENGTH ) );
	REQUIRES( isHandleRangeValid( iSignContext ) );
	REQUIRES( isHandleRangeValid( iHashContext ) );

	/* Check whether there's an issuerAndSerialNumber present */
	setMessageData( &msgData, NULL, 0 );
	status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
	if( cryptStatusOK( status ) )
		iAndSlength = msgData.length;

	/* If it's a length check only, determine how large the signature data
	   will be and exit */
	if( signature == NULL )

⌨️ 快捷键说明

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