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

📄 resource.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
			  envelopeInfoPtr->actionList != NULL ) )
			  return( CRYPT_ERROR_INITED );

		/* Create the appropriate encryption context.  We have to be careful 
		   to ensure that we use an algorithm which is compatible with the 
		   wrapping mechanism.  We don't have to perform this check if the
		   format type is PGP since PGP wrapping always uses CFB mode (so
		   there are no modes that need to be avoided) and the higher-level
		   code has constrained the algorithm type to something which is 
		   encodable using the PGP data format */
		if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP && \
			( isStreamCipher( cryptAlgo ) || \
			  cryptStatusError( sizeofAlgoIDex( cryptAlgo,
									( CRYPT_ALGO_TYPE ) CRYPT_MODE_CBC, 0 ) ) ) )
			cryptAlgo = CRYPT_ALGO_3DES;
		setMessageCreateObjectInfo( &createInfo, cryptAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );

		/* Derive the key into the context and add it to the action list */
#ifdef USE_PGP
		if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
			{
			RESOURCE_DATA msgData;
			BYTE salt[ PGP_SALTSIZE ];
			static const CRYPT_MODE_TYPE mode = CRYPT_MODE_CFB;

			/* PGP uses CFB mode for everything so we change the mode from 
			   the default of CBC to CFB */
			krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE, 
							 ( void * ) &mode, CRYPT_CTXINFO_MODE );

			/* Generate a salt, derive the key into the context, and insert 
			   it into the action list.  Since PGP doesn't perform a key 
			   exchange of a session key, we insert the password-derived 
			   context directly into the main action list */
			setMessageData( &msgData, salt, PGP_SALTSIZE );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
									  IMESSAGE_GETATTRIBUTE_S, &msgData, 
									  CRYPT_IATTRIBUTE_RANDOM_NONCE );
			if( cryptStatusOK( status ) )
				status = pgpPasswordToKey( createInfo.cryptHandle, 
										   value, valueLength, 
										   envelopeInfoPtr->defaultHash, 
										   salt, PGP_ITERATIONS );
			if( cryptStatusOK( status ) && \
				addAction( &envelopeInfoPtr->actionList, 
						   envelopeInfoPtr->memPoolState, ACTION_CRYPT, 
						   createInfo.cryptHandle ) == NULL )
				status = CRYPT_ERROR_MEMORY;
			}
		else
#endif /* USE_PGP */
			{
			RESOURCE_DATA msgData;

			setMessageData( &msgData, ( void * ) value, valueLength );
			status = krnlSendMessage( createInfo.cryptHandle, 
									  IMESSAGE_SETATTRIBUTE_S, &msgData,
									  CRYPT_CTXINFO_KEYING_VALUE );
			if( cryptStatusOK( status ) )
				{
				/* Make sure that this key exchange action isn't already 
				   present and insert it into the list */
				if( checkAction( envelopeInfoPtr->preActionList, 
								 ACTION_KEYEXCHANGE, 
								 createInfo.cryptHandle ) == ACTION_RESULT_INITED )
					status = CRYPT_ERROR_INITED;
				else
					if( addAction( &envelopeInfoPtr->preActionList, 
								   envelopeInfoPtr->memPoolState, 
								   ACTION_KEYEXCHANGE, 
								   createInfo.cryptHandle ) == NULL )
						status = CRYPT_ERROR_MEMORY;
				}
			}
		if( cryptStatusError( status ) )
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* It's a generic "add a context" action, check that everything is valid.  
	   This is necessary because the PGP format doesn't support the full 
	   range of enveloping capabilities */
	if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
		{
		/* PGP doesn't support both PKC and conventional key exchange 
		   actions in the same envelope since the session key is encrypted
		   for the PKC action but derived from the password for the 
		   conventional action */
		if( findAction( envelopeInfoPtr->preActionList,
						ACTION_KEYEXCHANGE ) != NULL )
			return( CRYPT_ERROR_INITED );

		/* PGP handles multiple signers by nesting signed data rather than
		   attaching multiple signatures, so we can only apply a single
		   signature per envelope */
		if( envInfo == CRYPT_ENVINFO_SIGNATURE && \
			envelopeInfoPtr->postActionList != NULL )
			return( CRYPT_ERROR_INITED );

		/* PGP doesn't allow multiple hash algorithms to be used when signing
		   data (a follow-on from the way nested sigs are handled) */
		if( envInfo == CRYPT_ENVINFO_HASH && \
			envelopeInfoPtr->actionList != NULL )
			return( CRYPT_ERROR_INITED );
		}
	switch( envInfo )
		{
		case CRYPT_ENVINFO_PUBLICKEY:
		case CRYPT_ENVINFO_PRIVATEKEY:
			actionListHeadPtrPtr = &envelopeInfoPtr->preActionList;
			actionType = ACTION_KEYEXCHANGE_PKC;
			break;

		case CRYPT_ENVINFO_KEY:
			/* PGP doesn't allow KEK-based encryption, so if it's a PGP 
			   envelope we drop through and treat it as a session key */
			if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP )
				{
				actionListHeadPtrPtr = &envelopeInfoPtr->preActionList;
				actionType = ACTION_KEYEXCHANGE;
				break;
				}

		case CRYPT_ENVINFO_SESSIONKEY:
			/* We can't add more than one session key */
			if( envelopeInfoPtr->actionList != NULL )
				return( CRYPT_ERROR_INITED );
			actionListHeadPtrPtr = &envelopeInfoPtr->actionList;
			actionType = ACTION_CRYPT;

