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

📄 res_env.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:

		status = checkActionIndirect( envelopeInfoPtr->postActionList,
									  checkSignatureActionFunction, 
									  signingKeyPresent );
		if( cryptStatusError( status ) )
			{
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_SIGNATURE, 
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( status );
			}
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Add Enveloping Information 						*
*																			*
****************************************************************************/

/* Add keyset information (this function is also used by the de-enveloping 
   routines) */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int addKeysetInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
				   IN_RANGE( CRYPT_ENVINFO_KEYSET_ENCRYPT, \
							 CRYPT_ENVINFO_KEYSET_SIGCHECK ) \
					const CRYPT_ATTRIBUTE_TYPE keysetFunction,
				   IN_HANDLE const CRYPT_KEYSET keyset )
	{
	CRYPT_KEYSET *iKeysetPtr;

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

	REQUIRES( keysetFunction == CRYPT_ENVINFO_KEYSET_ENCRYPT || \
			  keysetFunction == CRYPT_ENVINFO_KEYSET_DECRYPT || \
			  keysetFunction == CRYPT_ENVINFO_KEYSET_SIGCHECK );
	REQUIRES( isHandleRangeValid( keyset ) );

	/* 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:
			retIntError();
		}

	/* Make sure that the keyset hasn't already been set */
	if( *iKeysetPtr != CRYPT_ERROR )
		{
		setErrorInfo( envelopeInfoPtr, keysetFunction,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( CRYPT_ERROR_INITED );
		}

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

/* Add an encryption password */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int addPasswordInfo( ENVELOPE_INFO *envelopeInfoPtr,
							IN_BUFFER( passwordLength ) const void *password, 
							IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
								const int passwordLength )
	{
	CRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;
	CRYPT_CONTEXT iCryptContext;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MESSAGE_DATA msgData;
	ACTION_RESULT actionResult;
	int status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isReadPtr( password, passwordLength ) );

	REQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );
	REQUIRES( envelopeInfoPtr->type != CRYPT_FORMAT_PGP );

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

	/* Create the appropriate encryption context.  We have to be careful to 
	   ensure that we use an algorithm which is compatible with the wrapping 
	   mechanism */
	if( isStreamCipher( cryptAlgo ) || \
		cryptStatusError( sizeofAlgoIDex( cryptAlgo, 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 );
	iCryptContext = createInfo.cryptHandle;

	/* Derive the key into the context */
	setMessageData( &msgData, ( void * ) password, passwordLength );
	status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S, 
							  &msgData, CRYPT_CTXINFO_KEYING_VALUE );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Make sure that this key exchange action isn't already present and 
	   insert it into the action list */
	actionResult = checkAction( envelopeInfoPtr->preActionList, 
								ACTION_KEYEXCHANGE, iCryptContext );
	if( actionResult == ACTION_RESULT_ERROR || \
		actionResult == ACTION_RESULT_INITED )
		{
		setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PASSWORD,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		status = CRYPT_ERROR_INITED;
		}
	else
		{
		status = addAction( &envelopeInfoPtr->preActionList,
							envelopeInfoPtr->memPoolState, 
							ACTION_KEYEXCHANGE, iCryptContext );
		}
	if( cryptStatusError( status ) )
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}

#ifdef USE_PGP

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int addPgpPasswordInfo( ENVELOPE_INFO *envelopeInfoPtr,
							   IN_BUFFER( passwordLength ) const void *password, 
							   IN_RANGE( 1, CRYPT_MAX_TEXTSIZE ) \
								const int passwordLength )
	{
	CRYPT_ALGO_TYPE cryptAlgo = envelopeInfoPtr->defaultAlgo;
	CRYPT_CONTEXT iCryptContext;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MESSAGE_DATA msgData;
	BYTE salt[ PGP_SALTSIZE + 8 ];
	static const CRYPT_MODE_TYPE mode = CRYPT_MODE_CFB;
	int status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isReadPtr( password, passwordLength ) );

	REQUIRES( passwordLength > 0 && passwordLength <= CRYPT_MAX_TEXTSIZE );
	REQUIRES( envelopeInfoPtr->type == CRYPT_FORMAT_PGP );

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

	/* PGP doesn't support both PKC and conventional key exchange actions or 
	   multiple 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( envelopeInfoPtr->type == CRYPT_FORMAT_PGP && \
		( findAction( envelopeInfoPtr->preActionList,
					  ACTION_KEYEXCHANGE_PKC ) != NULL || \
		  envelopeInfoPtr->actionList != NULL ) )
		{
		setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_PUBLICKEY,
					  CRYPT_ERRTYPE_ATTR_PRESENT );
		return( CRYPT_ERROR_INITED );
		}

	/* Create the appropriate encryption context.  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 
	   that's encodable using the PGP data format so we don't need to 
	   perform any additional checking here */
	setMessageCreateObjectInfo( &createInfo, cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT, 
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	iCryptContext = createInfo.cryptHandle;

	/* PGP uses CFB mode for everything so we change the mode from the 
	   default of CBC to CFB */
	status = krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE, 
							  ( void * ) &mode, CRYPT_CTXINFO_MODE );
	if( cryptStatusError( status ) )
		return( status );

	/* Generate a salt and derive the key into the context */
	setMessageData( &msgData, salt, PGP_SALTSIZE );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
	if( cryptStatusOK( status ) )
		{
		status = pgpPasswordToKey( iCryptContext, CRYPT_UNUSED, 
								   password, passwordLength,
								   envelopeInfoPtr->defaultHash,
								   salt, PGP_SALTSIZE, PGP_ITERATIONS );
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		return( status );
		}

	/* Insert the context 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 */
	status = addAction( &envelopeInfoPtr->actionList, 
						envelopeInfoPtr->memPoolState, ACTION_CRYPT, 
						iCryptContext );
	if( cryptStatusError( status ) )
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
	return( status );
	}
