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

📄 res_actn.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						cryptlib Envelope Action Management					*
*						Copyright Peter Gutmann 1996-2008					*
*																			*
****************************************************************************/

#if defined( INC_ALL )
  #include "envelope.h"
#else
  #include "envelope/envelope.h"
#endif /* Compiler-specific includes */

/* The maximum number of actions that we can add to an action list */

#define MAX_ACTIONS		FAILSAFE_ITERATIONS_MED - 1

#ifdef USE_ENVELOPES

/****************************************************************************
*																			*
*								Find an Action								*
*																			*
****************************************************************************/

/* Find an action of a given type and the last action of a given type.
   Since the lists are sorted by action type, the generic findAction()
   finds the start of an action group.
   
   The casting to a non-const is a bit ugly but is necessitated by the fact 
   that while the functions don't change the action list entries, the caller 
   will */

CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
ACTION_LIST *findAction( const ACTION_LIST *actionListPtr,
						 IN_ENUM( ACTION ) const ACTION_TYPE actionType )
	{
	int iterationCount;
	
	assert( actionListPtr == NULL || \
			isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );

	REQUIRES_N( actionType == ACTION_KEYEXCHANGE || \
				actionType == ACTION_KEYEXCHANGE_PKC || \
				actionType == ACTION_SIGN || \
				actionType == ACTION_HASH || \
				actionType == ACTION_MAC || \
				actionType == ACTION_CRYPT );

	for( iterationCount = 0;
		 actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
		 actionListPtr = actionListPtr->next, iterationCount++ )
		{
		if( actionListPtr->action == actionType )
			return( ( ACTION_LIST * ) actionListPtr );
		}
	ENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( NULL );
	}

CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1 ) ) \
ACTION_LIST *findLastAction( const ACTION_LIST *actionListPtr,
							 IN_ENUM( ACTION ) const ACTION_TYPE actionType )
	{
	int iterationCount;

	assert( actionListPtr == NULL || \
			isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );

	REQUIRES_N( actionType == ACTION_KEYEXCHANGE || \
				actionType == ACTION_KEYEXCHANGE_PKC || \
				actionType == ACTION_SIGN || \
				actionType == ACTION_HASH || \
				actionType == ACTION_MAC || \
				actionType == ACTION_CRYPT );

	/* Find the start of the action group */
	actionListPtr = findAction( actionListPtr, actionType );
	if( actionListPtr == NULL )
		return( NULL );

	/* Find the end of the action group */
	for( iterationCount = 0;
		 actionListPtr->next != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 actionListPtr = actionListPtr->next, iterationCount++ )
		{
		if( actionListPtr->next->action != actionType )
			break;
		}
	ENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( ( ACTION_LIST * ) actionListPtr );
	}

/* An indirect action-check function that uses a caller-supplied callback to 
   verify a match for an action */

CHECK_RETVAL_PTR STDC_NONNULL_ARG( ( 1, 2 ) ) \
ACTION_LIST *findActionIndirect( const ACTION_LIST *actionListStart,
								 IN CHECKACTIONFUNCTION checkActionFunction,
								 IN_INT_Z const int intParam )
	{
	const ACTION_LIST *actionListPtr;
	int iterationCount;

	assert( isReadPtr( actionListStart, sizeof( ACTION_LIST ) ) );

	REQUIRES_N( checkActionFunction != NULL );

	for( actionListPtr = actionListStart, iterationCount = 0;
		 actionListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED; 
		 actionListPtr = actionListPtr->next, iterationCount++ )
		 {
		 const int status = checkActionFunction( actionListPtr, intParam );
		 if( cryptStatusOK( status ) )
			return( ( ACTION_LIST * ) actionListPtr );
		 }
	ENSURES_N( iterationCount < FAILSAFE_ITERATIONS_MED );

	return( NULL );
	}

/****************************************************************************
*																			*
*								Add/Delete an Action						*
*																			*
****************************************************************************/

/* Check whether more actions can be added to an action list */

CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
BOOLEAN moreActionsPossible( const ACTION_LIST *actionListPtr )
	{
	int actionCount;

	assert( actionListPtr == NULL || \
			isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );

	for( actionCount = 0;
		 actionListPtr != NULL && actionCount < FAILSAFE_ITERATIONS_MED;
		 actionListPtr = actionListPtr->next, actionCount++ );
	ENSURES_B( actionCount < FAILSAFE_ITERATIONS_MED );

	return( ( actionCount < MAX_ACTIONS ) ? TRUE : FALSE );
	}

/* Add a new action to the end of an action group in an action list */

CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 3 ) ) \
static int createNewAction( OUT_OPT_PTR ACTION_LIST **newActionPtrPtr,
							OUT_PTR ACTION_LIST **actionListHeadPtrPtr,
							INOUT MEMPOOL_STATE memPoolState,
							IN_ENUM( ACTION ) const ACTION_TYPE actionType,
							IN_HANDLE const CRYPT_HANDLE cryptHandle )							
	{
	ACTION_LIST *actionListPtr, *prevActionPtr = NULL;
	ACTION_LIST *newItem;
	int iterationCount;

	assert( newActionPtrPtr == NULL || \
			isWritePtr( newActionPtrPtr, sizeof( ACTION_LIST * ) ) );
	assert( isWritePtr( actionListHeadPtrPtr, sizeof( ACTION_LIST * ) ) );
	assert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );

	REQUIRES( actionType == ACTION_KEYEXCHANGE || \
			  actionType == ACTION_KEYEXCHANGE_PKC || \
			  actionType == ACTION_SIGN || \
			  actionType == ACTION_HASH || \
			  actionType == ACTION_MAC || \
			  actionType == ACTION_CRYPT );
	REQUIRES( isHandleRangeValid( cryptHandle ) );

	/* Clear return value */
	if( newActionPtrPtr != NULL )
		*newActionPtrPtr = NULL;

	/* Create the new action list item */
	if( ( newItem = getMemPool( memPoolState, \
								sizeof( ACTION_LIST ) ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( newItem, 0, sizeof( ACTION_LIST ) );
	newItem->action = actionType;
	newItem->iCryptHandle = cryptHandle;
	newItem->iExtraData = CRYPT_ERROR;
	newItem->iTspSession = CRYPT_ERROR;

	/* Find the last action in the action group */
	for( actionListPtr = *actionListHeadPtrPtr, iterationCount = 0;
		 actionListPtr != NULL && actionListPtr->action <= actionType && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 actionListPtr = actionListPtr->next, iterationCount++ )
		{
		prevActionPtr = actionListPtr;
		}
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );

	/* Append the new action */
#if 0	/* 1/4/08 Changed to use insertSingleListElement() */
	if( prevActionPtr == NULL )
		*actionListHeadPtrPtr = newItem;
	else
		prevActionPtr->next = newItem;
	newItem->next = actionListPtr;
#else
	insertSingleListElement( actionListHeadPtrPtr, prevActionPtr, newItem );
#endif /* 0 */
	if( newActionPtrPtr != NULL )
		*newActionPtrPtr = newItem;

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
int addActionEx( OUT_PTR ACTION_LIST **newActionPtrPtr,
				 OUT_PTR ACTION_LIST **actionListHeadPtrPtr,
				 INOUT MEMPOOL_STATE memPoolState,
				 IN_ENUM( ACTION ) const ACTION_TYPE actionType,
				 IN_HANDLE const CRYPT_HANDLE cryptHandle )
	{
	assert( isWritePtr( newActionPtrPtr, sizeof( ACTION_LIST * ) ) );
		/* Rest are checked in createNewAction() */

	return( createNewAction( newActionPtrPtr, actionListHeadPtrPtr, 
							 memPoolState, actionType, cryptHandle ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int addAction( OUT_PTR ACTION_LIST **actionListHeadPtrPtr,
			   INOUT MEMPOOL_STATE memPoolState,
			   IN_ENUM( ACTION ) const ACTION_TYPE actionType,
			   IN_HANDLE const CRYPT_HANDLE cryptHandle )
	{
	return( createNewAction( NULL, actionListHeadPtrPtr, memPoolState, 
							 actionType, cryptHandle ) );
	}

/* Delete an action from an action list */

STDC_NONNULL_ARG( ( 1, 2 ) ) \
static void deleteActionListItem( INOUT MEMPOOL_STATE memPoolState,
								  INOUT ACTION_LIST *actionListItem )
	{
	assert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );
	assert( isWritePtr( actionListItem, sizeof( ACTION_LIST ) ) );

	/* Destroy any attached objects and information if necessary and
	   clear the list item memory */
	if( actionListItem->iCryptHandle != CRYPT_ERROR )
		krnlSendNotifier( actionListItem->iCryptHandle, IMESSAGE_DECREFCOUNT );
	if( actionListItem->iExtraData != CRYPT_ERROR )
		krnlSendNotifier( actionListItem->iExtraData, IMESSAGE_DECREFCOUNT );
	if( actionListItem->iTspSession != CRYPT_ERROR )
		krnlSendNotifier( actionListItem->iTspSession, IMESSAGE_DECREFCOUNT );
	zeroise( actionListItem, sizeof( ACTION_LIST ) );
	freeMemPool( memPoolState, actionListItem );
	}

STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
void deleteAction( INOUT_PTR ACTION_LIST **actionListHeadPtrPtr, 
				   INOUT MEMPOOL_STATE memPoolState,	
				   INOUT ACTION_LIST *actionListItem )
	{
	ACTION_LIST *listPrevPtr;
	int iterationCount;

	assert( isWritePtr( actionListHeadPtrPtr, sizeof( ACTION_LIST * ) ) );
	assert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );
	assert( isWritePtr( actionListItem, sizeof( ACTION_LIST ) ) );

	REQUIRES_V( *actionListHeadPtrPtr != NULL );
	REQUIRES_V( actionListItem != NULL );
				/* Without this explicit assertion static analysers may 
				   assume that deleteSingleListElement() will dereference a 
				   NULL pointer */

	/* Find the previons entry in the list */
	for( listPrevPtr = *actionListHeadPtrPtr, iterationCount = 0;
		 listPrevPtr != NULL && listPrevPtr->next != actionListItem && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 listPrevPtr = listPrevPtr->next, iterationCount++ );
	ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_MED );

	/* Remove the item from the list */
	deleteSingleListElement( actionListHeadPtrPtr, listPrevPtr, 
							 actionListItem );

	/* Clear all data in the list item and free the memory */
	deleteActionListItem( memPoolState, actionListItem );
	}

/* Delete an action list */

STDC_NONNULL_ARG( ( 1, 2 ) ) \
void deleteActionList( INOUT MEMPOOL_STATE memPoolState,
					   INOUT ACTION_LIST *actionListPtr )
	{
	int iterationCount;

	assert( isWritePtr( memPoolState, sizeof( MEMPOOL_STATE ) ) );
	assert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );

	for( iterationCount = 0;
		 actionListPtr != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 iterationCount++ )
		{
		ACTION_LIST *actionListItem = actionListPtr;

		actionListPtr = actionListPtr->next;
		deleteActionListItem( memPoolState, actionListItem );
		}
	ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_MED );
	}

