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

📄 pgp_rd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
		retExt( status, 
				( status, errorInfo, 
				  "Invalid PGP userID information for key packet group %d",
				  keyGroupNo ) );
		}

	/* If there's no user ID present, set a generic label */
	if( pgpInfo->lastUserID <= 0 )
		{
		pgpInfo->userID[ 0 ] = "PGP key (no user ID found)";
		pgpInfo->userIDlen[ 0 ] = 26;
		pgpInfo->lastUserID = 1;
		}

	return( CRYPT_OK );
	}

/* Process the information in the packet group */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6 ) ) \
static int processPacketGroup( INOUT STREAM *stream, 
							   INOUT PGP_INFO *pgpInfo,
							   IN_OPT const KEY_MATCH_INFO *keyMatchInfo,
							   INOUT_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,
							   IN_INT_SHORT_Z const int keyGroupNo,
							   INOUT ERROR_INFO *errorInfo )
	{
	int iterationCount, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) ) );
	assert( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) && \
			  isWritePtr( matchedKeyInfoPtrPtr, sizeof( PGP_KEYINFO * ) ) ) );

	REQUIRES( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			  ( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL && \
				pgpInfo->keyData != NULL && \
				pgpInfo->keyDataLen == KEYRING_BUFSIZE ) );
	REQUIRES( keyGroupNo >= 0 && keyGroupNo < MAX_INTLENGTH_SHORT );
	REQUIRES( errorInfo != NULL );

	/* Clear the index information before we read the current key(s), since 
	   it may already have been initialised during a previous (incomplete) 
	   key read */
	memset( &pgpInfo->key, 0, sizeof( PGP_KEYINFO ) );
	memset( &pgpInfo->subKey, 0, sizeof( PGP_KEYINFO ) );
	memset( pgpInfo->userID, 0, sizeof( char * ) * MAX_PGP_USERIDS );
	memset( pgpInfo->userIDlen, 0, sizeof( int ) * MAX_PGP_USERIDS );
	pgpInfo->lastUserID = 0;

	/* Read all the packets in this packet group */
	for( status = CRYPT_OK, iterationCount = 0;
		 cryptStatusOK( status ) && sMemDataLeft( stream ) > 0 && \
			iterationCount++ < FAILSAFE_ITERATIONS_MED;
		 iterationCount++ )
		{
		status = readKey( stream, pgpInfo, keyGroupNo, errorInfo );
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
	if( cryptStatusError( status ) )
		{
		if( status != OK_SPECIAL && status != CRYPT_ERROR_NOSECURE )
			return( status );

		/* There's either something in the key information that we can't 
		   handle or it's stored with no security, skip the key */
		if( keyMatchInfo == NULL )
			pgpFreeEntry( pgpInfo );
		return( status );
		}

	/* If we're reading all keys, we're done */
	if( keyMatchInfo == NULL )
		return( CRYPT_OK );

	/* We're searching for a particular key, see if this is the one */
	if( pgpCheckKeyMatch( pgpInfo, &pgpInfo->key, keyMatchInfo ) )
		{
		*matchedKeyInfoPtrPtr = &pgpInfo->key;
		return( CRYPT_OK );
		}
	if( pgpCheckKeyMatch( pgpInfo, &pgpInfo->subKey, keyMatchInfo ) )
		{
		*matchedKeyInfoPtrPtr = &pgpInfo->subKey;
		return( CRYPT_OK );
		}

	/* No match, tell the caller to keep looking */
	return( CRYPT_ERROR_NOTFOUND );
	}

/****************************************************************************
*																			*
*								Read a Keyring								*
*																			*
****************************************************************************/

/* Read an entire keyring.  This function can be used in one of two ways, if 
   key match information is supplied each packet will be checked against it 
   and the read will exit when a match is found (used for public keyrings).  
   If no key match information is supplied, all keys will be read into 
   memory (used for private keyrings) */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 8, 9 ) ) \
