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

📄 decode.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
			{
			ENSURES( status != Z_STREAM_ERROR );	/* Parameter error */
			return( ( status == Z_DATA_ERROR ) ? CRYPT_ERROR_BADDATA : \
					( status == Z_MEM_ERROR ) ? CRYPT_ERROR_MEMORY : \
					( status == Z_BUF_ERROR ) ? CRYPT_ERROR_UNDERFLOW : \
					CRYPT_ERROR_FAILED );
			}

		/* Adjust the status information based on the data copied from the
		   buffer into the zStream (bytesCopied) and the data flushed from
		   the zStream to the output (bytesToCopy) */
		bytesCopied = bytesIn - envelopeInfoPtr->zStream.avail_in;
		bytesToCopy -= envelopeInfoPtr->zStream.avail_out;
		ENSURES( bytesCopied >= 0 && bytesCopied < MAX_INTLENGTH && \
				 bytesToCopy >= 0 && bytesToCopy <= originalInLength && \
				 bytesToCopy < MAX_INTLENGTH );

#if 0	/* 7/6/07 This check doesn't seem to serve any useful purpose since 
		   EOCs are handled at a higher level.  In particular the check for 
		   a single pair of EOCs produces false positives when there's a 
		   string of EOCs present at the end of the data.  This code goes 
		   back to at least 3.0 while the EOC handling has changed a fair 
		   bit since then so it's likely that it's an artefact from much 
		   older code */
		/* If we consumed all of the input and there's extra data left after
		   the end of the data stream, it's EOC information, mark that as
		   consumed as well */
		if( envelopeInfoPtr->zStream.avail_in <= 0 && \
			envelopeInfoPtr->dataLeft > 0 && \
			envelopeInfoPtr->dataLeft < envelopeInfoPtr->bufPos )
			{
			if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP && \
				( !( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) || \
				  ( envelopeInfoPtr->bufPos - envelopeInfoPtr->dataLeft != 2 ) ) )
				{
				/* We should only have the EOC octets { 0x00 0x00 } present
				   at this point */
				retIntError();
				}
			envelopeInfoPtr->dataLeft = envelopeInfoPtr->bufPos;
			}
#endif /* 0 */

		/* If we're doing a lookahead read we can't just copy the data out 
		   of the envelope buffer as we would for any other content type 
		   because we can't undo the decompression step, so we copy the data 
		   that was decompressed into the output buffer to a local buffer 
		   and insert it into the output stream on the next non-lookahead 
		   read.  The size of the read from the OOB buffer has been limited
		   previously when existing data was detected in the OOB buffer so 
		   the total of the current OOB buffer contents and the amount to 
		   read can never exceed the OOB buffer size */
		if( isLookaheadRead )
			{
			REQUIRES( envelopeInfoPtr->oobBufPos + \
					  originalInLength <= OOB_BUFFER_SIZE );

			memcpy( envelopeInfoPtr->oobBuffer + envelopeInfoPtr->oobBufPos,
					buffer, originalInLength );
			envelopeInfoPtr->oobBufPos += originalInLength;
			}
		}
	else
