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

📄 cms_denv.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
			envelopeInfoPtr->usage = ACTION_CRYPT;
			*state = DEENVSTATE_SET_ENCR;
			break;

		case ACTION_CRYPT:
			envelopeInfoPtr->usage = ACTION_CRYPT;
			*state = DEENVSTATE_ENCRCONTENT;
			break;

		case ACTION_SIGN:
			envelopeInfoPtr->usage = ACTION_SIGN;
			*state = DEENVSTATE_SET_HASH;
			break;

		case ACTION_MAC:
			/* MACd envelopes have key exchange information at the start 
			   just like ACTION_KEYEXCHANGE but the later processing is 
			   different, so we treat them as a special case here */
			envelopeInfoPtr->usage = ACTION_MAC;
			*state = DEENVSTATE_SET_ENCR;
			break;

		case ACTION_COMPRESS:
			/* With compressed data all that we need to do is check that the 
			   fixed AlgorithmIdentifier is present and set up the 
			   decompression stream, after which we go straight to the 
			   content */
			status = readGenericAlgoID( stream, OID_ZLIB, 
										sizeofOID( OID_ZLIB ) ); 
			if( cryptStatusError( status ) )
				return( status );
			envelopeInfoPtr->usage = ACTION_COMPRESS;
#ifdef USE_COMPRESSION
			if( inflateInit( &envelopeInfoPtr->zStream ) != Z_OK )
				return( CRYPT_ERROR_MEMORY );
			envelopeInfoPtr->flags |= ENVELOPE_ZSTREAMINITED;
			*state = DEENVSTATE_CONTENT;
#else
			return( CRYPT_ERROR_NOTAVAIL );
#endif /* USE_COMPRESSION */
			break;

		case ACTION_NONE:
			/* Since we're going straight to the data payload there's no 
			   nested content type so we explicitly set it to "data" */
			envelopeInfoPtr->contentType = CRYPT_CONTENT_DATA;
			*state = DEENVSTATE_DATA;
			break;

		default:
			retIntError();
		}

	return( CRYPT_OK );
	}

/* Process the encrypted content header */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processEncryptionHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
									INOUT STREAM *stream )
	{
	QUERY_INFO queryInfo;
	int status;

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

	/* Read the encrypted content header */
	status = readCMSencrHeader( stream, nestedContentOIDinfo, 
						FAILSAFE_ARRAYSIZE( nestedContentOIDinfo, OID_INFO ),
						NULL, &queryInfo );
	if( cryptStatusError( status ) )
		return( status );
	envelopeInfoPtr->contentType = status;
	envelopeInfoPtr->payloadSize = queryInfo.size;

	/* We've reached encrypted data, we can't go any further until we can 
	   either recover the session key from a key exchange object or are fed 
	   the session key directly */
	if( envelopeInfoPtr->actionList == NULL )
		{
		int dummy;

		/* Since the content can be indefinite-length we clear the size 
		   field to give it a sensible setting */
		queryInfo.size = 0;
		return( addContentListItem( envelopeInfoPtr, NULL, &queryInfo, 
									&dummy ) );
		}
	REQUIRES( envelopeInfoPtr->actionList != NULL && \
			  envelopeInfoPtr->actionList->action == ACTION_CRYPT );

	/* If the session key was recovered from a key exchange action but we 
	   ran out of input data before we could read the encryptedContent info 
	   it'll be present in the action list so we use it to set things up for 
	   the decryption.  This can only happen if the caller pushes in just 
	   enough data to get past the key exchange actions but not enough to 
	   recover the encryptedContent info and then pushes in a key exchange 
	   action in response to the CRYPT_ERROR_UNDERFLOW error */
	return( initEnvelopeEncryption( envelopeInfoPtr,
							envelopeInfoPtr->actionList->iCryptHandle,
							queryInfo.cryptAlgo, queryInfo.cryptMode,
							queryInfo.iv, queryInfo.ivLength,
							FALSE ) );
	}

/* Process the hash object header */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processHashHeader( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
							  INOUT STREAM *stream )
	{
	CRYPT_ALGO_TYPE hashAlgo = DUMMY_INIT;
	CRYPT_CONTEXT iHashContext;
	ACTION_LIST *actionListPtr;
	int iterationCount, status;

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

	/* Create the hash object from the data */
	status = readContextAlgoID( stream, &iHashContext, NULL, DEFAULT_TAG );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
								  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) )
		return( status );

	/* Check whether an identical hash action is already present either 
	   through being supplied externally or from a duplicate entry in the 
	   set */
	for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
		 actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED; 
		 actionListPtr = actionListPtr->next, iterationCount++ )
		{
		CRYPT_ALGO_TYPE actionHashAlgo;

		status = krnlSendMessage( actionListPtr->iCryptHandle,
								  IMESSAGE_GETATTRIBUTE, &actionHashAlgo, 
								  CRYPT_CTXINFO_ALGO );
		if( cryptStatusOK( status ) && actionHashAlgo == hashAlgo )
			{
			/* There's a duplicate action present, destroy the one that 
			   we've just created and continue */
			krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
			return( CRYPT_OK );
			}
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );

	/* We didn't find any duplicates, append the new hash action to the 
	   action list and remember that hashing is now active */
	status = addAction( &envelopeInfoPtr->actionList, 
						envelopeInfoPtr->memPoolState, 
						( envelopeInfoPtr->usage == ACTION_MAC ) ? \
							ACTION_MAC : ACTION_HASH, iHashContext );
	if( cryptStatusError( status ) )
		return( status );
	envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;
	
	ENSURES( envelopeInfoPtr->actionList != NULL && \
			 ( envelopeInfoPtr->actionList->action == ACTION_HASH || \
			   envelopeInfoPtr->actionList->action == ACTION_MAC ) );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Trailer Processing Routines						*