#ifdef USE_FORTEZZA
			/* If there's originator info present, make sure that it's 
			   consistent with the new session key */
			if( envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR )
				{
				status = checkFortezzaUsage( cryptHandle, envelopeInfoPtr, 
											 CRYPT_ENVINFO_SESSIONKEY );
				if( cryptStatusError( status ) )
					return( status );
				}
#endif /* USE_FORTEZZA */
			break;

		case CRYPT_ENVINFO_HASH:
			actionListHeadPtrPtr = &envelopeInfoPtr->actionList;
			actionType = ACTION_HASH;
			break;

		case CRYPT_ENVINFO_SIGNATURE:
			actionListHeadPtrPtr = &envelopeInfoPtr->postActionList;
			actionType = ACTION_SIGN;
			break;

		default:
			assert( NOTREACHED );
			return( CRYPT_ARGERROR_NUM1 );
		}

	/* Find the insertion point for this action and make sure that it isn't
	   already present.  The difference between an inited and present return
	   code is that an inited response indicates that the user explicitly 
	   added the action and can't add it again while a present response
	   indicates that the action was added automatically by cryptlib in
	   response to the user adding some other action and shouldn't be 
	   reported as an error, to the user it doesn't make any difference
	   whether the same action was added automatically by cryptlib or
	   explicitly */
	actionResult = checkAction( *actionListHeadPtrPtr, actionType, cryptHandle );
	if( actionResult == ACTION_RESULT_INITED )
		return( CRYPT_ERROR_INITED );
	if( actionResult == ACTION_RESULT_PRESENT )
		return( CRYPT_OK );

	/* Insert the action into the list.  If it's a non-idempotent context 
	   (i.e. one whose state can change based on user actions), we clone it 
	   for our own use, otherwise we just increment its reference count */
	if( actionType == ACTION_HASH || actionType == ACTION_CRYPT )
		{
		CRYPT_ALGO_TYPE cryptAlgo;
		MESSAGE_CREATEOBJECT_INFO createInfo;

		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, 
								  &cryptAlgo, CRYPT_CTXINFO_ALGO );
		if( cryptStatusOK( status ) )
			{
			setMessageCreateObjectInfo( &createInfo, cryptAlgo );
			status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
									  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
									  OBJECT_TYPE_CONTEXT );
			}
		if( cryptStatusError( status ) )
			return( status );
		status = krnlSendMessage( cryptHandle, IMESSAGE_CLONE, NULL, 
								  createInfo.cryptHandle );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			return( status );
			}
		cryptHandle = createInfo.cryptHandle;
		}
	else
		status = krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT );
	actionListPtr = addAction( actionListHeadPtrPtr, 
							   envelopeInfoPtr->memPoolState, actionType, 
							   cryptHandle );
	if( actionListPtr == NULL )
		{
		krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
		return( CRYPT_ERROR_MEMORY );
		}
	if( actionType == ACTION_HASH )
		/* Remember that we need to hook the hash action up to a signature
		   action before we start enveloping data */
		actionListPtr->flags |= ACTION_NEEDSCONTROLLER;

	/* If the newly-inserted action isn't a controlling action, we're done */
	if( actionType != ACTION_SIGN )
		return( status );

	/* If there's no subject hash action available, create one so we can 
	   connect it to the signature action */
	if( envelopeInfoPtr->actionList == NULL )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Create a default hash action */
		setMessageCreateObjectInfo( &createInfo, envelopeInfoPtr->defaultHash );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo, 
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );

		/* Add the hash action to the list */
		hashActionPtr = addAction( &envelopeInfoPtr->actionList, 
								   envelopeInfoPtr->memPoolState, ACTION_HASH, 
								   createInfo.cryptHandle );
		if( hashActionPtr == NULL )
			{
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			return( CRYPT_ERROR_MEMORY );
			}

		/* Remember that the action was added invisibly to the caller so that 
		   we don't return an error if they add it as well */
		hashActionPtr->flags |= ACTION_ADDEDAUTOMATICALLY;
		}
	else
		/* Find the last hash action that was added */
		hashActionPtr = findLastAction( envelopeInfoPtr->actionList, 
										ACTION_HASH );

	/* Connect the signature action to the last hash action that was added 
	   and remember that this action now has a controlling action */
	actionListPtr->associatedAction = hashActionPtr;
	hashActionPtr->flags &= ~ACTION_NEEDSCONTROLLER;

	return( CRYPT_OK );
	}

