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

📄 res_denv.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 4 页
字号:
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
	sMemDisconnect( &stream );

	return( status );
	}

/* Perform additional checks beyond those performed for a standard 
   signature as required by CMS signatures */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int checkCmsSignatureInfo( INOUT CONTENT_LIST *contentListPtr, 
								  IN_HANDLE const CRYPT_HANDLE iHashContext,
								  IN_HANDLE const CRYPT_HANDLE iSigCheckContext,
								  IN_ENUM( CRYPT_CONTENT ) \
									const CRYPT_CONTENT_TYPE contentType,
								  INOUT ERROR_INFO *errorInfo )
	{
	CONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;
	int status;

	assert( isWritePtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
	assert( isWritePtr( errorInfo, sizeof( ENVELOPE_INFO ) ) );

	REQUIRES( isHandleRangeValid( iHashContext ) );
	REQUIRES( isHandleRangeValid( iSigCheckContext ) );
	REQUIRES( contentType > CRYPT_CONTENT_NONE && \
			  contentType < CRYPT_CONTENT_LAST );

	/* If it's CMS signed data then the signature check key should be 
	   included with the signed data as a certificate chain, however it's 
	   possible (though unlikely) that the certificates may be unrelated to 
	   the signature, in which case the caller will have provided the 
	   signature check key from an external source */
	status = iCryptCheckSignature( contentListPtr->object, 
								   contentListPtr->objectSize, 
								   CRYPT_FORMAT_CMS,
								   ( sigInfo->iSigCheckKey == CRYPT_ERROR ) ? \
									iSigCheckContext : sigInfo->iSigCheckKey,
								   iHashContext, CRYPT_UNUSED,
								   &sigInfo->iExtraData );
	if( cryptStatusError( status ) )
		{
		retExt( CRYPT_ERROR_SIGNATURE,
				( CRYPT_ERROR_SIGNATURE, errorInfo, 
				  "Signature verification failed" ) );
		}

	/* If there are authenticated attributes present we have to perform an 
	   extra check to make sure that the content-type specified in the 
	   authenticated attributes matches the actual data content type */
	if( sigInfo->iExtraData != CRYPT_ERROR )
		{
		int signatureContentType;

		status = krnlSendMessage( sigInfo->iExtraData, IMESSAGE_GETATTRIBUTE, 
								  &signatureContentType, 
								  CRYPT_CERTINFO_CMS_CONTENTTYPE );
		if( cryptStatusError( status ) || \
			signatureContentType != contentType )
			{
			retExt( CRYPT_ERROR_SIGNATURE,
					( CRYPT_ERROR_SIGNATURE, errorInfo, 
					  "Content-type in authenticated attributes doesn't "
					  "match actual content type" ) );
			}
		}

	/* If there are unauthenticated attributes present, process them.  We 
	   don't record the processing status for these to ensure that some 
	   random error in the non signature-related attributes doesn't 
	   invalidate an otherwise OK signature */
	if( sigInfo->extraData2 != NULL )
		{
		const int localStatus = \
				processUnauthAttributes( contentListPtr, sigInfo->extraData2,
										 sigInfo->extraData2Length );
		if( cryptStatusError( localStatus ) )
			{
			retExt( CRYPT_ERROR_BADDATA,
					( CRYPT_ERROR_BADDATA, errorInfo, 
					  "Invalid unauthenticated attribute data") );
			}
		}

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Process Encryption Data							*
*																			*
****************************************************************************/

/* Import a wrapped session key */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int importSessionKey( const CONTENT_LIST *contentListPtr,
							 IN_HANDLE const CRYPT_CONTEXT iImportContext,
							 OUT_HANDLE_OPT CRYPT_CONTEXT *iSessionKeyContext )
	{
	CRYPT_CONTEXT iSessionKey;
	const CONTENT_LIST *sessionKeyInfoPtr;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	int iterationCount, status;

	assert( isReadPtr( contentListPtr, sizeof( CONTENT_LIST ) ) );
	assert( isWritePtr( iSessionKeyContext, sizeof( CRYPT_CONTEXT ) ) );

	REQUIRES( isHandleRangeValid( iImportContext ) );

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

#ifdef USE_PGP
	/* 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 )
		{
		return( iCryptImportKey( contentListPtr->object,
								 contentListPtr->objectSize,
								 CRYPT_FORMAT_PGP, iImportContext,
								 CRYPT_UNUSED, iSessionKeyContext ) );
		}
#endif /* USE_PGP */

	/* Look for the information required to recreate the session key context */
	for( sessionKeyInfoPtr = contentListPtr, iterationCount = 0;
		 sessionKeyInfoPtr != NULL && \
			sessionKeyInfoPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY && \
			iterationCount < FAILSAFE_ITERATIONS_LARGE;
		 sessionKeyInfoPtr = sessionKeyInfoPtr->next, iterationCount++ );
	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
	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->clEncrInfo.cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
							  OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		return( status );
	iSessionKey = createInfo.cryptHandle;
	status = krnlSendMessage( iSessionKey, IMESSAGE_SETATTRIBUTE,
							  ( void * ) &sessionKeyInfoPtr->clEncrInfo.cryptMode,
							  CRYPT_CTXINFO_MODE );
	if( cryptStatusOK( status ) )
		{
		status = iCryptImportKey( contentListPtr->object,
								  contentListPtr->objectSize,
								  contentListPtr->formatType, iImportContext, 
								  iSessionKey, NULL );
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
		return( status );
		}
	*iSessionKeyContext = iSessionKey;
	return( CRYPT_OK );
	}

/* Set up the envelope decryption using an added or recovered session key */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int initSessionKeyDecryption( INOUT ENVELOPE_INFO *envelopeInfoPtr,
									 IN_HANDLE \
										const CRYPT_CONTEXT iSessionKeyContext,
									 const BOOLEAN isRecoveredSessionKey )
	{
	ACTION_RESULT actionResult;
	int status;

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

	REQUIRES( isHandleRangeValid( iSessionKeyContext ) );

	/* If we recovered the session key from a key exchange action rather 
	   than having it passed directly to us by the user, try and set up the 
	   decryption */
	if( isRecoveredSessionKey )
		{
		const CONTENT_LIST *contentListPtr;
		int iterationCount;
		
		/* If we got as far as the encrypted data (indicated by the fact 
		   that there's content info present) we can set up the decryption.  
		   If we didn't get this far it'll be set up by the de-enveloping 
		   code when we reach it */
		for( contentListPtr = envelopeInfoPtr->contentList, iterationCount = 0;
			 contentListPtr != NULL && \
				contentListPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY && \
				iterationCount < FAILSAFE_ITERATIONS_LARGE;
			 contentListPtr = contentListPtr->next, iterationCount++ );
		ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
		if( contentListPtr != NULL )
			{
			const CONTENT_ENCR_INFO *encrInfo = &contentListPtr->clEncrInfo;

			/* We've got to the encrypted data, set up the decryption */
			status = initEnvelopeEncryption( envelopeInfoPtr, 
							iSessionKeyContext, encrInfo->cryptAlgo, 
							encrInfo->cryptMode, encrInfo->saltOrIV, 
							encrInfo->saltOrIVsize, FALSE );
			if( cryptStatusError( status ) )
				return( status );
			}
		}

	/* Add the recovered session encryption action to the action list */
	actionResult = checkAction( envelopeInfoPtr->actionList, ACTION_CRYPT,
								iSessionKeyContext );
	if( actionResult == ACTION_RESULT_ERROR || \
		actionResult == ACTION_RESULT_INITED )
		return( CRYPT_ERROR_INITED );
	status = addAction( &envelopeInfoPtr->actionList,
						envelopeInfoPtr->memPoolState, ACTION_CRYPT,
						iSessionKeyContext );
	if( cryptStatusError( status ) )
		return( status );

	/* Notify the kernel that the session key context is attached to the
	   envelope.  This is an internal object used only by the envelope so we
	   tell the kernel not to increment its reference count when it attaches
	   it */
	return( krnlSendMessage( envelopeInfoPtr->objectHandle, 
							 IMESSAGE_SETDEPENDENT, 
							 ( void * ) &iSessionKeyContext, 
							 SETDEP_OPTION_NOINCREF ) );
	}

/****************************************************************************
*																			*
*							Add De-enveloping Information 					*
*																			*
****************************************************************************/

/* Add signature verification information */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int findHashActionFunction( const ACTION_LIST *actionListPtr,
								   IN_INT_Z const int hashAlgo )
	{
	CRYPT_ALGO_TYPE actionCryptAlgo;
	int status;

	assert( isReadPtr( actionListPtr, sizeof( ACTION_LIST ) ) );

	REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
			  hashAlgo <= CRYPT_ALGO_LAST_HASH );

	/* Check to see if it's the action that we want */
	status = krnlSendMessage( actionListPtr->iCryptHandle,
							  IMESSAGE_GETATTRIBUTE, &actionCryptAlgo,
							  CRYPT_CTXINFO_ALGO );
	return( ( actionCryptAlgo == hashAlgo ) ? CRYPT_OK : CRYPT_ERROR );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int addSignatureInfo( INOUT ENVELOPE_INFO *envelopeInfoPtr,
							 INOUT CONTENT_LIST *contentListPtr,
							 IN_HANDLE const CRYPT_HANDLE sigCheckContext,
							 const BOOLEAN isExternalKey )
	{
	CONTENT_SIG_INFO *sigInfo = &contentListPtr->clSigInfo;
	ACTION_LIST *actionListPtr;
	int status;

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

	REQUIRES( isHandleRangeValid( sigCheckContext ) );

	/* If we've already processed this entry, return the cached processing 
	   result */
	if( contentListPtr->flags & CONTENTLIST_PROCESSED )
		return( sigInfo->processingResult );

	/* Find the hash action that we need to check this signature.  If we 
	   can't find one, return a bad signature error since something must 
	   have altered the algorithm ID for the hash */
	actionListPtr = findActionIndirect( envelopeInfoPtr->actionList,
										findHashActionFunction,
										sigInfo->hashAlgo );
	if( actionListPtr == NULL || actionListPtr->action != ACTION_HASH )
		{
		contentListPtr->flags |= CONTENTLIST_PROCESSED;
		sigInfo->processingResult = CRYPT_ERROR_SIGNATURE;
		retExt( CRYPT_ERROR_SIGNATURE,
				( CRYPT_ERROR_SIGNATURE, ENVELOPE_ERRINFO,
				  "Signature hash algorithm doesn't match hash algorithm "
				  "applied to enveloped data" ) );
		}

	/* Check the signature */
	if( contentListPtr->formatType == CRYPT_FORMAT_CMS )
		{
		status = checkCmsSignatureInfo( contentListPtr, 
										actionListPtr->iCryptHandle,
										sigCheckContext,
										envelopeInfoPtr->contentType,
										ENVELOPE_ERRINFO );
		}
	else
		{
		status = iCryptCheckSignature( contentListPtr->object,
								contentListPtr->objectSize,
								contentListPtr->formatType, sigCheckContext,
								actionListPtr->iCryptHandle, CRYPT_UNUSED, 
								NULL );
		if( cryptStatusError( status ) )
			{
			setErrorString( ENVELOPE_ERRINFO, 
							"Signature verification failed", 29 );
			}

⌨️ 快捷键说明

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