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

📄 res_denv.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int completeEnvelopeInfoUpdate( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );

	/* Destroy the content list, which at this point will contain only (now-
	   irrelevant) key exchange items */
	deleteContentList( envelopeInfoPtr->memPoolState,
					   &envelopeInfoPtr->contentList );
	envelopeInfoPtr->contentList = envelopeInfoPtr->contentListCurrent = NULL;

	/* If the only error was an information required error, we've now
	   resolved the problem and can continue */
	if( envelopeInfoPtr->errorState == CRYPT_ENVELOPE_RESOURCE )
		{
		envelopeInfoPtr->errorState = CRYPT_OK;

		/* The envelope is ready to process data, move it into the high
		   state.  Normally this is handled in the data-push code but this
		   leads to a race condition when all the data being pushed is
		   buffered inside the envelope, requiring only that processing be
		   enabled by adding a resource.  Once the resource is added the
		   only action left for the caller to perform is a flush, so they 
		   expect that high-state actions should succeed even though the
		   envelope state machine wouldn't move the envelope into the high
		   state until some data action (in this case a flush) is 
		   initiated.  To avoid this problem we move the envelope into the
		   high state as soon as the resource blockage has been cleared,
		   since any high-state-only information (for example the nested
		   content type) will now be available */
		return( krnlSendMessage( envelopeInfoPtr->objectHandle, 
								 IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_UNUSED, 
								 CRYPT_IATTRIBUTE_INITIALISED ) );
		}

	return( CRYPT_OK );
	}

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

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int addDeenvelopeInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							  IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE envInfo,
							  IN_INT_Z const int value )
	{
	CRYPT_HANDLE cryptHandle = ( CRYPT_HANDLE ) value;
	CRYPT_CONTEXT iNewContext = DUMMY_INIT;
	CRYPT_ATTRIBUTE_TYPE localEnvInfo = envInfo;
	CONTENT_LIST *contentListPtr;
	BOOLEAN isExternalKey = TRUE;
	int status = CRYPT_OK;

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

	REQUIRES( envInfo == CRYPT_IATTRIBUTE_ATTRONLY || \
			  ( envInfo > CRYPT_ENVINFO_FIRST && \
				envInfo < CRYPT_ENVINFO_LAST ) );

	/* A signature-check object can be passed in as a special-case type
	   CRYPT_ENVINFO_SIGNATURE_RESULT to indicate that the object was 
	   obtained internally (for example by instantiating it from an attached 
	   certificate chain) and doesn't require various special-case 
	   operations that are applied to user-supplied objects.  If this is the 
	   case we convert it to a standard CRYPT_ENVINFO_SIGNATURE and remember 
	   that it's an internally-supplied key */
	if( envInfo == CRYPT_ENVINFO_SIGNATURE_RESULT )
		{
		localEnvInfo = CRYPT_ENVINFO_SIGNATURE;
		isExternalKey = FALSE;
		}

	/* Since we can add one of a multitude of necessary information types 
	   we need to check to make sure that what we're adding is appropriate.  
	   We do this by trying to match what's being added to the first 
	   information object of the correct type */
	status = matchInfoObject( &contentListPtr, envelopeInfoPtr, 
							  localEnvInfo );
	if( cryptStatusError( status ) )
		{
		retExtArg( status,
				   ( status, ENVELOPE_ERRINFO,
					 "Added item doesn't match %s envelope information "
					 "object",
					 ( envelopeInfoPtr->contentListCurrent != NULL ) ? \
						"currently selected" : "any" ) );
		}

	/* Process non-encryption-related enveloping info */
	switch( localEnvInfo )
		{
		case CRYPT_IATTRIBUTE_ATTRONLY:
			/* This is off by default so we should only be turning it on */
			REQUIRES( value == TRUE );

			envelopeInfoPtr->flags |= ENVELOPE_ATTRONLY;
			return( CRYPT_OK );

		case CRYPT_ENVINFO_KEYSET_SIGCHECK:
		case CRYPT_ENVINFO_KEYSET_ENCRYPT:
		case CRYPT_ENVINFO_KEYSET_DECRYPT:
			/* It's keyset information, keep a record of it for later use */
			return( addKeysetInfo( envelopeInfoPtr, localEnvInfo, 
								   cryptHandle ) );

		case CRYPT_ENVINFO_HASH:
			{
			ACTION_LIST *actionListItem;

			/* The user is checking a detached signature, remember the hash 
			   for later.  In theory we should also 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( envelopeInfoPtr->actionList != NULL )
				{
				/* There's already a hash action present, we can't add 
				   anything further */
				setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_HASH,
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				return( CRYPT_ERROR_INITED );
				}

			/* Make sure that we can still add another action */
			if( !moreActionsPossible( envelopeInfoPtr->actionList ) )
				return( CRYPT_ERROR_OVERFLOW );

			/* Add the hash as an action list item */
			status = addActionEx( &actionListItem, 
								  &envelopeInfoPtr->actionList,
								  envelopeInfoPtr->memPoolState, 
								  ACTION_HASH, cryptHandle );
			if( cryptStatusError( status ) )
				return( status );
			return( krnlSendNotifier( cryptHandle, IMESSAGE_INCREFCOUNT ) );
			}

		case CRYPT_ENVINFO_SIGNATURE:
			/* It's a signature object, check the signature and exit */
			return( addSignatureInfo( envelopeInfoPtr, contentListPtr,
									  cryptHandle, isExternalKey ) );
		}

	/* Make sure that we can still add another action */
	if( !moreActionsPossible( envelopeInfoPtr->actionList ) )
		return( CRYPT_ERROR_OVERFLOW );

	/* Anything that's left at this point related to envelope decryption */
	switch( localEnvInfo )
		{
		case CRYPT_ENVINFO_PRIVATEKEY:
		case CRYPT_ENVINFO_KEY:
			/* Import the session key using the KEK */
			status = importSessionKey( contentListPtr, cryptHandle, 
									   &iNewContext );
			break;

		case CRYPT_ENVINFO_SESSIONKEY:
			{
			/* If we've been given the session key directly then we must 
			   have reached the encrypted data so we take a copy and set 
			   up the decryption with it */
			const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;

			status = initEnvelopeEncryption( envelopeInfoPtr, cryptHandle,
							encrInfo->cryptAlgo, encrInfo->cryptMode,
							encrInfo->saltOrIV, encrInfo->saltOrIVsize, TRUE );
			if( cryptStatusOK( status ) )
				{
				/* The session key context is the newly-created internal 
				   one */
				iNewContext = envelopeInfoPtr->iCryptContext;
				}
			break;
			}

		default:
			retIntError();
		}
	if( cryptStatusError( status ) )
		return( status );

	/* We've now got the session key, if we recovered it from a key exchange
	   action (rather than having it passed directly to us by the user) try
	   and set up the decryption */
	if( envelopeInfoPtr->usage != ACTION_MAC )
		{
		status = initSessionKeyDecryption( envelopeInfoPtr, iNewContext,
							( localEnvInfo != CRYPT_ENVINFO_SESSIONKEY ) ? \
								TRUE : FALSE );
		if( cryptStatusError( status ) )
			{
			if( localEnvInfo != CRYPT_ENVINFO_SESSIONKEY )
				krnlSendNotifier( iNewContext, IMESSAGE_DECREFCOUNT );
			if( status == CRYPT_ERROR_INITED )
				{
				/* If the attribute that we added to recover the session key 
				   is already present, provide extended error information */
				setErrorInfo( envelopeInfoPtr, localEnvInfo, 
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				}
			return( status );
			}
		}

	/* Complete the envelope information update */
	return( completeEnvelopeInfoUpdate( envelopeInfoPtr ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int addDeenvelopeInfoString( INOUT ENVELOPE_INFO *envelopeInfoPtr,
									IN_RANGE( CRYPT_ENVINFO_PASSWORD, \
											  CRYPT_ENVINFO_PASSWORD ) \
										const CRYPT_ATTRIBUTE_TYPE envInfo,
									IN_BUFFER( valueLength ) const void *value, 
									IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
										const int valueLength )
	{
	CRYPT_CONTEXT iNewContext = DUMMY_INIT;
	CONTENT_LIST *contentListPtr;
	int status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isReadPtr( value, valueLength ) );

	REQUIRES( envInfo == CRYPT_ENVINFO_PASSWORD );
	REQUIRES( valueLength > 0 && valueLength < MAX_ATTRIBUTE_SIZE );

	/* Since we can add one of a multitude of necessary information types, 
	   we need to check to make sure that what we're adding is appropriate.  
	   We do this by trying to match what's being added to the first 
	   information object of the correct type */
	status = matchInfoObject( &contentListPtr, envelopeInfoPtr, envInfo );
	if( cryptStatusError( status ) )
		{
		retExt( status,
				( status, ENVELOPE_ERRINFO,
				  "Added item doesn't match any envelope information "
				  "object" ) );
		}

	/* If we've been given a password and we need private key information, 
	   it's the password required to decrypt the key so we treat this 
	   specially.  This action recursively calls addDeenvelopeInfo() with 
	   the processed private key so we don't have to fall through to the 
	   session-key processing code below like the other key-handling 
	   actions */
	if( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY )
		{
		return( addPrivkeyPasswordInfo( envelopeInfoPtr, contentListPtr,
										value, valueLength ) );
		}

	/* Make sure that we can still add another action */
	if( envelopeInfoPtr->usage != ACTION_MAC && \
		!moreActionsPossible( envelopeInfoPtr->actionList ) )
		return( CRYPT_ERROR_OVERFLOW );

	/* We've been given a standard decryption password, create a decryption 
	   context for it, derive the key from the password, and use it to 
	   import the session/MAC key */
	if( envelopeInfoPtr->usage == ACTION_MAC )
		{
		if( envelopeInfoPtr->actionList == NULL )
			return( CRYPT_ERROR_NOTINITED );
		status = addPasswordInfo( contentListPtr, value, valueLength, 
								  envelopeInfoPtr->actionList->iCryptHandle, 
								  NULL, envelopeInfoPtr->type, 
								  ENVELOPE_ERRINFO );
		}
	else
		{
		status = addPasswordInfo( contentListPtr, value, valueLength, 
								  CRYPT_UNUSED, &iNewContext,
								  envelopeInfoPtr->type, ENVELOPE_ERRINFO );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* We've recovered the session key, try and set up the decryption */
	if( envelopeInfoPtr->usage != ACTION_MAC )
		{
		status = initSessionKeyDecryption( envelopeInfoPtr, iNewContext, 
										   TRUE );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( iNewContext, IMESSAGE_DECREFCOUNT );
			if( status == CRYPT_ERROR_INITED )
				{
				/* If the attribute that we added to recover the session key 
				   is already present, provide extended error information */
				setErrorInfo( envelopeInfoPtr, envInfo, 
							  CRYPT_ERRTYPE_ATTR_PRESENT );
				}
			return( status );
			}
		}

	/* Complete the envelope information update */
	return( completeEnvelopeInfoUpdate( envelopeInfoPtr ) );
	}

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

STDC_NONNULL_ARG( ( 1 ) ) \
void initDenvResourceHandling( INOUT ENVELOPE_INFO *envelopeInfoPtr )
	{
	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	
	REQUIRES_V( envelopeInfoPtr->flags & ENVELOPE_ISDEENVELOPE );

	/* Set the access method pointers */
	envelopeInfoPtr->addInfo = addDeenvelopeInfo;
	envelopeInfoPtr->addInfoString = addDeenvelopeInfoString;
	}
#endif /* USE_ENVELOPES */

⌨️ 快捷键说明

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