/* Check the consistency of envelope resources */

static CRYPT_ATTRIBUTE_TYPE checkMissingInfo( ENVELOPE_INFO *envelopeInfoPtr )
	{
	ACTION_LIST *actionListPtr;
	BOOLEAN needsSigAction = FALSE;

	/* If there are signature-related options present (signature envelope,
	   detached-sig flag set, hash context present, or CMS attributes or a 
	   TSA session present), there must be a signing key also present */
	for( actionListPtr = envelopeInfoPtr->postActionList;
		 actionListPtr != NULL; actionListPtr = actionListPtr->next )
		if( actionListPtr->iExtraData != CRYPT_ERROR || \
			actionListPtr->iTspSession != CRYPT_ERROR )
			{
			needsSigAction = TRUE;
			break;
			}
	if( ( envelopeInfoPtr->usage == ACTION_SIGN || \
		  envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG || \
		  findAction( envelopeInfoPtr->actionList, ACTION_HASH ) != NULL || \
		  needsSigAction ) && \
		findAction( envelopeInfoPtr->postActionList, ACTION_SIGN ) == NULL )
		return( CRYPT_ENVINFO_SIGNATURE );

	/* If it's a MAC envelope, there must be at least one key exchange action 
	   present.  A few obscure operations may set the usage without setting a 
	   key exchange action, for example making the envelope a MAC envelope 
	   simply indicates that any future key exchange actions should be used 
	   for MAC'ing rather than encryption */
	if( envelopeInfoPtr->usage == ACTION_MAC && \
		findAction( envelopeInfoPtr->preActionList, \
					ACTION_KEYEXCHANGE_PKC ) == NULL && \
		findAction( envelopeInfoPtr->preActionList, \
					ACTION_KEYEXCHANGE ) == NULL )
		/* We return the most generic CRYPT_ENVINFO_KEY error code, since 
		   there are several possible missing attribute types that could
		   be required */
		return( CRYPT_ENVINFO_KEY );

	/* If it's an encryption envelope, there must be a key present at some 
	   level.  This situation doesn't normally occur since the higher-level 
	   code will only set the usage to encryption once a key exchange action 
	   has been added, but we check anyway just to be safe */
	if( envelopeInfoPtr->usage == ACTION_CRYPT && \
		findAction( envelopeInfoPtr->preActionList, \
					ACTION_KEYEXCHANGE_PKC ) == NULL && \
		findAction( envelopeInfoPtr->preActionList, \
					ACTION_KEYEXCHANGE ) == NULL && \
		findAction( envelopeInfoPtr->actionList, ACTION_CRYPT ) == NULL )
		return( CRYPT_ENVINFO_KEY );

	/* If there's an originator present, there must be a matching public-key
	   action present */
	if( envelopeInfoPtr->usage == ACTION_CRYPT && \
		envelopeInfoPtr->iExtraCertChain != CRYPT_ERROR && \
		findAction( envelopeInfoPtr->preActionList, 
					ACTION_KEYEXCHANGE_PKC ) == NULL )
		return( CRYPT_ENVINFO_PUBLICKEY );

	return( CRYPT_ATTRIBUTE_NONE );
	}

/****************************************************************************
*																			*
*							Envelope Access Routines						*
*																			*
****************************************************************************/

void initResourceHandling( ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	if( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE )
		envelopeInfoPtr->addInfo = addDeenvelopeInfo;
	else
		{
		envelopeInfoPtr->addInfo = addEnvelopeInfo;
		envelopeInfoPtr->checkMissingInfo = checkMissingInfo;
		}
	}

⌨️ 快捷键说明

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