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

📄 pgp_deen.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
						envelopeInfoPtr->hashActionsActive = TRUE;
						envelopeInfoPtr->payloadSize = 0;
						state = PGP_DEENVSTATE_DONE;
						}
					else
						state = PGP_DEENVSTATE_DATA;
					break;

				case PGP_PACKET_ENCR_MDC:
					/* The encrypted-data-with-MDC packet is preceded by a
					   version number */
					status = sgetc( &stream );
					if( !cryptStatusError( status ) && status != 1 )
						status = CRYPT_ERROR_BADDATA;
					if( cryptStatusError( status ) )
						break;
					/* Fall through */

				case PGP_PACKET_ENCR:
					if( envelopeInfoPtr->usage != ACTION_NONE && \
						envelopeInfoPtr->usage != ACTION_CRYPT )
						{
						status = CRYPT_ERROR_BADDATA;
						break;
						}
					envelopeInfoPtr->usage = ACTION_CRYPT;
					state = ( packetType == PGP_PACKET_ENCR_MDC ) ? \
							PGP_DEENVSTATE_ENCR_MDC : PGP_DEENVSTATE_ENCR;
					break;

				case PGP_PACKET_MARKER:
					/* Obsolete market packet, skip it */
					status = sSkip( &stream, packetLength );
					if( cryptStatusError( status ) )
						break;
					break;

				default:
					status = CRYPT_ERROR_BADDATA;
				}

			/* If there's a problem, exit */
			if( cryptStatusError( status ) )
				break;

			/* Remember how far we got */
			streamPos = ( int ) stell( &stream );
			}

		/* Process the start of an encrypted data packet */
		if( state == PGP_DEENVSTATE_ENCR || \
			state == PGP_DEENVSTATE_ENCR_MDC )
			{
			BYTE ivInfoBuffer[ CRYPT_MAX_IVSIZE + 2 ];
			int ivSize;

			/* If there aren't any non-session-key keying resource objects
			   present, we can't go any further until we get a session key */
			if( envelopeInfoPtr->actionList == NULL )
				{
				/* There's no session key object present, add a pseudo-object
				   which takes the place of the (password-derived) session key
				   object in the content list.  This can only occur for PGP
				   2.x conventionally-encrypted data, which didn't encode any
				   algorithm information with the data, so if we get to this
				   point we know we've hit data encrypted with the default
				   IDEA/CFB derived from a user password using MD5 */
				if( envelopeInfoPtr->contentList == NULL )
					{
					status = addContentListItem( NULL, envelopeInfoPtr, 0, 0 );
					if( cryptStatusError( status ) )
						break;
					}

				/* We can't continue until we're given some sort of keying
				   resource */
				status = CRYPT_ENVELOPE_RESOURCE;
				break;
				}
			assert( envelopeInfoPtr->actionList->action == ACTION_CRYPT );

			/* Read and process PGP's peculiar two-stage IV */
			status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle,
									  RESOURCE_IMESSAGE_GETATTRIBUTE,
									  &ivSize, CRYPT_CTXINFO_IVSIZE );
			if( cryptStatusError( status ) )
				break;
			if( sread( &stream, ivInfoBuffer, ivSize + 2 ) != CRYPT_OK )
				{
				status = CRYPT_ERROR_UNDERFLOW;
				break;
				}
			status = pgpProcessIV( envelopeInfoPtr->actionList->iCryptHandle,
								   ivInfoBuffer, ivSize, FALSE,
								   ( state == PGP_DEENVSTATE_ENCR ) ? \
									 TRUE : FALSE );
			if( cryptStatusError( status ) )
				break;
			envelopeInfoPtr->iCryptContext = \
								envelopeInfoPtr->actionList->iCryptHandle;

			/* Remember where we are and move on to the next state */
			streamPos = stell( &stream );
			state = PGP_DEENVSTATE_DATA;
			}

		/* Process the start of a data packet */
		if( state == PGP_DEENVSTATE_DATA )
			{
			/* Synchronise the data stream processing to the start of the
			   encrypted data and move back to the start of the data
			   stream */
			status = envelopeInfoPtr->syncDeenvelopeData( envelopeInfoPtr,
														  &stream );
			if( cryptStatusError( status ) )
				break;
			streamPos = 0;
			assert( actionsOK( envelopeInfoPtr ) );

			/* Move on to the next state.  For plain data we're done,
			   however for other content types we have to either process or
			   strip out the junk PGP puts at the start of the content */
			if( envelopeInfoPtr->usage != ACTION_NONE )
				{
				envelopeInfoPtr->oobEventCount = 1;
				state = PGP_DEENVSTATE_DATA_HEADER;
				}
			else
				state = PGP_DEENVSTATE_DONE;
			assert( actionsOK( envelopeInfoPtr ) );
			}

		/* PGP doesn't provide any indication of what the content of the
		   current packet is, so we have to burrow down into the encrypted
		   data to see whether the payload needs any further processing.
		   This state looks ahead into this data to see whether we need to
		   strip the header (for a plain data packet) or inform the user
		   that there's a nested content type */
		if( state == PGP_DEENVSTATE_DATA_HEADER )
			{
			STREAM headerStream;
			BYTE buffer[ 64 + 256 ];
			int bytesWanted;

			/* If there's no out-of-band data left to remove at the start of
			   the payload, we're done */
			if( !envelopeInfoPtr->oobEventCount && \
				!envelopeInfoPtr->oobDataLeft )
				break;

			/* We have to perform all sorts of special-case processing to
			   handle the out-of-band packet header at the start of the
			   payload.  Initially, we need to find out how much header data
			   is actually present.  The header consists of:
				byte	ctb
				byte[]	length
				byte	type = 'b' | 't'
				byte	filename length
				byte[]	filename
				byte[4]	timestamp

			   The smallest size for this header (1-byte length, no filename)
			   is 1 + 1 + 1 + 1 + 4 = 8 bytes.  This is also just enough to
			   get us to the filename length for a maximum-size header, which
			   is 1 + 5 + 1 + 1 bytes up to the filename length.  Thus we
			   read 8 bytes */
			bytesWanted = envelopeInfoPtr->oobEventCount ? \
						  -8 : envelopeInfoPtr->oobDataLeft;

			/* Try and read the the requested amount of out-of-band data
			   from the start of the payload */
			length = envelopeInfoPtr->copyFromDeenvelope( envelopeInfoPtr,
														  buffer, bytesWanted );
			if( cryptStatusError( length ) )
				status = length;
			else
				if( length < \
					( ( bytesWanted >= 0 ) ? bytesWanted : -bytesWanted ) )
					status = CRYPT_ERROR_UNDERFLOW;
			if( cryptStatusError( status ) )
				break;

			/* If we're down to stripping raw header data, clean up and
			   exit */
			if( !envelopeInfoPtr->oobEventCount )
				{
				/* We've successfully stripped all the out-of-band data.  If
				   it's compressed data (which doesn't have a 1:1
				   correspondence between input and output and which has an
				   unknown-length encoding so there's no length information
				   to adjust), exit */
				envelopeInfoPtr->oobDataLeft = 0;
				if( envelopeInfoPtr->usage == ACTION_COMPRESS )
					{
					state = PGP_DEENVSTATE_DONE;
					continue;
					}

				/* Adjust the current data count by what we've removed.  If
				   we've reached the end of the data (ie the entire current
				   segment is contained within the data present in the
				   buffer), remember that what's left still needs to be
				   processed (eg hashed in the case of signed data) on the
				   way out */
				envelopeInfoPtr->segmentSize -= length;
				assert( envelopeInfoPtr->segmentSize >= 0 );
				if( envelopeInfoPtr->segmentSize <= envelopeInfoPtr->bufPos )
					{
					envelopeInfoPtr->dataLeft = envelopeInfoPtr->segmentSize;
					envelopeInfoPtr->segmentSize = 0;
					}

				/* We've processed the header, if this is signed data we
				   start hashing from this point (the PGP RFCs are wrong in
				   this regard, only the payload is hashed, not the entire
				   packet) */
				if( envelopeInfoPtr->usage == ACTION_SIGN )
					envelopeInfoPtr->hashActionsActive = TRUE;

				/* We're done */
				state = PGP_DEENVSTATE_DONE;
				continue;
				}

			/* Read the header information and see what we've got */
			sMemConnect( &headerStream, buffer, length );
			packetType = getPacketInfo( &headerStream, envelopeInfoPtr,
										&packetLength );
			if( cryptStatusError( packetType ) )
				{
				sMemClose( &headerStream );
				status = packetType;
				break;
				}

			/* Remember the total data packet size unless it's compressed
			   data, which doesn't have a 1:1 correspondence between input
			   and output.  This also skips any MDC packets which may be
			   attached to the end of the plaintext */
			if( envelopeInfoPtr->usage != ACTION_COMPRESS )
				envelopeInfoPtr->payloadSize = envelopeInfoPtr->segmentSize = \
										stell( &headerStream ) + packetLength;

			/* If it's a literal data packet, parse it so we can strip it
			   from the data we return to the caller */
			if( packetType == PGP_PACKET_DATA )
				{
				int extraLen;

				sgetc( &headerStream );		/* Skip content type */
				extraLen = sgetc( &headerStream );
				envelopeInfoPtr->oobDataLeft = \
							( int ) stell( &headerStream ) + extraLen + 4;
				sMemClose( &headerStream );

				/* We've processed enough of the header to know what to do
				   next, move on to the next stage where we just consume all
				   the input */
				envelopeInfoPtr->oobEventCount--;
				}
			else
				{
				static const struct {
					const int pgpType; const int cryptlibType;
					} typeMapTbl[] = {
					{ PGP_PACKET_COPR, CRYPT_CONTENT_COMPRESSEDDATA },
					{ PGP_PACKET_ENCR, CRYPT_CONTENT_ENCRYPTEDDATA },
					{ PGP_PACKET_ENCR_MDC, CRYPT_CONTENT_ENCRYPTEDDATA },
					{ PGP_PACKET_SKE, CRYPT_CONTENT_ENCRYPTEDDATA },
					{ PGP_PACKET_PKE, CRYPT_CONTENT_ENVELOPEDDATA },
					{ PGP_PACKET_SIGNATURE, CRYPT_CONTENT_SIGNEDDATA },
					{ PGP_PACKET_SIGNATURE_ONEPASS, CRYPT_CONTENT_SIGNEDDATA },
					{ CRYPT_ERROR, CRYPT_ERROR },
					};
				int i;

				sMemClose( &headerStream );

				/* If it's a known packet type, indicate it as the nested
				   content type */
				for( i = 0; typeMapTbl[ i ].pgpType != CRYPT_ERROR; i++ )
					if( typeMapTbl[ i ].pgpType == packetType )
						{
						envelopeInfoPtr->contentType = \
											typeMapTbl[ i ].cryptlibType;
						break;
						}
				if( typeMapTbl[ i ].pgpType == CRYPT_ERROR )
					{
					status = CRYPT_ERROR_BADDATA;
					break;
					}

				/* If it's not compressed data (which doesn't have a 1:1
				   correspondence between input and output), we've reached
				   the end of the data (ie the entire current segment is
				   contained within the data present in the buffer), remember
				   that what's left still needs to be processed (eg hashed
				   in the case of signed data) on the way out */
				if( envelopeInfoPtr->usage != ACTION_COMPRESS && \
					envelopeInfoPtr->segmentSize <= envelopeInfoPtr->bufPos )
					{
					envelopeInfoPtr->dataLeft = envelopeInfoPtr->segmentSize;
					envelopeInfoPtr->segmentSize = 0;
					}

				/* Don't try and process the content any further */
				envelopeInfoPtr->oobEventCount = \
								envelopeInfoPtr->oobDataLeft = 0;
				state = PGP_DEENVSTATE_DONE;
				}
			}
		}
	envelopeInfoPtr->pgpDeenvState = state;

	/* Consume the input we've processed so far by moving everything past the
	   current position down to the start of the memory buffer */
	length = envelopeInfoPtr->bufPos - streamPos;
	if( length && streamPos )
		memmove( envelopeInfoPtr->buffer, envelopeInfoPtr->buffer + streamPos,
				 length );
	envelopeInfoPtr->bufPos = length;

	/* If all went OK but we're still not out of the header information,
	   return an underflow error */
	if( cryptStatusOK( status ) && state != PGP_DEENVSTATE_DONE )
		status = CRYPT_ERROR_UNDERFLOW;

	/* Clean up */
	sMemDisconnect( &stream );
	return( status );
	}

