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

📄 decode.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	if( envelopeInfoPtr->iCryptContext != CRYPT_ERROR )
		{
		status = krnlSendMessage( envelopeInfoPtr->iCryptContext,
								  IMESSAGE_CTX_DECRYPT, bufPtr,
								  bytesToCopy );
		if( cryptStatusError( status ) )
			return( status );
		}
	envelopeInfoPtr->bufPos += bytesToCopy;
	if( !( envelopeInfoPtr->dataFlags & ENVDATA_NOLENGTHINFO ) )
		envelopeInfoPtr->segmentSize -= bytesToCopy;

	/* If the payload has a definite length and we've reached its end, set
	   the EOC flag to make sure that we don't go any further */
	if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED && \
		envelopeInfoPtr->segmentSize <= 0 )
		{
		status = processDataEnd( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}

	ENSURES( bytesToCopy > 0 && bytesToCopy <= length );
	ENSURES( sanityCheck( envelopeInfoPtr ) );

	*bytesCopied = bytesToCopy;
	return( CRYPT_OK );
	}

/* Copy data into the de-enveloping envelope.  Returns the number of bytes
   copied */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int copyToDeenvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							 IN_BUFFER( length ) const BYTE *buffer, 
							 IN_LENGTH const int length )
	{
	BYTE *bufPtr = ( BYTE * ) buffer;
	int currentLength = length, bytesCopied, iterationCount;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isReadPtr( buffer, length ) );

/*///////////////////////////////////////////////////*/
assert( envelopeInfoPtr->segmentSize != CRYPT_UNUSED );
/*///////////////////////////////////////////////////*/

	REQUIRES( sanityCheck( envelopeInfoPtr ) );
	REQUIRES( length > 0 && length < MAX_INTLENGTH );

	/* If we're trying to copy data into a full buffer, return a count of 0
	   bytes (the calling routine may convert this to an overflow error if
	   necessary) */
	if( envelopeInfoPtr->bufPos >= envelopeInfoPtr->bufSize )
		return( 0 );

	/* If we're verifying a detached signature, just hash the data and exit.
	   We don't have to check whether hashing is active or not because it'll
	   always be active for detached data sicne this is the only thing 
	   that's done with it */
	if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
		{
		int status;

		REQUIRES( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE );

		status = hashEnvelopeData( envelopeInfoPtr->actionList,
								   buffer, currentLength );
		return( cryptStatusError( status ) ? status : currentLength );
		}

	/* Keep processing data until either we run out of input or we can't copy
	   in any more data.  The code sequence within this loop acts as a simple
	   FSM so that if we exit at any point then the next call to this
	   function will resume where we left off */
	iterationCount = 0;
	do
		{
		int segmentCount, status;

		/* If there's no segment information currently available we need to
		   process a segment header before we can handle any data.  The use
		   of a loop is necessary to handle some broken implementations that
		   emit zero-length sub-segments, and as a corollary it also helps
		   avoid a pile of special-case code to manage PGP's strange way of
		   handling the last segment in indefinite-length encodings.  We 
		   limit the segment count to FAILSAFE_ITERATIONS_SMALL sub-segments 
		   to make sure that we don't spend forever trying to process 
		   extremely broken data */
		for( segmentCount = 0; \
			 segmentCount < FAILSAFE_ITERATIONS_SMALL && \
				envelopeInfoPtr->segmentSize <= 0; \
			 segmentCount++ )
			{
			SEGMENT_STATUS segmentStatus;
			int bytesConsumed;

			status = getNextSegment( envelopeInfoPtr, bufPtr, currentLength,
									 &bytesConsumed, &segmentStatus );
			if( status == OK_SPECIAL )
				{
				/* If we've reached the end of the payload, we're done */
				if( segmentStatus == SEGMENT_ENDOFDATA )
					return( length - currentLength );

				/* We got the length via some other mechanism because it's a
				   definite-length or non-segmenting encoding, no input was
				   consumed and we can exit */
				ENSURES( segmentStatus == SEGMENT_FIXEDLENGTH );
				break;
				}
			if( cryptStatusError( status ) )
				return( status );
			if( bytesConsumed <= 0 )
				{
				/* We don't have enough input data left to read the
				   information for the next segment, exit */
				ENSURES( segmentStatus == SEGMENT_INSUFFICIENTDATA );
				ENSURES( sanityCheck( envelopeInfoPtr ) );
				return( length - currentLength );
				}
			bufPtr += bytesConsumed;
			currentLength -= bytesConsumed;

			/* If we've reached the EOC or consumed all of the input data,
			   exit */
			if( ( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) || \
				currentLength <= 0 )
				{
				ENSURES( sanityCheck( envelopeInfoPtr ) );
				return( length - currentLength );
				}
			}
		if( segmentCount >= FAILSAFE_ITERATIONS_SMALL )
			{
			/* We've processed FAILSAFE_ITERATIONS_SMALL consecutive sub-
			   segments in a row, there's something wrong with the input 
			   data */
			return( CRYPT_ERROR_BADDATA );
			}
		ENSURES( currentLength > 0 && currentLength <= length && \
				 currentLength < MAX_INTLENGTH );

		/* Copy the data into the envelope, decrypting it as we go if
		   necessary.  In theory we could also check to see whether any
		   more data can fit into the buffer before trying to copy it in
		   but since this would require knowledge of the internal buffer-
		   handling strategy used by copyData() we always call it and rely
		   on a bytesCopied value of zero to indicate that the tank is
		   full */
		status = copyData( envelopeInfoPtr, bufPtr, currentLength, 
						   &bytesCopied );
		if( cryptStatusError( status ) )
			return( status );
		bufPtr += bytesCopied;
		currentLength -= bytesCopied;

		ENSURES( sanityCheck( envelopeInfoPtr ) );
		ENSURES( currentLength >= 0 && currentLength <= length && \
				 currentLength < MAX_INTLENGTH );

		assert( ( envelopeInfoPtr->segmentSize >= 0 ) || \
				( ( envelopeInfoPtr->dataFlags & ENVDATA_NOSEGMENT ) && \
				  ( envelopeInfoPtr->payloadSize == CRYPT_UNUSED ) && \
				  ( envelopeInfoPtr->segmentSize == CRYPT_UNUSED ) ) );
		}
	while( currentLength > 0 && bytesCopied > 0 && \
		   iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );

	ENSURES( sanityCheck( envelopeInfoPtr ) );
	return( length - currentLength );
	}

