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

📄 sign_rw.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*						  Signature Read/Write Routines						*
*						Copyright Peter Gutmann 1992-2007					*
*																			*
****************************************************************************/

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

/* Context-specific tags for the SignerInfo record */

enum { CTAG_SI_SKI };

/****************************************************************************
*																			*
*							X.509 Signature Routines						*
*																			*
****************************************************************************/

/* Read/write raw signatures */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readRawSignature( INOUT STREAM *stream, 
							 INOUT QUERY_INFO *queryInfo )
	{
	const int startPos = stell( stream );
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );

	/* Read the start of the signature */
	status = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,
								DEFAULT_TAG );
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->dataStart = stell( stream ) - startPos;

	/* Make sure that the remaining signature data is present */
	return( sSkip( stream, queryInfo->dataLength ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeRawSignature( INOUT STREAM *stream, 
							  STDC_UNUSED const CRYPT_CONTEXT iSignContext,
							  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
							  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
							  IN_BUFFER( signatureLength ) const BYTE *signature,
							  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( signature, signatureLength ) );
			/* Other parameters aren't used for this format */

	REQUIRES( signatureLength >= 40 && \
			  signatureLength < MAX_INTLENGTH_SHORT );

	/* Write the BIT STRING wrapper and signature */
	writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
	return( writeRawObject( stream, signature, signatureLength ) );
	}

/* Read/write X.509 signatures */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readX509Signature( INOUT STREAM *stream, 
							  INOUT QUERY_INFO *queryInfo )
	{
	const int startPos = stell( stream );
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );

	/* Read the signature/hash algorithm information followed by the start
	   of the signature */
	status = readAlgoIDext( stream, &queryInfo->cryptAlgo,
							&queryInfo->hashAlgo );
	if( cryptStatusOK( status ) )
		{
		status = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,
									DEFAULT_TAG );
		}
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->dataStart = stell( stream ) - startPos;

	/* Make sure that the remaining signature data is present */
	return( sSkip( stream, queryInfo->dataLength ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeX509Signature( INOUT STREAM *stream,
							   IN_HANDLE const CRYPT_CONTEXT iSignContext,
							   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
							   STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
							   IN_BUFFER( signatureLength ) const BYTE *signature,
							   IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( signature, signatureLength ) );
			/* Other parameters aren't used for this format */

	REQUIRES( isHandleRangeValid( iSignContext ) );
	REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
			  hashAlgo <= CRYPT_ALGO_LAST_HASH );
	REQUIRES( signatureLength >= 40 && \
			  signatureLength < MAX_INTLENGTH_SHORT );

	/* Write the hash+signature algorithm identifier followed by the BIT
	   STRING wrapper and signature */
	writeContextAlgoID( stream, iSignContext, hashAlgo );
	writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
	return( writeRawObject( stream, signature, signatureLength ) );
	}

/****************************************************************************
*																			*
*							CMS Signature Routines							*
*																			*
****************************************************************************/