static int processKeyringPackets( INOUT STREAM *stream, 
								  IN_ARRAY( maxNoPgpObjects ) PGP_INFO *pgpInfo, 
								  IN_LENGTH_SHORT const int maxNoPgpObjects,
								  OUT_BUFFER_FIXED( bufSize ) BYTE *buffer, 
								  IN_LENGTH_SHORT_MIN( 64 ) const int bufSize,
								  IN_OPT const KEY_MATCH_INFO *keyMatchInfo,
								  INOUT_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,
								  OUT BOOLEAN *unhandledDataPresent,
								  INOUT ERROR_INFO *errorInfo )
	{
	BYTE streamBuffer[ STREAM_BUFSIZE + 8 ];
	BOOLEAN moreData, insecureKeys = FALSE;
	int bufEnd, keyGroupNo = 0, iterationCount, status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) * maxNoPgpObjects ) );
	assert( isWritePtr( buffer, bufSize ) );
	assert( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) && \
			  isWritePtr( matchedKeyInfoPtrPtr, sizeof( PGP_KEYINFO * ) ) ) );
	assert( isWritePtr( unhandledDataPresent, sizeof( BOOLEAN ) ) );

	REQUIRES( maxNoPgpObjects >= 1 && maxNoPgpObjects < MAX_INTLENGTH_SHORT );
	REQUIRES( bufSize > 64 && bufSize < MAX_INTLENGTH_SHORT );
	REQUIRES( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			  ( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL && \
				pgpInfo->keyData != NULL && \
				pgpInfo->keyDataLen == KEYRING_BUFSIZE ) );
	REQUIRES( errorInfo != NULL );

	/* Clear return value */
	*unhandledDataPresent = FALSE;

	/* Scan all the objects in the file.  This is implemented as a sliding
	   window that reads a certain amount of data into a lookahead buffer
	   and then tries to identify a packet group in the buffer.  If we need
	   to skip packets (for example due to unknown algorithms) we mark the
	   keyset as read-only since it's no longer safe for us to write the
	   incompletely-processed data to disk */
	sioctl( stream, STREAM_IOCTL_IOBUFFER, streamBuffer, STREAM_BUFSIZE );
	for( moreData = TRUE, bufEnd = 0, iterationCount = 0;
		 ( moreData || bufEnd > 0 ) && \
			iterationCount < FAILSAFE_ITERATIONS_MAX;
		 iterationCount++ )
		{
		PGP_INFO *pgpInfoPtr = &pgpInfo[ keyGroupNo ];
		STREAM keyStream;
		int length = DUMMY_INIT;	/* Init needed by gcc */

		/* Fill the lookahead buffer:

			 buffer		 bufEnd			 bufSize
				|			|				|
				v			v				v
				+-----------+---------------+
				|///////////|				|
				+-----------+---------------+ 
							|
							+-- length --> */
		if( moreData )
			{
			REQUIRES( bufEnd >= 0 && bufEnd < bufSize );

			status = length = sread( stream, buffer + bufEnd,
									 bufSize - bufEnd );
			if( status <= 0 )
				{
				/* If we read nothing and there's nothing left in the buffer,
				   we're done */
				if( bufEnd <= 0 )
					{
					/* If we've previously read at least one group of key 
					   packets, we're OK */
					if( keyGroupNo > 0 )
						status = CRYPT_OK;
					return( status );
					}

				/* There's still data in the buffer, we can continue until 
				   we drain it */
				length = 0;
				}
			if( length < bufSize - bufEnd )
				{
				/* We didn't get as much as we requested, there's nothing
				   left to read */
				moreData = FALSE;
				}
			bufEnd += length;
			}

		/* Determine the size of the group of key packets in the buffer */
		status = scanPacketGroup( buffer, bufEnd, &length );
		if( status == OK_SPECIAL )
			{
			/* Remember that we hit something that we couldn't process */
			*unhandledDataPresent = TRUE;

			/* If the packet group is contained within the buffer, remove 
			   the problem packets and continue */
			if( length <= bufEnd )
				{
				if( bufEnd - length > 0 )
					memmove( buffer, buffer + length, bufEnd - length );
				bufEnd -= length;
				continue;
				}
			ENSURES( length > bufEnd );

			/* The packet group overflows the buffer, skip the remaining
			   contents and continue */
			status = sseek( stream, stell( stream ) + ( length - bufEnd ) );
			if( cryptStatusError( status ) )
				break;
			bufEnd = 0;
			continue;
			}
		if( cryptStatusError( status ) )
			{
			retExt( status,
					( status, errorInfo, 
					  "Couldn't parse key packet group %d", keyGroupNo ) );
			}
		if( length <= 0 )
			return( CRYPT_OK );

		/* Move the packet group from the keyring buffer to the key data */
		if( keyMatchInfo == NULL )
			{
			/* It's a read of all packets, allocate room for the current
			   packet group */
			if( ( pgpInfoPtr->keyData = \
								clAlloc( "readKeyring", length ) ) == NULL )
				return( CRYPT_ERROR_MEMORY );
			pgpInfoPtr->keyDataLen = length;
			}
		memcpy( pgpInfoPtr->keyData, buffer, length );
		if( bufEnd > length )
			memmove( buffer, buffer + length, bufEnd - length );
		bufEnd -= length;

		/* Process the current packet group */
		sMemConnect( &keyStream, pgpInfoPtr->keyData, length );
		status = processPacketGroup( &keyStream, pgpInfoPtr, keyMatchInfo,
									 matchedKeyInfoPtrPtr, keyGroupNo, 
									 errorInfo );
		sMemDisconnect( &keyStream );
		if( cryptStatusError( status ) )
			{
			/* If we were looking for a match for a particular key and 
			   didn't find it, continue */
			if( keyMatchInfo != NULL && status == CRYPT_ERROR_NOTFOUND )
				continue;

			/* If it's not a recoverable error, exit */
			if( status != OK_SPECIAL && status != CRYPT_ERROR_NOSECURE )
				return( status );

			/* Remember that we hit something that we couldn't process, and
			   optionally an (unusable) unprotected key */
			*unhandledDataPresent = TRUE;
			if( status == CRYPT_ERROR_NOSECURE )
				insecureKeys = TRUE;
			continue;
			}

		/* If we're looking for a particular key, we've found it */
		if( keyMatchInfo != NULL )
			return( CRYPT_OK );

		/* We're reading all keys, move on to the next empty slot.  Note 
		   that we only get to this point if we've been able to do something 
		   with the key, if not then the unhandledDataPresent flag is set 
		   without moving on to the next key group */
		keyGroupNo++;
		if( keyGroupNo >= maxNoPgpObjects )
			{
			retExt( CRYPT_ERROR_OVERFLOW, 
					( CRYPT_ERROR_OVERFLOW, errorInfo, 
					  "Maximum keyset object item count %d reached, no more "
					  "room to add further items", maxNoPgpObjects ) );
			}
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MAX );

	/* If we were looking for a specific match, we haven't found it */
	if( keyMatchInfo != NULL )
		return( CRYPT_ERROR_NOTFOUND );

	/* If we haven't found any keys that we can use let the caller know.  
	   The error code to return here is a bit complex because we can skip 
	   keys either because there's something in the key data that we can't
	   process or because the keys aren't sufficiently protected for us to
	   trust them.  The most complex case is when both situations occur.  
	   To keep it simple, if there are any insecure keys then we report
	   CRYPT_ERROR_NOSECURE on the basis that if the keys had been 
	   appropriately secured then we might have been able to process them 
	   and return one */
	if( keyGroupNo <= 0 )
		{
		return( insecureKeys ? CRYPT_ERROR_NOSECURE : \
							   CRYPT_ERROR_NOTFOUND );
		}

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 6 ) ) \
int pgpReadKeyring( INOUT STREAM *stream, 
					IN_ARRAY( maxNoPgpObjects ) PGP_INFO *pgpInfo, 
					IN_LENGTH_SHORT const int maxNoPgpObjects,
					IN_OPT const KEY_MATCH_INFO *keyMatchInfo,
					INOUT_OPT PGP_KEYINFO **matchedKeyInfoPtrPtr,
					INOUT ERROR_INFO *errorInfo )
	{
	BOOLEAN unhandledDataPresent;
	BYTE *buffer;
	int status;

	assert( isWritePtr( stream, sizeof( STREAM ) ) );
	assert( isWritePtr( pgpInfo, sizeof( PGP_INFO ) * maxNoPgpObjects ) );
	assert( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			( isReadPtr( keyMatchInfo, sizeof( KEY_MATCH_INFO ) ) && \
			  isWritePtr( matchedKeyInfoPtrPtr, sizeof( PGP_KEYINFO * ) ) ) );

	REQUIRES( maxNoPgpObjects >= 1 && maxNoPgpObjects < MAX_INTLENGTH_SHORT );
	REQUIRES( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			  ( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL && \
				pgpInfo->keyData != NULL && \
				pgpInfo->keyDataLen == KEYRING_BUFSIZE ) );
	REQUIRES( errorInfo != NULL );

	/* Clear the return value */
	if( matchedKeyInfoPtrPtr != NULL )
		*matchedKeyInfoPtrPtr = NULL;

	/* Since PGP keyrings just contain an arbitrary collection of packets 
	   concatenated together we can't tell in advance how much data we 
	   should be reading.  Because of this we have to set the file stream to 
	   allow partial reads without returning a read error */
	if( ( buffer = clAlloc( "readKeyring", KEYRING_BUFSIZE ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	sioctl( stream, STREAM_IOCTL_PARTIALREAD, NULL, TRUE );
	status = processKeyringPackets( stream, pgpInfo, maxNoPgpObjects, 
									buffer, KEYRING_BUFSIZE, 
									keyMatchInfo, matchedKeyInfoPtrPtr, 
									&unhandledDataPresent, errorInfo );
	sioctl( stream, STREAM_IOCTL_IOBUFFER, NULL, 0 );
	clFree( "readKeyring", buffer );
	if( cryptStatusError( status ) )
		return( status );

	/* If we couldn't process one or more packets let the caller know that 
	   not all keyring data is present in memory */
	return( unhandledDataPresent ? OK_SPECIAL : CRYPT_OK );
	}
#endif /* USE_PGPKEYS */

⌨️ 快捷键说明

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