static int processPostamble( ENVELOPE_INFO *envelopeInfoPtr )
	{
	CONTENT_LIST *contentListPtr;
	int status = CRYPT_OK;

	/* If that's all there is, return */
	if( envelopeInfoPtr->usage != ACTION_SIGN )
		return( CRYPT_OK );

	/* Find the signature information in the content list.  In theory this
	   could get ugly because there could be multiple one-pass signature
	   packets present, however PGP handles multiple signatures by nesting
	   them so this isn't a problem */
	for( contentListPtr = envelopeInfoPtr->contentList;
		 contentListPtr != NULL && \
			contentListPtr->envInfo != CRYPT_ENVINFO_SIGNATURE;
		 contentListPtr = contentListPtr->next );

	/* If we're processing a one-pass signature, the signature data follows
	   rather than precedes the payload, so we have to read the signature
	   before we can continue */
	if( contentListPtr->object == NULL )
		{
		STREAM stream;
		long packetLength;
		int packetType;

		/* Make sure there's enough data left in the stream to do something
		   with.  This isn't strictly necessary for the following code to
		   work but is required to avoid triggering the zero-length stream
		   check */
		if( envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft < \
			PGP_MAX_HEADER_SIZE )
			return( CRYPT_ERROR_UNDERFLOW );

		/* Read the signature packet at the end of the payload */
		sMemConnect( &stream, envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,
					 envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft );
		packetType = getPacketInfo( &stream, envelopeInfoPtr, &packetLength );
		if( !cryptStatusError( packetType ) && \
			packetType != PGP_PACKET_SIGNATURE )
			packetType = CRYPT_ERROR_BADDATA;
		if( cryptStatusError( packetType ) )
			{
			sMemDisconnect( &stream );
			return( packetType );
			}
		status = addContentListItem( &stream, envelopeInfoPtr,
									 PGP_PACKET_SIGNATURE_SPECIAL,
									 packetLength );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* We've seen all the signed data, complete the hashing.  When we reach
	   this point there may still be unhashed data left in the buffer (it
	   won't have been hashed yet because the hashing is performed when the
	   data is copied out, after unwrapping and whatnot) so we hash it
	   before we wrap up the hashing */
	if( envelopeInfoPtr->dataLeft )
		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr,
						envelopeInfoPtr->buffer, envelopeInfoPtr->dataLeft );
	if( cryptStatusOK( status ) )
		/* After hashing the content, PGP also hashes in extra authenticated
		   attributes */
		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr,
										contentListPtr->extraData,
										contentListPtr->extraDataLength );
	if( cryptStatusOK( status ) && contentListPtr->extraDataLength != 5 )
		{
		BYTE buffer[ 8 ], *bufPtr = buffer + 2;

		/* In addition to the standard authenticated attributes, OpenPGP
		   hashes in even more stuff at the end */
		buffer[ 0 ] = 0x04;
		buffer[ 1 ] = 0xFF;
		mputBLong( bufPtr, contentListPtr->extraDataLength );
		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr,
													buffer, 6 );
		}
	if( cryptStatusOK( status ) )
		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr, "", 0 );
	if( cryptStatusError( status ) )
		return( status );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Envelope Access Routines						*
*																			*
****************************************************************************/

void initPGPDeenveloping( ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	envelopeInfoPtr->processPreamble = processPreamble;
	envelopeInfoPtr->processPostamble = processPostamble;

	/* Set up the processing state information */
	envelopeInfoPtr->pgpDeenvState = PGP_DEENVSTATE_NONE;
	}

⌨️ 快捷键说明

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