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

📄 sign_rw.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:

	/* Write the header */
	writeSequence( stream, ( int ) sizeofShortInteger( SIGNATURE_EX_VERSION ) + \
				   sizeofObject( msgData.length ) + \
				   signAlgoIdSize + hashAlgoIdSize + \
				   sizeofObject( signatureLength ) );

	/* Write the version, key ID and algorithm identifier */
	writeShortInteger( stream, SIGNATURE_EX_VERSION, DEFAULT_TAG );
	writeOctetString( stream, msgData.data, msgData.length, CTAG_SI_SKI );
	writeAlgoID( stream, hashAlgo );
	writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE );
	return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
	}

/****************************************************************************
*																			*
*							PGP Signature Routines							*
*																			*
****************************************************************************/

#ifdef USE_PGP

/* Read a PGP type-and-value packet and check whether it's one of ours */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readTypeAndValue( INOUT STREAM *stream, 
							 INOUT QUERY_INFO *queryInfo,
							 IN_LENGTH_Z const int startPos )
	{
	BYTE nameBuffer[ 32 + 8 ];
	static const char FAR_BSS *nameString = "issuerAndSerialNumber";
	int nameLength, valueLength, status;	/* length = 21 */

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

	REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
	REQUIRES( startPos < stell( stream ) );

	/* Skip the flags */
	status = sSkip( stream, UINT32_SIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the attribute length information and make sure that it looks 
	   valid */
	nameLength = readUint16( stream );
	valueLength = readUint16( stream );
	if( cryptStatusError( valueLength ) )
		return( valueLength );
	if( nameLength != 21 || valueLength < 16 || valueLength > 2048 )
		return( sSkip( stream, nameLength + valueLength ) );

	/* Read the name and check whether it's one that we recognise */
	status = sread( stream, nameBuffer, nameLength );
	if( cryptStatusError( status ) )
		return( status );
	if( !memcmp( nameBuffer, nameString, nameLength ) )
		{
		/* It's an issuerAndSerialNumber, remember it for later */
		queryInfo->iAndSStart = stell( stream ) - startPos;
		queryInfo->iAndSLength = valueLength;
		}
	return( sSkip( stream, valueLength ) );
	}

/* Read signature subpackets.  In theory we could do something with the 
   isAuthenticated flag but at the moment we don't rely on any attributes 
   that require authentication.  The most that an attacker can do by 
   changing the keyID/iAndS field is cause the signature check to fail, 
   which they can do just as easily by flipping a bit */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readSignatureSubpackets( INOUT STREAM *stream, 
									INOUT QUERY_INFO *queryInfo,
									IN_LENGTH_SHORT const int length, 
									IN_LENGTH const int startPos,
									const BOOLEAN isAuthenticated )
	{
	const int endPos = stell( stream ) + length;
	int iterationCount = 0;

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

	REQUIRES( length > 0 && length < MAX_INTLENGTH_SHORT );
	REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
	REQUIRES( startPos < stell( stream ) );

	while( stell( stream ) < endPos && \
		   iterationCount++ < FAILSAFE_ITERATIONS_MED )
		{
		int subpacketLength, type = DUMMY_INIT, status;

		/* Read the subpacket length and type */
		status = pgpReadShortLength( stream, &subpacketLength, 
									 PGP_CTB_OPENPGP );
		if( cryptStatusOK( status ) )
			status = type = sgetc( stream );
		if( cryptStatusError( status ) )
			return( status );

		/* If it's an unrecognised subpacket with the critical flag set,
		   reject the signature.  The range check isn't complete since there
		   are a few holes in the range, but since the holes presumably exist
		   because of deprecated subpacket types any new packets will be 
		   added at the end so it's safe to use */
		if( ( type & 0x80 ) && ( ( type & 0x7F ) > PGP_SUBPACKET_LAST ) )
			return( CRYPT_ERROR_NOTAVAIL );

		switch( type )
			{
			case PGP_SUBPACKET_KEYID:
				/* Make sure that the length is valid */
				if( subpacketLength != PGP_KEYID_SIZE + 1 )
					return( CRYPT_ERROR_BADDATA );

				/* If it's a key ID and we haven't already set this from a 
				   preceding one-pass signature packet (which can happen 
				   with detached sigs), set it now */
				if( queryInfo->keyIDlength <= 0 )
					{
					status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
					queryInfo->keyIDlength = PGP_KEYID_SIZE;
					}
				else
					{
					/* We've already got the ID, skip it and continue.  The 
					   -1 is for the packet type, which we've already read */
					status = sSkip( stream, subpacketLength - 1 );
					}
				break;

			case PGP_SUBPACKET_TYPEANDVALUE:
				/* It's a type-and-value packet, check whether it's one of 
				   ours */
				status = readTypeAndValue( stream, queryInfo, startPos );
				break;

			default:
				/* It's something else, skip it and continue.  The -1 is for 
				   the packet type, which we've already read */
				status = sSkip( stream, subpacketLength - 1 );
			}

		if( cryptStatusError( status ) )
			return( status );
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( CRYPT_OK );
	}

/* Signature info:

	byte	ctb = PGP_PACKET_SIGNATURE_ONEPASS
	byte[]	length
	byte	version = 3 (= OpenPGP, not the expected PGP3)
	byte	sigType
	byte	hashAlgo
	byte	sigAlgo
	byte[8]	keyID
	byte	1 */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readPgpOnepassSigPacket( INOUT STREAM *stream, 
							 INOUT QUERY_INFO *queryInfo )
	{
	int status;

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

	/* Make sure that the packet header is in order and check the packet
	   version.  This is an OpenPGP-only packet */
	status = getPgpPacketInfo( stream, queryInfo );
	if( cryptStatusError( status ) )
		return( status );
	if( sgetc( stream ) != 3 )
		return( CRYPT_ERROR_BADDATA );
	queryInfo->version = PGP_VERSION_OPENPGP;

	/* Skip the sig.type and get the hash algorithm and signature 
	   algorithms */
	status = sgetc( stream );	/* Skip signature type */
	if( cryptStatusOK( status ) )
		status = readPgpAlgo( stream, &queryInfo->hashAlgo, 
							  PGP_ALGOCLASS_HASH );
	if( cryptStatusOK( status ) )
		status = readPgpAlgo( stream, &queryInfo->cryptAlgo, 
							  PGP_ALGOCLASS_SIGN );
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->type = CRYPT_OBJECT_SIGNATURE;

	/* Get the PGP key ID and make sure that this isn't a nested signature */
	status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->keyIDlength = PGP_KEYID_SIZE;
	return( ( sgetc( stream ) != 1 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );
	}

/* Read/write PGP signatures.

		byte	ctb = PGP_PACKET_SIGNATURE
		byte[]	length
	v3:	byte	version = PGP_2,3	v4: byte	version = PGP_VERSION_OPENPGP
		byte	infoLen = 5				byte	sigType
			byte	sigType				byte	sigAlgo
			byte[4]	sig.time			byte	hashAlgo
		byte[8]	keyID					uint16	length of auth.attributes
		byte	sigAlgo					byte[]	authenticated attributes
		byte	hashAlgo				uint16	length of unauth.attributes
		byte[2]	hash check				byte[]	unauthenticated attributes
		mpi(s)	signature							-- Contains keyID
										byte[2]	hash check
										mpi(s)	signature */

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

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

	REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
	REQUIRES( startPos < stell( stream ) );

	/* Read PGP 2.x additional signature information */
	if( sgetc( stream ) != 5 )
		return( CRYPT_ERROR_BADDATA );
	queryInfo->attributeStart = stell( stream ) - startPos;
	queryInfo->attributeLength = 5;
	status = sSkip( stream, 5 );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the signer keyID and signature and hash algorithms */
	status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
	if( cryptStatusError( status ) )
		return( status );
	queryInfo->keyIDlength = PGP_KEYID_SIZE;
	status = readPgpAlgo( stream, &queryInfo->cryptAlgo, 
						  PGP_ALGOCLASS_SIGN );
	if( cryptStatusOK( status ) )
		status = readPgpAlgo( stream, &queryInfo->hashAlgo, 
							  PGP_ALGOCLASS_HASH );
	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readOpenPgpSigInfo( INOUT STREAM *stream, 
							   INOUT QUERY_INFO *queryInfo,
							   IN_LENGTH_Z const int startPos )
	{
	int length, status;

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

	REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
	REQUIRES( startPos < stell( stream ) );

	/* Remember the extra data to be hashed and read the signature and hash 
	   algorithms.  Since the extra data starts at the version byte that 
	   we've already read, we add a -1 offset to the start position, as well
	   as including it in the overall length calculation */
	queryInfo->attributeStart = ( stell( stream ) - 1 ) - startPos;
	queryInfo->attributeLength = PGP_VERSION_SIZE + 1 + \
								 PGP_ALGOID_SIZE + PGP_ALGOID_SIZE;
	status = sgetc( stream );	/* Skip signature type */
	if( cryptStatusOK( status ) )
		status = readPgpAlgo( stream, &queryInfo->cryptAlgo, 
							  PGP_ALGOCLASS_SIGN );
	if( cryptStatusOK( status ) )
		status = readPgpAlgo( stream, &queryInfo->hashAlgo, 
							  PGP_ALGOCLASS_HASH );
	if( cryptStatusError( status ) )
		return( status );

	/* Process the authenticated attributes */
	length = readUint16( stream );
	if( cryptStatusError( length ) )
		return( length );
	if( length < 0 || length > 2048 )
		return( CRYPT_ERROR_BADDATA );
	queryInfo->attributeLength += UINT16_SIZE + length;
	if( length > 0 )
		{
		status = readSignatureSubpackets( stream, queryInfo, length,
										  startPos, TRUE );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Process the unauthenticated attributes */
	queryInfo->unauthAttributeStart = stell( stream ) - startPos;
	length = readUint16( stream );
	if( cryptStatusError( length ) )
		return( length );
	if( length < 0 || length > 2048 )
		return( CRYPT_ERROR_BADDATA );
	queryInfo->unauthAttributeLength = UINT16_SIZE + length;
	if( length > 0 )
		{
		status = readSignatureSubpackets( stream, queryInfo, length, 
										  startPos, FALSE );
		if( cryptStatusError( status ) )
			return( status );
		}

	return( CRYPT_OK );
	}

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

⌨️ 快捷键说明

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