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

📄 cryptenv.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
			envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
			}
#endif /* USE_PGP */
		}

	/* If we're past the main data-processing state, process the postamble */
	if( envelopeInfoPtr->state == STATE_POSTDATA )
		{
		/* Since we're processing trailer information, just copy it in
		   directly */
		if( bytesIn > 0 )
			{
			const int bytesToCopy = min( envelopeInfoPtr->bufSize - \
										 envelopeInfoPtr->bufPos, bytesIn );

			ENSURES( bytesToCopy >= 0 && bytesToCopy <= bytesIn && \
					 envelopeInfoPtr->bufPos + \
						bytesToCopy <= envelopeInfoPtr->bufSize );
			if( bytesToCopy > 0 )
				{
				memcpy( envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos,
						bufPtr, bytesToCopy );
				envelopeInfoPtr->bufPos += bytesToCopy;
				*bytesCopied += bytesToCopy;
				}
			}

		/* Process the postamble.  During this processing we can encounter 
		   two special types of recoverable error, CRYPT_ERROR_UNDERFLOW (we 
		   need more data to continue) or OK_SPECIAL (we processed all of 
		   the data but there's out-of-band information still to go), if 
		   it's one of these then we don't treat it as a standard error */
		status = envelopeInfoPtr->processPostambleFunction( envelopeInfoPtr );
		if( cryptStatusError( status ) && status != OK_SPECIAL )
			{
			if( !isRecoverableError( status ) )
				{
				envelopeInfoPtr->errorState = status;

				/* MACd envelopes differ somewhat from signed envelopes in 
				   that the integrity check results are available 
				   immediately that payload processing is complete rather
				   than afterwards as the result of user action with 
				   signature metadata.  As a result the postamble 
				   processing can return a CRYPT_ERROR_SIGNATURE to indicate
				   that although all data was processed successfully (which
				   would normally produce a CRYPT_OK result) the integrity 
				   check for the data failed.  To reconcile the two status
				   values we treat the envelope as if a CRYPT_OK had been
				   returned (by marking processing as being complete) while 
				   recording a CRYPT_ERROR_SIGNATURE.  However we do return
				   the signature error since the user may be using 
				   authenticated encryption and not even be aware that they
				   should perform an explicit check for a signature 
				   failure */
				if( status == CRYPT_ERROR_SIGNATURE && \
					envelopeInfoPtr->usage == ACTION_MAC )
					envelopeInfoPtr->state = STATE_FINISHED;
				}
			return( status );
			}
		ENSURES( status == CRYPT_OK || status == OK_SPECIAL );

		/* If the postamble processing routine returns OK_SPECIAL then it's 
		   processed enough of the postamble for the caller to continue, but 
		   there's more to go so we shouldn't change the overall state yet */
		if( status == CRYPT_OK )
			{
			/* We've processed all data, we're done unless it's a detached
			   sig with the data supplied out-of-band */
			envelopeInfoPtr->state = \
					( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) ? \
					STATE_EXTRADATA : STATE_FINISHED;
			}

		/* At this point we always exit since the out-of-band data has to be
		   processed in a separate push */
		return( CRYPT_OK );
		}

	/* If there's extra out-of-band data present, process it separately.  
	   This is slightly complicated by the fact that the single envelope is
	   being used to process two independent lots of data, so we have to be 
	   careful to distinguish between handling of the main payload data and 
	   handling of this additional out-of-band data */
	if( envelopeInfoPtr->state == STATE_EXTRADATA )
		{
		/* We pass this point twice, the first time round we check the state 
		   and if it's DEENVSTATE_DONE (set when processing of the main data 
		   was completed) we reset it to DEENVSTATE_NONE and make sure that 
		   it's a flush */
		if( envelopeInfoPtr->deenvState == DEENVSTATE_DONE )
			{
			/* We've finished with the main payload data, reset the state for 
			   the additional out-of-band data.  Normally we exit here since 
			   it's a flush, however if the hash value was supplied 
			   externally (which means that hashing was never active, since 
			   it was done by the caller) we drop through to the wrap-up, 
			   since there's no second flush of payload data to be performed 
			   and so the flush applies to both sets of data */
			envelopeInfoPtr->deenvState = DEENVSTATE_NONE;
			if( envelopeInfoPtr->dataFlags & ENVDATA_HASHACTIONSACTIVE )
				return( length ? CRYPT_ERROR_BADDATA : CRYPT_OK );
			}

		/* This is just raw additional data so we feed it directly to the 
		   processing function.  If this is a flush then the buffer will be
		   set to NULL which the low-level routines don't allow so we 
		   substitute an empty buffer */
		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr, 
							( buffer == NULL ) ? "" : buffer, length );
		if( cryptStatusOK( status ) )
			{
			*bytesCopied = length;
			if( length <= 0 )
				envelopeInfoPtr->state = STATE_FINISHED;
			}
		}

	return( status );
	}

