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

📄 resource.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*																			*
*					cryptlib Enveloping Information Management				*
*						Copyright Peter Gutmann 1996-2002					*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "asn1.h"
  #include "asn1oid.h"
  #include "envelope.h"
  #include "pgp.h"
#elif defined( INC_CHILD )
  #include "../keymgmt/asn1.h"
  #include "../keymgmt/asn1oid.h"
  #include "../envelope/envelope.h"
  #include "../envelope/pgp.h"
#else
  #include "keymgmt/asn1.h"
  #include "keymgmt/asn1oid.h"
  #include "envelope/envelope.h"
  #include "envelope/pgp.h"
#endif /* Compiler-specific includes */

/****************************************************************************
*																			*
*					Functions for Action and Content Lists					*
*																			*
****************************************************************************/

/* Create a new action */

static ACTION_LIST *createAction( const ACTION_TYPE actionType,
								  const CRYPT_HANDLE cryptHandle )
	{
	ACTION_LIST *actionListItem;

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

	return( actionListItem );
	}

/* 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 */

ACTION_LIST *findAction( ACTION_LIST *actionListPtr,
						 const ACTION_TYPE actionType )
	{
	while( actionListPtr != NULL )
		{
		if( actionListPtr->action == actionType )
			return( actionListPtr );
		actionListPtr = actionListPtr->next;
		}

	return( NULL );
	}

ACTION_LIST *findLastAction( ACTION_LIST *actionListPtr,
							 const ACTION_TYPE actionType )
	{
	ACTION_LIST *prevActionPtr;

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

	/* Find the end of the action group */
	prevActionPtr = actionListPtr;
	while( actionListPtr != NULL )
		{
		if( actionListPtr->action != actionType )
			break;
		prevActionPtr = actionListPtr;
		actionListPtr = actionListPtr->next;
		}
	return( prevActionPtr );
	}

/* Check a new action to make sure it isn't already present in the action 
   list, producing one of the following outcomes.  The two 'action present' 
   results are for the case where the action is already present and 
   shouldn't be added again, and where the action is present from being 
   added as an (invisible to the user) side-effect of another action being 
   added, so that this attempt to add it should be reported as CRYPT_OK 
   rather than CRYPT_INITED */

typedef enum {
	ACTION_RESULT_OK,				/* Action not present, can be added */
	ACTION_RESULT_EMPTY,			/* Action list is empty */
	ACTION_RESULT_INITED,			/* Action present (CRYPT_INITED) */
	ACTION_RESULT_PRESENT			/* Action present (CRYPT_OK) */
	} ACTION_RESULT;

