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

📄 resource.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
			actionListCurrent->needsController )
			deleteAction( &envelopeInfoPtr->actionList, actionListCurrent );
		}
	}

/* Check that the actions in an envelope are consistent.  This is a complex
   function which is called from an assert() macro, so we only need to define
   it when we're building a debug version */

#ifndef NDEBUG

BOOLEAN actionsOK( ENVELOPE_INFO *envelopeInfoPtr )
	{
	ACTION_LIST *actionListPtr = envelopeInfoPtr->actionList;

	/* The permitted action combinations are key exchange + crypt/MAC, 
	   sign + hash, crypt, or none, make sure this is the case */
	if( envelopeInfoPtr->preActionList != NULL )
		{
		/* Key exchange must be followed by crypt or MAC action */
		if( actionListPtr == NULL )
			return( FALSE );
		while( actionListPtr != NULL )
			{
			if( actionListPtr->action != ACTION_CRYPT && \
				actionListPtr->action != ACTION_MAC )
				return( FALSE );
			actionListPtr = actionListPtr->next;
			}
		if( envelopeInfoPtr->postActionList != NULL )
			return( FALSE );
		}
	else
		if( envelopeInfoPtr->postActionList != NULL )
			{
			/* Signature must be preceded by hash action */
			if( actionListPtr == NULL )
				return( FALSE );
			while( actionListPtr != NULL )
				{
				if( actionListPtr->action != ACTION_HASH )
					return( FALSE );
				actionListPtr = actionListPtr->next;
				}
			if( envelopeInfoPtr->preActionList != NULL )
				return( FALSE );
			}
		else
			if( actionListPtr != NULL )
				/* A standalone action can only be (session-key based) 
				   encryption except for de-enveloping a signed envelope,
				   where we can have standalone hash actions before we get 
				   to the signature data and add post-actions */
				if( !( ( actionListPtr->action == ACTION_CRYPT ) || \
					   ( ( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE ) && \
					     actionListPtr->action == ACTION_HASH ) ) )
					return( FALSE );

	/* Pre-actions can only be key exchange actions, and have to be sorted
	   by action group */
	if( envelopeInfoPtr->preActionList != NULL )
		{
		actionListPtr = envelopeInfoPtr->preActionList;

		while( actionListPtr != NULL && \
			   actionListPtr->action == ACTION_KEYEXCHANGE )
			actionListPtr = actionListPtr->next;
		while( actionListPtr != NULL && \
			   actionListPtr->action == ACTION_KEYEXCHANGE_PKC )
			actionListPtr = actionListPtr->next;

		return( ( actionListPtr == NULL ) ? TRUE : FALSE );
		}

	/* Post-actions can only be signature actions */
	if( envelopeInfoPtr->postActionList != NULL )
		{
		for( actionListPtr = envelopeInfoPtr->postActionList;
			 actionListPtr != NULL; actionListPtr = actionListPtr->next )
			if( actionListPtr->action != ACTION_SIGN )
				return( FALSE );

		return( TRUE );
		}

	/* A standalone action can be either a single crypt, one or more hashes,
	   or nothing */
	if( envelopeInfoPtr->actionList == NULL )
		return( TRUE );
	if( envelopeInfoPtr->actionList->action == ACTION_CRYPT )
		return( envelopeInfoPtr->actionList->next == NULL ? TRUE : FALSE );
	for( actionListPtr = envelopeInfoPtr->preActionList;
		 actionListPtr != NULL; actionListPtr = actionListPtr->next )
		if( actionListPtr->action != ACTION_HASH )
			return( FALSE );

	return( TRUE );
	}
#endif /* !NDEBUG */

/****************************************************************************
*																			*
*						Misc.Enveloping Info Management Functions			*
*																			*
****************************************************************************/

/* Set up the encryption for an envelope */