/* Read/write PKCS #7/CMS (issuerAndSerialNumber) signatures */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCmsSignature( INOUT STREAM *stream, 
							 INOUT QUERY_INFO *queryInfo )
	{
	const int startPos = stell( stream );
	long value, endPos;
	int length, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );

	status = getStreamObjectLength( stream, &length );
	if( cryptStatusError( status ) )
		return( status );
	endPos = startPos + length;

	/* Read the header */
	readSequence( stream, NULL );
	status = readShortInteger( stream, &value );
	if( cryptStatusError( status ) )
		return( status );
	if( value != SIGNATURE_VERSION )
		return( CRYPT_ERROR_BADDATA );

	/* Read the issuer and serial number and hash algorithm ID.  Since we're 
	   recording the position of the issuerAndSerialNumber as a blob we have 
	   to use getStreamObjectLength() to get the overall blob data size */
	status = getStreamObjectLength( stream, &length );
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->iAndSStart = stell( stream ) - startPos;
	queryInfo->iAndSLength = length;
	sSkip( stream, length );
	status = readAlgoID( stream, &queryInfo->hashAlgo );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the authenticated attributes if there are any present */
	if( peekTag( stream ) == MAKE_CTAG( 0 ) )
		{
		status = getStreamObjectLength( stream, &length );
		if( cryptStatusError( status ) )
			return( status );
		queryInfo->attributeStart = stell( stream ) - startPos;
		queryInfo->attributeLength = length;
		status = sSkip( stream, length );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Read the CMS/cryptlib signature algorithm and the start of the 
	   signature */
	status = readAlgoID( stream, &queryInfo->cryptAlgo );
	if( cryptStatusOK( status ) )
		{
		status = readOctetStringHole( stream, &queryInfo->dataLength, 
									  18 + 18, DEFAULT_TAG );
		}
	if( cryptStatusOK( status ) )
		{
		queryInfo->dataStart = stell( stream ) - startPos;
		status = sSkip( stream, queryInfo->dataLength );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Read the unauthenticated attributes if there are any present */
	if( stell( stream ) < endPos && peekTag( stream ) == MAKE_CTAG( 1 ) )
		{
		status = getStreamObjectLength( stream, &length );
		if( cryptStatusError( status ) )
			return( status );
		queryInfo->unauthAttributeStart = stell( stream ) - startPos;
		queryInfo->unauthAttributeLength = length;
		status = sSkip( stream, length );
		if( cryptStatusError( status ) )
			return( status );
		}

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeCmsSignature( INOUT STREAM *stream,
							  IN_HANDLE const CRYPT_CONTEXT iSignContext,
							  STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
							  STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
							  IN_BUFFER( signatureLength ) const BYTE *signature,
							  IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
	{
	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( signature, signatureLength ) );
			/* Other parameters aren't used for this format */

	REQUIRES( isHandleRangeValid( iSignContext ) );
	REQUIRES( signatureLength >= 40 && \
			  signatureLength < MAX_INTLENGTH_SHORT );

	/* Write the signature algorithm identifier and signature data.  The
	   handling of CMS signatures is non-orthogonal to readCmsSignature()
	   because creating a CMS signature involves adding assorted additional
	   data like iAndS and signed attributes that present too much
	   information to pass into a basic writeSignature() call */
	writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE );
	return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
	}

/* Read/write cryptlib/CMS (keyID) signatures */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCryptlibSignature( INOUT STREAM *stream, 
								  INOUT QUERY_INFO *queryInfo )
	{
	const int startPos = stell( stream );
	long value;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );

	/* Read the header */
	readSequence( stream, NULL );
	status = readShortInteger( stream, &value );
	if( cryptStatusError( status ) )
		return( status );
	if( value != SIGNATURE_EX_VERSION )
		return( CRYPT_ERROR_BADDATA );

	/* Read the key ID and hash algorithm identifier */
	readOctetStringTag( stream, queryInfo->keyID, &queryInfo->keyIDlength,
						8, CRYPT_MAX_HASHSIZE, CTAG_SI_SKI );
	status = readAlgoID( stream, &queryInfo->hashAlgo );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the CMS/cryptlib signature algorithm and the start of the 
	   signature */
	status = readAlgoID( stream, &queryInfo->cryptAlgo );
	if( cryptStatusOK( status ) )
		{
		status = readOctetStringHole( stream, &queryInfo->dataLength, 
									  18 + 18, DEFAULT_TAG );
		}
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->dataStart = stell( stream ) - startPos;

	/* Make sure that the remaining signature data is present */
	return( sSkip( stream, queryInfo->dataLength ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeCryptlibSignature( INOUT STREAM *stream,
								   IN_HANDLE const CRYPT_CONTEXT iSignContext,
								   IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
								   STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
								   IN_BUFFER( signatureLength ) \
									const BYTE *signature,
								   IN_LENGTH_SHORT_MIN( 40 ) \
									const int signatureLength )
	{
	MESSAGE_DATA msgData;
	BYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];
	const int signAlgoIdSize = \
				sizeofContextAlgoID( iSignContext, CRYPT_ALGO_NONE );
	const int hashAlgoIdSize = sizeofAlgoID( hashAlgo );
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isReadPtr( signature, signatureLength ) );
			/* Other parameters aren't used for this format */

	REQUIRES( isHandleRangeValid( iSignContext ) );
	REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
			  hashAlgo <= CRYPT_ALGO_LAST_HASH );
	REQUIRES( signatureLength >= 40 && \
			  signatureLength < MAX_INTLENGTH_SHORT );

	if( cryptStatusError( signAlgoIdSize ) )
		return( signAlgoIdSize );
	if( cryptStatusError( hashAlgoIdSize ) )
		return( hashAlgoIdSize );

	/* Get the key ID */
	setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_IATTRIBUTE_KEYID );
	if( cryptStatusError( status ) )
		return( status );

⌨️ 快捷键说明

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