static ACTION_RESULT checkAction( const ACTION_LIST *actionListStart,
								  const ACTION_TYPE actionType, 
								  const CRYPT_HANDLE cryptHandle )
	{
	ACTION_LIST *actionListPtr = ( ACTION_LIST * ) actionListStart;
	BYTE keyID[ KEYID_SIZE ];
	int cryptAlgo, status;

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

	/* 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.  For a hash/
	   MAC/session key object we get the algorithm, for a PKC object 
	   (signature or key exchange) we get the key ID */
	if( actionType == ACTION_HASH || actionType == ACTION_MAC || \
		actionType == ACTION_CRYPT )
		status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE,
								  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	else
		if( actionType != ACTION_KEYEXCHANGE )
			{
			RESOURCE_DATA msgData;

			assert( actionType == ACTION_KEYEXCHANGE_PKC || \
					actionType == ACTION_SIGN );

			setResourceData( &msgData, keyID, KEYID_SIZE );
			status = krnlSendMessage( cryptHandle, 
									  RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
									  &msgData, CRYPT_IATTRIBUTE_KEYID );
			}
	if( cryptStatusError( status ) )
		return( CRYPT_ARGERROR_NUM1 );

	/* Walk down the list from the first to the last action in the action 
	   group, checking each in turn */
	for( actionListPtr = findAction( actionListPtr, actionType );
		 actionListPtr != NULL && actionListPtr->action == actionType;
		 actionListPtr = actionListPtr->next )
		{
		RESOURCE_DATA msgData;
		BOOLEAN isDuplicate = FALSE;

		/* Make sure we haven't added this action already.  This can get
		   a bit tricky both because detecting some types of duplicates is
		   rather hard and because the definition of what's an invalid
		   duplicate varies somewhat.  For a hash, MAC, and encryption
		   action, we only allow one action of a given algorithm type to
		   be added.  For a PKC key exchange or signature action we only 
		   allow one action for a given key to be added.  For a conventional
		   key exchange action we should in theory check for duplicates in
		   some form but it's not certain what constitutes a duplicate (for
		   example are two otherwise identical actions with a different 
		   number of key setup iterations considered duplicates or not?) so 
		   for now we assume the user won't do anything silly (in any case 
		   for any key exchange action the only thing a duplicate will do is 
		   result in unnecessary bloating in the envelope header) */
		if( actionType == ACTION_HASH || actionType == ACTION_MAC || \
			actionType == ACTION_CRYPT )
			{
			int actionAlgo;

			/* It's a hash/MAC or session key object, compare the two
			   objects by comparing their algorithms */
			if( cryptStatusOK( \
					krnlSendMessage( actionListPtr->iCryptHandle, 
									 RESOURCE_IMESSAGE_GETATTRIBUTE,
									 &actionAlgo, CRYPT_CTXINFO_ALGO ) ) && \
				actionAlgo == cryptAlgo )
				isDuplicate = TRUE;
			}
		else
			{
			/* It's a PKC key exchange or signature action, compare the two 
			   objects by comparing their keys */
			setResourceData( &msgData, keyID, KEYID_SIZE );
			if( cryptStatusOK( \
					krnlSendMessage( actionListPtr->iCryptHandle, 
									 RESOURCE_IMESSAGE_COMPARE, &msgData, 
									 RESOURCE_MESSAGE_COMPARE_KEYID ) ) )
				isDuplicate = TRUE;
			}
		if( isDuplicate )
			{
			/* If the action was added automatically as the result of adding 
			   another action then the first attempt to add it by the caller 
			   isn't an error */
			if( actionListPtr->addedAutomatically )
				{
				actionListPtr->addedAutomatically = FALSE;
				return( ACTION_RESULT_PRESENT );
				}

			return( ACTION_RESULT_INITED );
			}
		}

	return( ACTION_RESULT_OK );
	}

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

ACTION_LIST *addAction( ACTION_LIST **actionListHeadPtrPtr,
						const ACTION_TYPE actionType,
						const CRYPT_HANDLE cryptHandle )
	{
	ACTION_LIST *actionListPtr = *actionListHeadPtrPtr, *prevActionPtr = NULL;
	ACTION_LIST *actionListItem;

	/* Create a new action and */
	actionListItem = createAction( actionType, 
								   ( cryptHandle == CRYPT_UNUSED ) ? \
								   CRYPT_ERROR : cryptHandle );
	if( actionListItem == NULL )
		return( NULL );

	/* Find the last action in the action group and append the new action */
	while( actionListPtr != NULL && actionListPtr->action <= actionType )
		{
		prevActionPtr = actionListPtr;
		actionListPtr = actionListPtr->next;
		}
	if( prevActionPtr == NULL )
		*actionListHeadPtrPtr = actionListItem;
	else
		prevActionPtr->next = actionListItem;
	actionListItem->next = actionListPtr;

	return( actionListItem );
	}

/* Delete an action from an action list */