*																			*
****************************************************************************/

/* Process EOCs that separate the payload from the trailer */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int processPayloadEOCs( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
							   INOUT STREAM *stream )
	{
	int status;

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

	/* If the payload has an indefinite-length encoding, make sure that the
	   required EOCs are present */
	if( envelopeInfoPtr->payloadSize == CRYPT_UNUSED )
		{
		if( ( status = checkEOC( stream ) ) != TRUE || \
			( status = checkEOC( stream ) ) != TRUE )
			{
			return( cryptStatusError( status ) ? \
					status : CRYPT_ERROR_BADDATA );
			}

		return( CRYPT_OK );
		}

	/* If the data was encoded using a mixture of definite and indefinite 
	   encoding there may be EOC's present even though the length is known 
	   so we skip them if necessary */
	if( ( status = checkEOC( stream ) ) == TRUE )
		status = checkEOC( stream );
	if( cryptStatusError( status ) )
		return( status );

	return( CRYPT_OK );
	}

/* Complete processing of the authenticated payload */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int completePayloadProcessing( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	/* 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 
	   deblocking and whatnot, so we hash it before we wrap up the 
	   hashing */
	if( envelopeInfoPtr->dataLeft > 0 )
		{
		int status;

		status = envelopeInfoPtr->processExtraData( envelopeInfoPtr,
													envelopeInfoPtr->buffer,
													envelopeInfoPtr->dataLeft );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Wrap up the hashing */
	return( envelopeInfoPtr->processExtraData( envelopeInfoPtr, "", 0 ) );
	}

/* Process the signed data trailer */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int processSignedTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
								 INOUT STREAM *stream, 
								 INOUT_ENUM( DEENV_STATE ) DEENV_STATE *state )
	{
	DEENV_STATE newState;
	int tag, status;

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

	/* Read the SignedData EOC's if necessary */
	status = processPayloadEOCs( envelopeInfoPtr, stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Check whether there's a certificate chain to follow */
	tag = peekTag( stream );
	if( cryptStatusError( tag ) )
		return( tag );
	newState = ( tag == MAKE_CTAG( 0 ) ) ? \
			   DEENVSTATE_CERTSET : DEENVSTATE_SET_SIG;

	/* If we've seen all of the signed data complete the hashing */
	if( !( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
		{
		status = completePayloadProcessing( envelopeInfoPtr );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Move on to the next state */
	*state = newState;
	return( CRYPT_OK );
	}

/* Process the MACd data trailer */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
static int processMacTrailer( INOUT ENVELOPE_INFO *envelopeInfoPtr, 
							  INOUT STREAM *stream, 
							  OUT_BOOL BOOLEAN *failedMAC )
	{
	MESSAGE_DATA msgData;
	BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
	int hashSize, status;

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

	/* Clear return value */
	*failedMAC = FALSE;

	/* Read the AuthenticatedData EOC's if necessary */
	status = processPayloadEOCs( envelopeInfoPtr, stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Read the MAC value that follows the payload */
	status = readOctetString( stream, hash, &hashSize, 16, 
							  CRYPT_MAX_HASHSIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Complete the payload processing and compare the read MAC value with 
	   the calculated one */
	status = completePayloadProcessing( envelopeInfoPtr );
	if( cryptStatusError( status ) )
		return( status );
	setMessageData( &msgData, hash, hashSize );
	status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle, 
							  IMESSAGE_COMPARE, &msgData, 
							  MESSAGE_COMPARE_HASH );
	if( cryptStatusError( status ) )
		{
		/* Unlike signatures a failed MAC check (reported as a CRYPT_ERROR
		   comparison result) is detected immediately rather than after the
		   payload processing has completed.  However if we bail out now 
		   then any later checks of things like signature metadata will fail 
		   because the envelope regards processing as still being incomplete 
		   so we have to continue processing data until we at least get the 
		   envelope to the finished state */
		assert( status == CRYPT_ERROR );
		*failedMAC = TRUE;
		}

	return( CRYPT_OK );
	}

/* Process any remaining EOCs.  This gets a bit complicated because there 
   can be a variable number of EOCs depending on where definite and 
   indefinite encodings were used so we look for at least one EOC and at 
   most a number that depends on the data type being processed */

⌨️ 快捷键说明

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