📄 res_actn.c
字号:
/****************************************************************************
* *
* 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 + -