/* Pop data from an envelope */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int envelopePop( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
						OUT_BUFFER( length, *bytesCopied ) void *buffer,
						IN_LENGTH const int length, 
						OUT_LENGTH_Z int *bytesCopied )
	{
	int status;

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

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

	/* Clear return value */
	*bytesCopied = 0;

	/* Copy the data from the envelope to the output */
	status = envelopeInfoPtr->copyFromEnvelopeFunction( envelopeInfoPtr, 
														buffer, length, 
														bytesCopied,
														ENVCOPY_FLAG_NONE );
	if( cryptStatusError( status ) )
		envelopeInfoPtr->errorState = status;
	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
static int deenvelopePop( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
						  OUT_BUFFER( length, *bytesCopied ) void *buffer,
						  IN_LENGTH const int length, 
						  OUT_LENGTH_Z int *bytesCopied )
	{
	int status;

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

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

	/* Clear return value */
	*bytesCopied = 0;

	/* If we haven't reached the data yet force a flush to try and get to 
	   it.  We can end up with this condition if the caller pushes in 
	   deenveloping information and then immediately tries to pop data 
	   without an intervening flush (or implicit flush on the initial push) to 
	   resolve the state of the data in the envelope */
	if( envelopeInfoPtr->state == STATE_PREDATA )
		{
		int dummy;

		status = deenvelopePush( envelopeInfoPtr, NULL, 0, &dummy );
		if( cryptStatusError( status ) )
			return( status );

		/* If we still haven't got anywhere return an underflow error */
		if( envelopeInfoPtr->state == STATE_PREDATA )
			return( CRYPT_ERROR_UNDERFLOW );
		}

	/* Copy the data from the envelope to the output */
	status = envelopeInfoPtr->copyFromEnvelopeFunction( envelopeInfoPtr, 
														buffer, length, 
														bytesCopied,
														ENVCOPY_FLAG_NONE );
	if( cryptStatusError( status ) && !isRecoverableError( status ) )
		envelopeInfoPtr->errorState = status;
	return( status );
	}

/****************************************************************************
*																			*
*								Envelope Message Handler					*
*																			*
****************************************************************************/

/* Handle a message sent to an envelope */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int envelopeMessageFunction( INOUT TYPECAST( ENVELOPE_INFO * ) \
										void *objectInfoPtr,
									IN_MESSAGE const MESSAGE_TYPE message,
									void *messageDataPtr,
									IN_INT_Z const int messageValue )
	{
	ENVELOPE_INFO *envelopeInfoPtr = ( ENVELOPE_INFO * ) objectInfoPtr;

	assert( isWritePtr( objectInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
	REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH );

	/* Process destroy object messages */
	if( message == MESSAGE_DESTROY )
		{
		int status = CRYPT_OK;

		/* Check to see whether the envelope still needs operations performed
		   on it to resolve the state of the data within it (for example if
		   the caller pushes data but doesn't flush it, there will be a few
		   bytes left that can't be popped).  For enveloping, destroying the 
		   envelope while it's in any state other than STATE_PREDATA or 
		   STATE_FINISHED is regarded as an error.  For de-enveloping we have 
		   to be more careful since deenveloping information required to 
		   resolve the envelope state could be unavailable so we shouldn't 
		   return an error if something like a signature check remains to be 
		   done.  What we therefore do is check to see whether we've processed 
		   any data yet and report an error if there's data left in the 
		   envelope or if we're destroying it in the middle of processing 
		   data */
		if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
			{
			/* If we've got to the point of processing data in the envelope
			   and there's either more to come or some left to pop, we
			   shouldn't be destroying it yet.  The one exception occurs 
			   when we're MACing data and the integrity checks fails, in
			   which case the integrity-check-failed status prevents the
			   user from popping the (corrupted) data and so there may be
			   data left in the envelope */
			if( envelopeInfoPtr->state == STATE_DATA )
				status = CRYPT_ERROR_INCOMPLETE;
			if( ( envelopeInfoPtr->state == STATE_POSTDATA || \
				  envelopeInfoPtr->state == STATE_FINISHED ) && \
				envelopeInfoPtr->dataLeft > 0 && \
				( !( envelopeInfoPtr->usage == ACTION_MAC && \
					 envelopeInfoPtr->errorState == CRYPT_ERROR_SIGNATURE ) ) )
				status = CRYPT_ERROR_INCOMPLETE;
			}
		else
			{
			/* If we're in the middle of processing data we shouldn't be
			   destroying the envelope yet */
			if( envelopeInfoPtr->state != STATE_PREDATA && \
				envelopeInfoPtr->state != STATE_FINISHED )
				status = CRYPT_ERROR_INCOMPLETE;
			}

		/* Delete the action and content lists */
		if( envelopeInfoPtr->preActionList != NULL )
			deleteActionList( envelopeInfoPtr->memPoolState, 
							  envelopeInfoPtr->preActionList );
		if( envelopeInfoPtr->actionList != NULL )
			deleteActionList( envelopeInfoPtr->memPoolState, 
							  envelopeInfoPtr->actionList );
		if( envelopeInfoPtr->postActionList != NULL )
			deleteActionList( envelopeInfoPtr->memPoolState, 
							  envelopeInfoPtr->postActionList );
		if( envelopeInfoPtr->contentList != NULL )
			deleteContentList( envelopeInfoPtr->memPoolState, 
							   &envelopeInfoPtr->contentList );

#ifdef USE_COMPRESSION
		/* Delete the zlib compression state information if necessary */
		if( envelopeInfoPtr->flags & ENVELOPE_ZSTREAMINITED )
			{
			if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
				inflateEnd( &envelopeInfoPtr->zStream );
			else
				deflateEnd( &envelopeInfoPtr->zStream );
			}
#endif /* USE_COMPRESSION */

		/* Clean up keysets */
		if( envelopeInfoPtr->iSigCheckKeyset != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iSigCheckKeyset,
							  IMESSAGE_DECREFCOUNT );
		if( envelopeInfoPtr->iEncryptionKeyset != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iEncryptionKeyset,
							  IMESSAGE_DECREFCOUNT );
		if( envelopeInfoPtr->iDecryptionKeyset != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iDecryptionKeyset,
							  IMESSAGE_DECREFCOUNT );

		/* Clean up other envelope objects */
		if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
			krnlSendNotifier( envelopeInfoPtr->iExtraCertChain,
							  IMESSAGE_DECREFCOUNT );

		/* Clear and free the buffers if necessary */
		if( envelopeInfoPtr->buffer != NULL )

⌨️ 快捷键说明

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