#endif /* USE_COMPRESSION */
		{
		/* Copy out as much of the data as we can, making sure that we don't
		   overrun into any following data */
		if( bytesToCopy > envelopeInfoPtr->bufPos )
			bytesToCopy = envelopeInfoPtr->bufPos;
		if( envelopeInfoPtr->dataLeft > 0 && \
			bytesToCopy > envelopeInfoPtr->dataLeft )
			bytesToCopy = envelopeInfoPtr->dataLeft;
		ENSURES( bytesToCopy >= 0 && bytesToCopy <= maxLength && \
				 bytesToCopy < MAX_INTLENGTH );

		/* We perform the postcondition check here because there are 
		   numerous exit points in the following code and this avoids having 
		   to check at every one */
		ENSURES( sanityCheck( envelopeInfoPtr ) );

		/* If we're using a block encryption mode and we haven't seen the
		   end-of-contents yet and there's no data waiting in the block
		   buffer (which would mean that there's more data to come), we
		   can't copy out the last block because it might contain padding,
		   so we decrease the effective data amount by one block's worth */
		if( envelopeInfoPtr->blockSize > 1 && \
			!( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) && \
			envelopeInfoPtr->blockBufferPos > 0 )
			bytesToCopy -= envelopeInfoPtr->blockSize;

		/* If we've ended up with nothing to copy (e.g. due to blocking
		   requirements), exit */
		if( bytesToCopy <= 0 )
			{
			*length = oobBytesCopied;
			return( CRYPT_OK );
			}
		ENSURES( bytesToCopy > 0 && bytesToCopy < MAX_INTLENGTH );

		/* If we've seen the end-of-contents octets and there's no payload
		   left to copy out, exit */
		if( ( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) && \
			envelopeInfoPtr->dataLeft <= 0 )
			{
			*length = oobBytesCopied;
			return( CRYPT_OK );
			}

		/* If we're doing a lookahead read just copy the data out without
		   adjusting the read-data values */
		if( isLookaheadRead )
			{
			REQUIRES( bytesToCopy > 0 && bytesToCopy <= OOB_BUFFER_SIZE );

			memcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );
			*length = bytesToCopy;
			return( CRYPT_OK );
			}

		/* Hash the payload data if necessary */
		if( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE )
			{
			status = hashEnvelopeData( envelopeInfoPtr->actionList,
									   envelopeInfoPtr->buffer, 
									   bytesToCopy );
			if( cryptStatusError( status ) )
				return( status );
			}

		/* We're not using compression, copy the data across directly */
		memcpy( buffer, envelopeInfoPtr->buffer, bytesToCopy );
		bytesCopied = bytesToCopy;
		}
	ENSURES( envelopeInfoPtr->bufPos - bytesCopied >= 0 );

	/* Move any remaining data down to the start of the buffer  */
	remainder = envelopeInfoPtr->bufPos - bytesCopied;
	ENSURES( remainder >= 0 && remainder < MAX_INTLENGTH && \
			 bytesCopied >= 0 && bytesCopied < MAX_INTLENGTH && \
			 bytesCopied + remainder <= envelopeInfoPtr->bufSize );
	if( remainder > 0 && bytesCopied > 0 )
		{
		memmove( envelopeInfoPtr->buffer, 
				 envelopeInfoPtr->buffer + bytesCopied, remainder );
		}
	envelopeInfoPtr->bufPos = remainder;

	/* If there's data following the payload, adjust the end-of-payload
	   pointer to reflect the data that we've just copied out */
	if( envelopeInfoPtr->dataLeft > 0 && bytesCopied > 0 )
		envelopeInfoPtr->dataLeft -= bytesCopied;
	ENSURES( envelopeInfoPtr->dataLeft >= 0 && \
			 envelopeInfoPtr->dataLeft < MAX_INTLENGTH );
	*length = oobBytesCopied + bytesToCopy;

	ENSURES( sanityCheck( envelopeInfoPtr ) );
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Extra Data Management Functions						*
*																			*
****************************************************************************/