/* Delete any orphaned actions, for example automatically-added hash actions
   that were overridden by user-supplied alternate actions */

STDC_NONNULL_ARG( ( 1 ) ) \
void deleteUnusedActions( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	ACTION_LIST *actionListPtr;
	int iterationCount;

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

	/* Check for unattached hash/MAC or encryption actions and delete them */
	for( actionListPtr = envelopeInfoPtr->actionList, iterationCount = 0;
		 actionListPtr != NULL && \
			iterationCount < FAILSAFE_ITERATIONS_MED;
		 iterationCount++ )
		{
		ACTION_LIST *actionListCurrent = actionListPtr;

		actionListPtr = actionListPtr->next;
		if( ( actionListCurrent->action == ACTION_HASH || \
			  actionListCurrent->action == ACTION_MAC || \
			  actionListCurrent->action == ACTION_CRYPT ) && \
			( actionListCurrent->flags & ACTION_NEEDSCONTROLLER ) )
			{
			deleteAction( &envelopeInfoPtr->actionList,
						  envelopeInfoPtr->memPoolState, actionListCurrent );
			}
		}
	ENSURES_V( iterationCount < FAILSAFE_ITERATIONS_MED );
	}

/****************************************************************************
*																			*
*								Check an Action								*
*																			*
****************************************************************************/

/* Check a new action to make sure that it isn't already present in the
   action list, producing an ACTION_RESULT outcome */

CHECK_RETVAL_ENUM( ACTION ) STDC_NONNULL_ARG( ( 1 ) ) \
ACTION_RESULT checkAction( const ACTION_LIST *actionListStart,
						   IN_ENUM( ACTION ) const ACTION_TYPE actionType, 
						   IN_HANDLE const CRYPT_HANDLE cryptHandle )
	{
	ACTION_LIST *actionListPtr = ( ACTION_LIST * ) actionListStart;
	MESSAGE_DATA msgData;
	BYTE keyID[ KEYID_SIZE + 8 ];
	CRYPT_ALGO_TYPE cryptAlgo = DUMMY_INIT;
	int iterationCount, status;

	assert( actionListPtr == NULL || \
			isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );

	REQUIRES_EXT( ( actionType == ACTION_KEYEXCHANGE || \
					actionType == ACTION_KEYEXCHANGE_PKC || \
					actionType == ACTION_SIGN || \
					actionType == ACTION_HASH || \
					actionType == ACTION_MAC || \
					actionType == ACTION_CRYPT ), ACTION_RESULT_ERROR );
	REQUIRES_EXT( isHandleRangeValid( cryptHandle ), ACTION_RESULT_ERROR );

	/* If the action list is empty, there's nothing to check */
	if( actionListPtr == NULL )
		return( ACTION_RESULT_EMPTY );

	/* Get identification information for the action object */
	switch( actionType )
		{
		case ACTION_KEYEXCHANGE:
			/* For conventional key wrap we can't really do much, for raw
			   action objects we'd check the algorithm for duplicates but
			   it's perfectly valid to wrap a single session/MAC key using
			   multiple key wrap objects with the same algorithm */
			status = CRYPT_OK;
			break;

⌨️ 快捷键说明

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