/****************************************************************************
*																			*
*								Copy from Envelope							*
*																			*
****************************************************************************/

/* Copy buffered out-of-band data from earlier processing to the output.  
   This is only required for PGP envelopes where we have to burrow down into
   nested content in order to figure out what to do with it */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int copyOobData( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
						OUT_BUFFER( maxLength, *length ) BYTE *buffer, 
						IN_LENGTH const int maxLength, 
						OUT_LENGTH_Z int *length,
						const BOOLEAN retainInBuffer )
	{
	const int oobBytesToCopy = min( maxLength, envelopeInfoPtr->oobBufPos );
	const int oobRemainder = envelopeInfoPtr->oobBufPos - oobBytesToCopy;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isWritePtr( buffer, maxLength ) );
	assert( isWritePtr( length, sizeof( int ) ) );

	REQUIRES( sanityCheck( envelopeInfoPtr ) );
	REQUIRES( maxLength > 0 && maxLength < MAX_INTLENGTH );

	ENSURES( oobBytesToCopy > 0 && \
			 oobBytesToCopy <= envelopeInfoPtr->oobBufPos );
	memcpy( buffer, envelopeInfoPtr->oobBuffer, oobBytesToCopy );
	*length = oobBytesToCopy;

	/* If we're retaining the data in the OOB, we're done */
	if( retainInBuffer )
		{
		ENSURES( sanityCheck( envelopeInfoPtr ) );

		return( CRYPT_OK );
		}

	/* We're moving data out of the OOB buffer, adjust the OOB buffer 
	   contents */
	if( oobRemainder > 0 )
		{
		memmove( envelopeInfoPtr->oobBuffer,
				 envelopeInfoPtr->oobBuffer + oobBytesToCopy, oobRemainder );
		}
	envelopeInfoPtr->oobBufPos = oobRemainder;

	ENSURES( sanityCheck( envelopeInfoPtr ) );

	return( CRYPT_OK );
	}

/* Copy data from the envelope.  Returns the number of bytes copied */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int copyFromDeenvelope( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
							   OUT_BUFFER( maxLength, *length ) BYTE *buffer, 
							   IN_LENGTH const int maxLength, 
							   OUT_LENGTH_Z int *length, 
							   IN_FLAGS( ENVCOPY ) const int flags )
	{
	const BOOLEAN isLookaheadRead = ( flags & ENVCOPY_FLAG_OOBDATA ) ? \
									TRUE : FALSE;
	int bytesToCopy = maxLength, bytesCopied, oobBytesCopied = 0;
	int remainder, status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isWritePtr( buffer, maxLength ) );
	assert( isWritePtr( length, sizeof( int ) ) );