int initEnvelopeEncryption( ENVELOPE_INFO *envelopeInfoPtr,
							const CRYPT_CONTEXT cryptContext,
							const CRYPT_ALGO algorithm, const CRYPT_MODE mode,
							const BYTE *iv, const int ivLength,
							const BOOLEAN copyContext )
	{
	CRYPT_CONTEXT iCryptContext = cryptContext;
	CRYPT_ALGO cryptAlgo;
	CRYPT_MODE cryptMode;
	RESOURCE_DATA msgData;
	int blockSize, status;

	/* Extract the information we need to process data */
	status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_GETATTRIBUTE, 
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_GETATTRIBUTE, 
								  &cryptMode, CRYPT_CTXINFO_MODE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_GETATTRIBUTE, 
								  &blockSize, CRYPT_CTXINFO_BLOCKSIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Make sure the context is what's required */
	if( algorithm != CRYPT_UNUSED && \
		( cryptAlgo != algorithm || cryptMode != mode ) )
		/* This can only happen on deenveloping if the data is corrupted or 
		   if the user is asked for a KEK and tries to supply a session key 
		   instead */
		return( CRYPT_ERROR_WRONGKEY );

	/* If it's a user-supplied context, take a copy for our own use.  This is
	   only done for user-supplied raw session keys, for everything else we 
	   either use cryptlib's object management to handle things for us or the
	   context is a internal one created specifically for our own use */
	if( copyContext )
		{
		status = krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_CLONE,
								  &iCryptContext, 0 );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Load the IV into the context and set up the encryption information for
	   the envelope */
	if( !isStreamCipher( cryptAlgo ) )
		{
		if( iv != NULL )
			{
			int ivSize;

			status = krnlSendMessage( cryptContext, 
									  RESOURCE_IMESSAGE_GETATTRIBUTE, 
									  &ivSize, CRYPT_CTXINFO_IVSIZE );
			setResourceData( &msgData, ( void * ) iv, min( ivLength, ivSize ) );
			if( cryptStatusOK( status ) )
				status = krnlSendMessage( iCryptContext, 
										  RESOURCE_IMESSAGE_SETATTRIBUTE_S,
										  &msgData, CRYPT_CTXINFO_IV );
			}
		else
			/* There's no IV specified, generate a new one */
			status = krnlSendNotifier( iCryptContext, RESOURCE_IMESSAGE_CTX_GENIV );
		if( cryptStatusError( status ) )
			{
			if( copyContext )
				/* Destroy the copy we created earlier */
				krnlSendNotifier( iCryptContext, RESOURCE_IMESSAGE_DECREFCOUNT );
			return( status );
			}
		}
	envelopeInfoPtr->iCryptContext = iCryptContext;
	envelopeInfoPtr->blockSize = blockSize;
	envelopeInfoPtr->blockSizeMask = ~( blockSize - 1 );

	return( CRYPT_OK );
	}

/* Add keyset information */

static int addKeyset( ENVELOPE_INFO *envelopeInfoPtr,
					  const CRYPT_ATTRIBUTE_TYPE keysetFunction,
					  const CRYPT_KEYSET keyset )
	{
	CRYPT_KEYSET *iKeysetPtr;

	/* Figure out which keyset we want to set */
	switch( keysetFunction )
		{
		case CRYPT_ENVINFO_KEYSET_ENCRYPT:
			iKeysetPtr = &envelopeInfoPtr->iEncryptionKeyset;
			break;

		case CRYPT_ENVINFO_KEYSET_DECRYPT:
			iKeysetPtr = &envelopeInfoPtr->iDecryptionKeyset;
			break;

		case CRYPT_ENVINFO_KEYSET_SIGCHECK:
			iKeysetPtr = &envelopeInfoPtr->iSigCheckKeyset;
			break;

		default:
			assert( NOTREACHED );
			}

	/* Make sure the keyset hasn't already been set */
	if( *iKeysetPtr != CRYPT_ERROR )
		return( CRYPT_ERROR_INITED );

	/* Remember the new keyset and increment its reference count */
	*iKeysetPtr = keyset;
	return( krnlSendNotifier( keyset, RESOURCE_IMESSAGE_INCREFCOUNT ) );
	}

/****************************************************************************
*																			*
*					Deenveloping Information Management Functions			*
*																			*
****************************************************************************/

/* Import a wrapped session key */

static int importSessionKey( ENVELOPE_INFO *envelopeInfoPtr, 
							 const CONTENT_LIST *contentListPtr,
							 const CRYPT_CONTEXT iImportContext,
							 CRYPT_CONTEXT *iSessionKeyContext )
	{
	MESSAGE_CREATEOBJECT_INFO createInfo;
	CONTENT_LIST *sessionKeyInfoPtr;
	int status;

	/* Clear the return value */
	*iSessionKeyContext = CRYPT_ERROR;

	/* PGP doesn't provide separate session key information with the 
	   encrypted data but wraps it up alongside the encrypted key, so we
	   can't import the wrapped key into a context via the standard key
	   import functions but instead have to create the context as part of 
	   the unwrap process */
	if( contentListPtr->formatType == CRYPT_FORMAT_PGP )
		{
		MECHANISM_WRAP_INFO mechanismInfo;
		BYTE *payloadPtr = contentListPtr->payload;
		int payloadLength = contentListPtr->payloadSize;

		/* If it's an RSA key, skip the MPI header around the RSA data.  DLP
		   keys are handled natively so no extra processing is required */
		if( contentListPtr->cryptAlgo == CRYPT_ALGO_RSA )
			{
			payloadPtr += 2;
			payloadLength -= 2;
			}

		/* Decrypt the encrypted key and load it into the context */
		setMechanismWrapInfo( &mechanismInfo, payloadPtr, payloadLength, NULL, 
							  0, CRYPT_UNUSED, iImportContext, CRYPT_UNUSED );
		status = krnlSendMessage( iImportContext, RESOURCE_IMESSAGE_DEV_IMPORT, 
								  &mechanismInfo, MECHANISM_PKCS1_PGP );
		if( cryptStatusOK( status ) )
			*iSessionKeyContext = mechanismInfo.keyContext;
		clearMechanismInfo( &mechanismInfo );

		return( status );
		}

	/* Look for the information required to recreate the session key context */
	for( sessionKeyInfoPtr = envelopeInfoPtr->contentList;
		 sessionKeyInfoPtr != NULL && \
			sessionKeyInfoPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY;
		 sessionKeyInfoPtr = sessionKeyInfoPtr->next );
	if( sessionKeyInfoPtr == NULL )
		/* We need to read more data before we can recreate the session key */
		return( CRYPT_ERROR_UNDERFLOW );

	/* Create the session key context and import the encrypted session key */
	setMessageCreateObjectInfo( &createInfo, sessionKeyInfoPtr->cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, 
							  RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	status = krnlSendMessage( createInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_SETATTRIBUTE,
							  &sessionKeyInfoPtr->cryptMode,
							  CRYPT_CTXINFO_MODE );
	if( cryptStatusOK( status ) )
		status = iCryptImportKeyEx( contentListPtr->object, 
									contentListPtr->objectSize,
									iImportContext, createInfo.cryptHandle );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( createInfo.cryptHandle, 
						  RESOURCE_IMESSAGE_DECREFCOUNT );
		return( status );
		}
	*iSessionKeyContext = createInfo.cryptHandle;
	return( CRYPT_OK );
	}