static void deleteActionListItem( ACTION_LIST *actionListItem )
	{
	/* Destroy any attached objects and information if necessary and 
	   clear the list item memory */
	if( actionListItem->iCryptHandle != CRYPT_ERROR )
		krnlSendNotifier( actionListItem->iCryptHandle,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
	if( actionListItem->iExtraData != CRYPT_ERROR )
		krnlSendNotifier( actionListItem->iExtraData,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
	if( actionListItem->iTspSession != CRYPT_ERROR )
		krnlSendNotifier( actionListItem->iTspSession,
						  RESOURCE_IMESSAGE_DECREFCOUNT );
	zeroise( actionListItem, sizeof( ACTION_LIST ) );
	free( actionListItem );
	}

void deleteAction( ACTION_LIST **actionListHead, 
				   ACTION_LIST *actionListItem )
	{
	ACTION_LIST *listPrevPtr;

	for( listPrevPtr = *actionListHead; 
		 listPrevPtr != NULL && listPrevPtr->next != actionListItem; 
		 listPrevPtr = listPrevPtr->next );

	/* Remove the item from the list */
	if( actionListItem == *actionListHead )
		/* Delete from start */
		*actionListHead = actionListItem->next;
	else
		/* Delete from middle or end */
		listPrevPtr->next = actionListItem->next;

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

/* Delete an action list */

void deleteActionList( ACTION_LIST *actionListPtr )
	{
	while( actionListPtr != NULL )
		{
		ACTION_LIST *actionListItem = actionListPtr;

		actionListPtr = actionListPtr->next;
		deleteActionListItem( actionListItem );
		}
	}

/* Create a content list item */

void initContentListItem( CONTENT_LIST *contentListItem )
	{
	memset( contentListItem, 0, sizeof( CONTENT_LIST ) );
	contentListItem->iSigCheckKey = CRYPT_ERROR;
	contentListItem->iExtraData = CRYPT_ERROR;
	}

CONTENT_LIST *createContentListItem( const CRYPT_FORMAT_TYPE formatType,
									 const void *object, const int objectSize )
	{
	CONTENT_LIST *contentListItem;

	if( ( contentListItem = malloc( sizeof( CONTENT_LIST ) ) ) == NULL )
		return( NULL );
	initContentListItem( contentListItem );
	contentListItem->formatType = formatType;
	contentListItem->object = ( void * ) object;
	contentListItem->objectSize = objectSize;

	return( contentListItem );
	}

/* Add an item to the content list */

void appendContentListItem( ENVELOPE_INFO *envelopeInfoPtr,
							const CONTENT_LIST *contentListItem )
	{
	CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentList;

	if( envelopeInfoPtr->contentList == NULL )
		{
		envelopeInfoPtr->contentList = ( CONTENT_LIST * ) contentListItem;
		return;
		}

	/* Find the end of the list and add the new item */
	while( contentListPtr->next != NULL )
		contentListPtr = contentListPtr->next;
	contentListPtr->next = ( CONTENT_LIST * ) contentListItem;
	}

/* Delete a content list */

void deleteContentList( CONTENT_LIST *contentListPtr )
	{
	while( contentListPtr != NULL )
		{
		CONTENT_LIST *contentListItem = contentListPtr;

		/* Destroy any attached objects if necessary */
		if( contentListItem->iSigCheckKey != CRYPT_ERROR )
			krnlSendNotifier( contentListItem->iSigCheckKey,
							  RESOURCE_IMESSAGE_DECREFCOUNT );
		if( contentListItem->iExtraData != CRYPT_ERROR )
			krnlSendNotifier( contentListItem->iExtraData,
							  RESOURCE_IMESSAGE_DECREFCOUNT );

		/* Erase and free the object buffer if necessary */
		contentListPtr = contentListPtr->next;
		if( contentListItem->object != NULL )
			{
			zeroise( contentListItem->object, contentListItem->objectSize );
			free( contentListItem->object );
			}
		zeroise( contentListItem, sizeof( CONTENT_LIST ) );
		free( contentListItem );
		}
	}

/* Delete any orphaned actions (for example automatically added hash actions 
   which were overridden with user-supplied alternate actions) */

void deleteUnusedActions( ENVELOPE_INFO *envelopeInfoPtr )
	{
	ACTION_LIST *actionListPtr = envelopeInfoPtr->actionList;

	/* Check for unattached hash/MAC or encryption actions and delete them */
	while( actionListPtr != NULL )
		{
		ACTION_LIST *actionListCurrent = actionListPtr;

		actionListPtr = actionListPtr->next;
		if( ( actionListCurrent->action == ACTION_HASH || \
			  actionListCurrent->action == ACTION_MAC || \
			  actionListCurrent->action == ACTION_CRYPT ) && \

⌨️ 快捷键说明

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