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

📄 pgp.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 4 页
字号:
		status = sSkip( stream, packetLength );
		}

	return( status );
	}

/* Process the information in the packet group */

static int processPacketGroup( STREAM *stream, PGP_INFO *pgpInfo,
							   const KEY_MATCH_INFO *keyMatchInfo,
							   PGP_KEYINFO **matchedKeyInfoPtrPtr )
	{
	int status;

	/* Clear the index info before we read the current keys, 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 */
	do
		status = readKey( stream, pgpInfo );
	while( cryptStatusOK( status ) && sMemDataLeft( stream ) > 0 );
	if( cryptStatusError( status ) )
		{
		if( status != OK_SPECIAL )
			return( status );

		/* There's something in the key information that we can't handle, 
		   mark the keyring as read-only and skip the key */
		if( keyMatchInfo == NULL )
			pgpFreeEntry( pgpInfo );
		return( OK_SPECIAL );
		}

	/* 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( checkKeyMatch( pgpInfo, &pgpInfo->key, keyMatchInfo ) )
		{
		*matchedKeyInfoPtrPtr = &pgpInfo->key;
		return( CRYPT_OK );
		}
	if( checkKeyMatch( pgpInfo, &pgpInfo->subKey, keyMatchInfo ) )
		{
		*matchedKeyInfoPtrPtr = &pgpInfo->subKey;
		return( CRYPT_OK );
		}

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

/* 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.  If no key match info is
   supplied, all keys will be read into memory */

static int processKeyringPacketsMMapped( STREAM *stream, 
										 KEYSET_INFO *keysetInfo, 
										 const KEY_MATCH_INFO *keyMatchInfo,
										 PGP_KEYINFO **matchedKeyInfoPtrPtr )
	{
	PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfo->keyData;
	int keyGroupNo = 0, status;

	assert( keyMatchInfo == NULL || \
			( pgpInfo->keyData != NULL && \
			  pgpInfo->keyDataLen == KEYRING_BUFSIZE ) );

	while( TRUE )
		{
		PGP_INFO *pgpInfoPtr = &pgpInfo[ keyGroupNo ];
		STREAM keyStream;
		int length;

		/* Determine the size of the group of key packets in the buffer */
		status = scanPacketGroup( sMemBufPtr( stream ), 
								  sMemDataLeft( stream ), &length );
		if( cryptStatusError( status ) )
			{
			if( status != OK_SPECIAL )
				return( status );

			/* We couldn't process one or more packets, make the keyset
			   read-only to ensure that the incomplete key data isn't 
			   written to disk */
			keysetInfo->options = CRYPT_KEYOPT_READONLY;
			}

		status = sFileToMemStream( &keyStream, stream, NULL, length );
		if( cryptStatusOK( status ) )
			status = processPacketGroup( &keyStream, pgpInfoPtr, keyMatchInfo,
										 matchedKeyInfoPtrPtr );
		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( status != OK_SPECIAL )
				return( status );

			/* There's something in the key information that we can't 
			   handle, mark the keyring as read-only */
			keysetInfo->options = CRYPT_KEYOPT_READONLY;
			status = CRYPT_OK;
			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 */
		keyGroupNo++;
		if( keyGroupNo >= MAX_PGP_OBJECTS )
			return( CRYPT_ERROR_OVERFLOW );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int processKeyringPackets( STREAM *stream, BYTE *buffer, 
								  KEYSET_INFO *keysetInfo, 
								  const KEY_MATCH_INFO *keyMatchInfo,
								  PGP_KEYINFO **matchedKeyInfoPtrPtr )
	{
	PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfo->keyData;
	BYTE streamBuffer[ STREAM_BUFSIZE ];
	BOOLEAN moreData = TRUE;
	int bufEnd = 0, keyGroupNo = 0, status;

	assert( keyMatchInfo == NULL || \
			( pgpInfo->keyData != NULL && \
			  pgpInfo->keyDataLen == KEYRING_BUFSIZE ) );

	/* 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 );
	while( moreData || bufEnd > 0 )
		{
		PGP_INFO *pgpInfoPtr = &pgpInfo[ keyGroupNo ];
		STREAM keyStream;
		int length;

		/* Fill the lookahead buffer */
		if( moreData )
			{
			status = length = sread( stream, buffer + bufEnd,
									 KEYRING_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 < KEYRING_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 )
			{
			/* We couldn't process one or more packets, make the keyset
			   read-only to ensure that the incomplete key data isn't 
			   written to disk */
			keysetInfo->options = CRYPT_KEYOPT_READONLY;

			/* 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;
				}

			/* 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 ) || length <= 0 )
			return( status );

		/* 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 > 0 )
			memmove( buffer, buffer + length, bufEnd - length );
		bufEnd -= length;

		/* Process the current packet group */
		sMemConnect( &keyStream, pgpInfoPtr->keyData, length );
		status = processPacketGroup( &keyStream, pgpInfoPtr, keyMatchInfo,
									 matchedKeyInfoPtrPtr );
		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( status != OK_SPECIAL )
				return( status );

			/* There's something in the key information that we can't 
			   handle, mark the keyring as read-only */
			keysetInfo->options = CRYPT_KEYOPT_READONLY;
			status = CRYPT_OK;
			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 */
		keyGroupNo++;
		if( keyGroupNo >= MAX_PGP_OBJECTS )
			return( CRYPT_ERROR_OVERFLOW );
		}
	
	return( ( keyMatchInfo == NULL ) ? CRYPT_OK : CRYPT_ERROR_NOTFOUND );
	}

static int readKeyring( KEYSET_INFO *keysetInfo, 
						const KEY_MATCH_INFO *keyMatchInfo,
						PGP_KEYINFO **matchedKeyInfoPtrPtr )
	{
	STREAM *stream = &keysetInfo->keysetFile->stream;
	int status;

	assert( ( keyMatchInfo == NULL && matchedKeyInfoPtrPtr == NULL ) || \
			( keyMatchInfo != NULL && matchedKeyInfoPtrPtr != NULL ) );

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

	if( sIsMemMappedStream( stream ) )
		{
		status = processKeyringPacketsMMapped( stream, keysetInfo, 
											   keyMatchInfo, 
											   matchedKeyInfoPtrPtr );
		}
	else
		{
		BYTE *buffer;

		if( ( buffer = clAlloc( "readKeyring", KEYRING_BUFSIZE ) ) == NULL )
			return( CRYPT_ERROR_MEMORY );

		/* 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 */
		sioctl( stream, STREAM_IOCTL_PARTIALREAD, NULL, 0 );
		status = processKeyringPackets( stream, buffer, keysetInfo, 
										keyMatchInfo, matchedKeyInfoPtrPtr );
		sioctl( stream, STREAM_IOCTL_IOBUFFER, NULL, 0 );
		clFree( "readKeyring", buffer );
		}

	/* If we're reading all keys and the read failed, the keyring as a whole 
	   can't be used */
	if( keyMatchInfo == NULL && cryptStatusError( status ) )
		keysetInfo->shutdownFunction( keysetInfo );
	return( status );
	}

/* Read key data from a PGP keyring */

static int getItemFunction( KEYSET_INFO *keysetInfo,
							CRYPT_HANDLE *iCryptHandle,
							const KEYMGMT_ITEM_TYPE itemType,
							const CRYPT_KEYID_TYPE keyIDtype,
							const void *keyID,  const int keyIDlength,
							void *auxInfo, int *auxInfoLength,
							const int flags )
	{
	CRYPT_CONTEXT iSessionKey;
	PGP_INFO *pgpInfo = ( PGP_INFO * ) keysetInfo->keyData;
	PGP_KEYINFO *keyInfo;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MECHANISM_WRAP_INFO mechanismInfo;
	RESOURCE_DATA msgData;
	int status;

	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
			itemType == KEYMGMT_ITEM_PRIVATEKEY );
	assert( keyIDtype == CRYPT_KEYID_NAME || \
			keyIDtype == CRYPT_KEYID_URI || \
			keyIDtype == CRYPT_IKEYID_KEYID || \
			keyIDtype == CRYPT_IKEYID_PGPKEYID );

	/* Find the requested item.  This is complicated somewhat by the fact
	   that private keys are held in memory while public keys (which can
	   be arbitrarily numerous) are held on disk.  This means that the former
	   (and also public keys read from a private-key keyring) are found with 
	   a quick in-memory search while the latter require a scan of the 
	   keyring on disk */
	if( itemType == KEYMGMT_ITEM_PRIVATEKEY || \
		keysetInfo->subType == KEYSET_SUBTYPE_PGP_PRIVATE )
		{
		/* Try and locate the appropriate object in the PGP collection */
		pgpInfo = findEntry( keysetInfo->keyData, keyIDtype, keyID, 
							 keyIDlength, flags, &keyInfo );
		if( pgpInfo == NULL )
			return( CRYPT_ERROR_NOTFOUND );
		}
	else
		{
		CONST_INIT_STRUCT_4( KEY_MATCH_INFO keyMatchInfo, \
							 keyIDtype, keyID, keyIDlength, flags );

		CONST_SET_STRUCT( keyMatchInfo.keyIDtype = keyIDtype; \
						  keyMatchInfo.keyID = keyID; \
						  keyMatchInfo.keyIDlength = keyIDlength; \
						  keyMatchInfo.flags = flags );

		/* Try and find the required key in the file */
		sseek( &keysetInfo->keysetFile->stream, 0 );

⌨️ 快捷键说明

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