/* Add de-enveloping information to an envelope */

static int addDeenvelopeInfo( ENVELOPE_INFO *envelopeInfoPtr,
							  const CRYPT_ATTRIBUTE_TYPE envInfo, 
							  const void *value, const int valueLength )
	{
	CONTENT_LIST *contentListPtr = envelopeInfoPtr->contentListCurrent;
	CRYPT_HANDLE cryptHandle = *( ( CRYPT_HANDLE * ) value ), iNewContext;
	ACTION_LIST *actionListPtr;
	int status;

	/* If it's keyset information, just keep a record of it for later use */
	if( envInfo == CRYPT_ENVINFO_KEYSET_SIGCHECK || \
		envInfo == CRYPT_ENVINFO_KEYSET_ENCRYPT || \
		envInfo == CRYPT_ENVINFO_KEYSET_DECRYPT )
		return( addKeyset( envelopeInfoPtr, envInfo, cryptHandle ) );

	/* If it's a hash action, the user is checking a detached sig, remember
	   the hash for later.  In theory we should check the state of the hash 
	   context, however PGP requires that it not be completed (since it
	   needs to hash further data) and everything else requires that it be
	   completed, but we don't know at this point whether we're processing
	   PGP or non-PGP data, so we can't perform any checking here */
	if( envInfo == CRYPT_ENVINFO_HASH )
		{
		ACTION_LIST *actionListItem;

		/* If there's already an action present, we can't add anything 
		   further */
		if( envelopeInfoPtr->actionList != NULL )
			return( CRYPT_ERROR_INITED );

		/* Add the hash as an action list item */
		actionListItem = createAction( ACTION_HASH, cryptHandle );
		if( actionListItem == NULL )
			return( CRYPT_ERROR_MEMORY );
		envelopeInfoPtr->actionList = actionListItem;
		return( krnlSendNotifier( cryptHandle, 
								  RESOURCE_IMESSAGE_INCREFCOUNT ) );
		}

	/* Since we can add one of a multitude of necessary information types, we
	   need to check to make sure what we're adding is appropriate.  If the
	   caller hasn't tried to read the required resource information yet, we
	   try to match what's being added to the first information object of the 
	   correct type */
	if( contentListPtr == NULL )
		{
		/* Look for the first information object matching the supplied
		   information */
		for( contentListPtr = envelopeInfoPtr->contentList;
			 contentListPtr != NULL && contentListPtr->envInfo != envInfo;
			 contentListPtr = contentListPtr->next );
		if( contentListPtr == NULL )
			return( CRYPT_ARGERROR_VALUE );
		}

	/* Make sure the information we're adding matches the currently required
	   information object.  The one exception to this is that we can be 
	   passed password information when we require a private key if the 
	   private key is encrypted */
	if( contentListPtr->envInfo != envInfo && \
		!( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY && \
		   envInfo == CRYPT_ENVINFO_PASSWORD ) )
		return( CRYPT_ARGERROR_VALUE );

	/* If it's a signature object, check the signature and exit.  Anything
	   left after this point is a keying object */
	if( envInfo == CRYPT_ENVINFO_SIGNATURE )
		{
		/* If we've already processed this entry, return the saved processing
		   result */
		if( contentListPtr->processed )
			return( contentListPtr->processingResult );

⌨️ 快捷键说明

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