/* Synchronise the deenveloping data stream */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int syncDeenvelopeData( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							   INOUT STREAM *stream )
	{
	const long dataStartPos = stell( stream );
	const int oldBufPos = envelopeInfoPtr->bufPos;
	const int bytesLeft = sMemDataLeft( stream );
	int bytesCopied;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isWritePtr( stream, sizeof( STREAM ) ) );

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

	REQUIRES( sanityCheck( envelopeInfoPtr ) );
	REQUIRES( !cryptStatusError( dataStartPos ) );

	/* After the envelope header has been processed, what's left is payload
	   data that requires special processing because of segmenting and
	   decryption and hashing requirements, so we feed it in via a
	   copyToDeenvelope() of the data in the buffer.  This is a rather ugly
	   hack, but it works because we're moving data backwards in the buffer
	   so there shouldn't be any problems for the rare instances where the
	   data overlaps.  In the worst case (PKCS #7/CMS short definite-length
	   OCTET STRING) we only consume two bytes, the tag and one-byte length,
	   but since we're using memmove() in copyData() this shouldn't be a
	   problem.

	   Since we're in effect restarting from the payload data, we reset
	   everything that counts to point back to the start of the buffer where
	   we'll be moving the payload data.  We don't have to worry about the
	   copyToDeenvelope() overflowing the envelope since the source is the
	   envelope buffer so the data must fit within the envelope */
	envelopeInfoPtr->bufPos = 0;
	if( bytesLeft <= 0 )
		{
		/* Handle the special case of the data ending at exactly this point */
		sseek( stream, 0 );
		return( CRYPT_ERROR_UNDERFLOW );
		}
	sMemDisconnect( stream );
	sMemConnect( stream, envelopeInfoPtr->buffer, bytesLeft );
	bytesCopied = envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
							envelopeInfoPtr->buffer + dataStartPos, bytesLeft );
	if( cryptStatusError( bytesCopied ) )
		{
		/* Undo the buffer position reset.  This isn't 100% effective if
		   there are multiple segments present and we hit an error after
		   we've copied down enough data to overwrite what's at the start,
		   but in most cases it allows us to undo the copyToEnvelope(), and 
		   if the data is corrupted we won't be able to get any further 
		   anyway */
		envelopeInfoPtr->bufPos = oldBufPos;
		ENSURES( sanityCheck( envelopeInfoPtr ) );
		return( bytesCopied );
		}
	ENSURES( bytesCopied >= 0 && bytesCopied < MAX_INTLENGTH );

	/* If we copied over less than the total available and have hit the
	   end-of-data marker it means that there's extra data following the
	   payload.  We need to move this down to the end of the decoded payload 
	   data since copyToDeenvelope() stops copying as soon as it hits the 
	   end-of-data.  We use memmove() rather than memcpy() for this since 
	   we're copying to/from the same buffer:

				  dataStartPos
						|
						v<--- bLeft --->|
		+---------------+---------------+--------
		|				|///////////////|			Start
		+---------------+---------------+--------

				  dataStartPos
						|
		|<- bCop -->|	v		|<-bToC>|
		+---------------+---------------+--------
		|//payload//|	|		|///////|			After copyToDeenvelope
		+---------------+---------------+--------
					^			^
					|			|
				dataLeft  dStartPos + bCopied

		+-----------+-------+--------------------
		|//payload//|///////|						EOC
		+-----------+-------+--------------------
					^		^
					|		|
				 dLeft	  bufPos */
	if( ( envelopeInfoPtr->dataFlags & ENVDATA_ENDOFCONTENTS ) && \
		bytesCopied < bytesLeft )
		{
		const int bytesToCopy = bytesLeft - bytesCopied;

		REQUIRES( bytesToCopy > 0 && bytesToCopy < MAX_INTLENGTH && \
				  envelopeInfoPtr->dataLeft + \
						bytesToCopy <= envelopeInfoPtr->bufSize && \
				  bytesCopied + dataStartPos + \
						bytesToCopy <= envelopeInfoPtr->bufSize );

		memmove( envelopeInfoPtr->buffer + envelopeInfoPtr->dataLeft,
				 envelopeInfoPtr->buffer + dataStartPos + bytesCopied,
				 bytesToCopy );
		envelopeInfoPtr->bufPos = envelopeInfoPtr->dataLeft + bytesToCopy;
		}

	ENSURES( sanityCheck( envelopeInfoPtr ) );
	return( CRYPT_OK );
	}

/* Process additional out-of-band data that doesn't get copied into/out of
   the de-enveloping envelope */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processExtraData( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							 IN_BUFFER( length ) const void *buffer, 
							 IN_LENGTH const int length )
	{
	int status;

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

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

	/* If the hash value was supplied externally (which means that there's
	   nothing for us to hash since it's already been done by the caller),
	   there won't be any hash actions active and we can return immediately */
	if( !( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE ) )
		return( ( length > 0 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );

	/* Hash the data or wrap up the hashing as appropriate */
	status = hashEnvelopeData( envelopeInfoPtr->actionList, buffer, length );
	if( cryptStatusError( status ) )
		return( status );

	/* If we've finished the hashing, clear the hashing-active flag to
	   prevent data from being hashed again if it's processed by other
	   code such as copyFromDeenvelope() */
	if( length <= 0 )
		envelopeInfoPtr->dataFlags &= ~ENVDATA_HASHACTIONSACTIVE;

	return( CRYPT_OK );
	}

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

STDC_NONNULL_ARG( ( 1 ) ) \
void initDeenvelopeStreaming( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	envelopeInfoPtr->copyToEnvelopeFunction = copyToDeenvelope;
	envelopeInfoPtr->copyFromEnvelopeFunction = copyFromDeenvelope;
	envelopeInfoPtr->syncDeenvelopeData = syncDeenvelopeData;
	envelopeInfoPtr->processExtraData = processExtraData;
	}
#endif /* USE_ENVELOPES */

⌨️ 快捷键说明

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