#endif /* USE_PGP */

/* Add a context to an envelope */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int addContextInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
						   IN_HANDLE const CRYPT_HANDLE cryptHandle,
						   INOUT_PTR ACTION_LIST **actionListHeadPtrPtr,
						   IN_ENUM( ACTION ) const ACTION_TYPE actionType )
	{
	CRYPT_ALGO_TYPE cryptAlgo, certHashAlgo;
	CRYPT_MODE_TYPE cryptMode = CRYPT_MODE_NONE;
	CRYPT_HANDLE iCryptHandle = cryptHandle;
	ACTION_LIST *actionListPtr, *hashActionPtr;
	ACTION_RESULT actionResult;
	int status;

	assert( isWritePtr( envelopeInfoPtr, sizeof( ENVELOPE_INFO ) ) );
	assert( isWritePtr( actionListHeadPtrPtr, sizeof( ACTION_LIST * ) ) );

	REQUIRES( isHandleRangeValid( cryptHandle ) );
	REQUIRES( actionType > ACTION_NONE && actionType < ACTION_LAST );

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

	/* Make sure that the algorithm information is encodable using the 
	   selected envelope format.  This should already have been checked by
	   the calling function but we double-check here because this provides 
	   a convenient centralised location for it */
	status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) && \
		( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
		  cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) )
		{
		status = krnlSendMessage( iCryptHandle, IMESSAGE_GETATTRIBUTE,
								  &cryptMode, CRYPT_CTXINFO_MODE );
		}
	if( cryptStatusError( status ) )
		return( status );
	if( !envelopeInfoPtr->checkAlgo( cryptAlgo, cryptMode ) )
		return( CRYPT_ARGERROR_NUM1 );

	/* Find the insertion point for this action and make sure that it isn't
	   already present.  The difference between ACTION_RESULT_INITED and 
	   ACTION_RESULT_PRESENT 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, 
								iCryptHandle );
	switch( actionResult )
		{
		case ACTION_RESULT_OK:
		case ACTION_RESULT_EMPTY:
			break;

		case ACTION_RESULT_INITED:
			return( CRYPT_ERROR_INITED );
	
		case ACTION_RESULT_PRESENT:
			return( CRYPT_OK );

		case ACTION_RESULT_ERROR:
			return( CRYPT_ARGERROR_NUM1 );

		default:
			retIntError();
		}

	/* 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 )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		setMessageCreateObjectInfo( &createInfo, cryptAlgo );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
								  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
								  OBJECT_TYPE_CONTEXT );
		if( cryptStatusError( status ) )
			return( status );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_CLONE, NULL,
								  createInfo.cryptHandle );
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
			return( status );
			}
		iCryptHandle = createInfo.cryptHandle;
		}
	else
		{
		status = krnlSendNotifier( iCryptHandle, IMESSAGE_INCREFCOUNT );
		if( cryptStatusError( status ) )
			return( status );
		}
	status = addActionEx( &actionListPtr, actionListHeadPtrPtr,
						  envelopeInfoPtr->memPoolState, actionType, 
						  iCryptHandle );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptHandle, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	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 );

	/* Check whether the hash algorithm used in the certificate attached to 
	   the signing key is stronger than the one that's set for the envelope 
	   as a whole and if it is, upgrade the envelope hash algo.  This is 
	   based on the fact that anyone who's able to verify the certificate 

⌨️ 快捷键说明

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