/*///////////////////////////////////////////////////*/
assert( envelopeInfoPtr->segmentSize != CRYPT_UNUSED );
/*///////////////////////////////////////////////////*/

	REQUIRES( sanityCheck( envelopeInfoPtr ) );
	REQUIRES( maxLength > 0 && maxLength < MAX_INTLENGTH );
	REQUIRES( !isLookaheadRead || \
			  ( isLookaheadRead && \
			    ( bytesToCopy > 0 && bytesToCopy <= OOB_BUFFER_SIZE ) ) );
	REQUIRES( flags == ENVCOPY_FLAG_NONE || flags == ENVCOPY_FLAG_OOBDATA );

	/* Clear return values */
	memset( buffer, 0, min( bytesToCopy, 8 ) );
	*length = 0;

	/* If we're verifying a detached signature the data is communicated 
	   out-of-band so there's nothing to copy out (the length is still set
	   to zero from the earlier code */
	if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
		return( CRYPT_OK );

	/* If there's buffered out-of-band data from an earlier lookahead read 
	   present, insert it into the output stream */
	if( envelopeInfoPtr->oobBufPos > 0 )
		{
		status = copyOobData( envelopeInfoPtr, buffer, bytesToCopy, 
							  &oobBytesCopied, isLookaheadRead );
		if( cryptStatusError( status ) )
			return( status );
		bytesToCopy -= oobBytesCopied;
		buffer += oobBytesCopied;
		if( bytesToCopy <= 0 )
			{
			*length = oobBytesCopied;

			ENSURES( sanityCheck( envelopeInfoPtr ) );
			return( CRYPT_OK );
			}
		}
	ENSURES( bytesToCopy > 0 && bytesToCopy <= maxLength && \
			 bytesToCopy < MAX_INTLENGTH );

	/* If we're using compression, expand the data from the buffer to the
	   output via the zStream */
#ifdef USE_COMPRESSION
	if( envelopeInfoPtr->flags & ENVELOPE_ZSTREAMINITED )
		{
		const int originalInLength = bytesToCopy;
		const int bytesIn = \
			( envelopeInfoPtr->dataLeft > 0 && \
			  envelopeInfoPtr->dataLeft < envelopeInfoPtr->bufPos ) ? \
			envelopeInfoPtr->dataLeft : envelopeInfoPtr->bufPos;

		/* Decompress the data into the output buffer.  Note that we use the
		   length value to determine the length of the output rather than
		   bytesToCopy since the ratio of bytes in the buffer to bytes of
		   output isn't 1:1 as it is for other content types.

		   When using PGP 2.x-compatible decompression we have to allow a
		   return status of Z_BUF_ERROR because it uses a compression format
		   from a pre-release version of InfoZip that doesn't include
		   header or trailer information so the decompression code can't
		   definitely tell that it's reached the end of its input data but
		   can only report that it can't go any further.

		   When we're trying to suck all remaining compressed data from the 
		   zstream we may get a (rather misleadingly named) Z_BUF_ERROR if 
		   there's both no internally buffered data left and no new input 
		   available to produce any output.  If this is the case we simply
		   treat it as a nothing-copied condition, since decompression will
		   continue when the user provides more input.

		   We can also get a Z_BUF_ERROR for some types of (non-fatal) error
		   situations, for example if we're flushing out data still present
		   in the zstream (avail_in == 0) and there's a problem such as the
		   compressor needing more data but there's none available, the zlib
		   code will report it as a Z_BUF_ERROR.  In this case we convert it
		   into a (recoverable) underflow error, which isn't always accurate
		   but is more useful than the generic CRYPT_ERROR_FAILED */
		envelopeInfoPtr->zStream.next_in = envelopeInfoPtr->buffer;
		envelopeInfoPtr->zStream.avail_in = bytesIn;
		envelopeInfoPtr->zStream.next_out = buffer;
		envelopeInfoPtr->zStream.avail_out = bytesToCopy;
		status = inflate( &envelopeInfoPtr->zStream, Z_SYNC_FLUSH );
		if( status != Z_OK && status != Z_STREAM_END && \
			!( status == Z_BUF_ERROR && \
			   envelopeInfoPtr->type == CRYPT_FORMAT_PGP ) && \
			!( status == Z_BUF_ERROR && bytesIn == 0 ) )

⌨️ 快捷键说明

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