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

📄 resource.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		/* Find the hash action we need to check this signature */
		for( actionListPtr = envelopeInfoPtr->actionList;
			 actionListPtr != NULL; actionListPtr = actionListPtr->next )
			{
			int cryptAlgo;

			/* Check to see if it's the one we want */
			if( cryptStatusOK( \
					krnlSendMessage( actionListPtr->iCryptHandle, 
									 RESOURCE_IMESSAGE_GETATTRIBUTE,
									 &cryptAlgo, CRYPT_CTXINFO_ALGO ) ) && \
				cryptAlgo == contentListPtr->hashAlgo )
				break;
			}

		/* If we can't find a hash action to match this signature, return a
		   bad signature error since something must have altered the
		   algorithm ID for the hash */
		if( actionListPtr == NULL || actionListPtr->action != ACTION_HASH )
			{
			contentListPtr->processed = TRUE;
			contentListPtr->processingResult = CRYPT_ERROR_SIGNATURE;
			return( CRYPT_ERROR_SIGNATURE );
			}

		/* Check the signature */
		if( contentListPtr->formatType == CRYPT_FORMAT_CMS )
			{
			int value;

			status = iCryptCheckSignatureEx( contentListPtr->object,
											 contentListPtr->objectSize,
											 contentListPtr->iSigCheckKey,
											 actionListPtr->iCryptHandle,
											 &contentListPtr->iExtraData );

			/* If there are authenticated attributes present we have to
			   perform an extra check here to make sure that the content-type
			   specified in the authenticated attributes matches the actual
			   data content type */
			if( cryptStatusOK( status ) && \
				contentListPtr->iExtraData != CRYPT_ERROR )
				{
				status = krnlSendMessage( contentListPtr->iExtraData, 
									RESOURCE_IMESSAGE_GETATTRIBUTE, &value, 
									CRYPT_CERTINFO_CMS_CONTENTTYPE );
				if( cryptStatusError( status ) || \
					envelopeInfoPtr->contentType != value )
					status = CRYPT_ERROR_SIGNATURE;
				}
			}
		else
			{
			if( contentListPtr->formatType == CRYPT_FORMAT_PGP )
				status = iCryptCheckSignatureEx( contentListPtr->payload, 
									contentListPtr->payloadSize, 
									cryptHandle, actionListPtr->iCryptHandle,
									NULL );
			else
				status = iCryptCheckSignatureEx( contentListPtr->object,
									contentListPtr->objectSize, cryptHandle, 
									actionListPtr->iCryptHandle, NULL );

			/* Remember the key which was used to check the signature in case
			   the user wants to query it later */
			contentListPtr->iSigCheckKey = cryptHandle;
			}

		/* Remember the processing result so we don't have to repeat the
		   processing if queried again.  Since we don't need the encoded
		   signature data any more after this point, we free it to make the
		   memory available for reuse */
		free( contentListPtr->object );
		contentListPtr->object = NULL;
		contentListPtr->objectSize = 0;
		contentListPtr->processed = TRUE;
		contentListPtr->processingResult = status;
		return( status );
		}

	/* If we need private key information and we've been given a password,
	   it's the password required to decrypt the key so we treat this
	   specially */
	if( contentListPtr->envInfo == CRYPT_ENVINFO_PRIVATEKEY && \
		envInfo == CRYPT_ENVINFO_PASSWORD )
		{
		MESSAGE_KEYMGMT_INFO getkeyInfo;

		/* Make sure there's a keyset available to pull the key from */
		if( envelopeInfoPtr->iDecryptionKeyset == CRYPT_ERROR )
			{
			setErrorInfo( envelopeInfoPtr, CRYPT_ENVINFO_KEYSET_DECRYPT,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			return( CRYPT_ERROR_NOTINITED );
			}

		/* Try and get the key information.  Since we're accessing the key
		   by (unique) key ID, there's no real need to specify a preference 
		   for encryption keys */
		if( contentListPtr->issuerAndSerialNumber == NULL )
			{
			setMessageKeymgmtInfo( &getkeyInfo, 
					( contentListPtr->formatType == CRYPT_FORMAT_PGP ) ? \
					CRYPT_IKEYID_PGPKEYID : CRYPT_IKEYID_KEYID, 
					contentListPtr->keyID, contentListPtr->keyIDsize, 
					( void * ) value, valueLength, KEYMGMT_FLAG_NONE );
			}
		else
			{
			setMessageKeymgmtInfo( &getkeyInfo, 
					CRYPT_IKEYID_ISSUERANDSERIALNUMBER,
					contentListPtr->issuerAndSerialNumber,
					contentListPtr->issuerAndSerialNumberSize,
					( void * ) value, valueLength, KEYMGMT_FLAG_NONE );
			}
		status = krnlSendMessage( envelopeInfoPtr->iDecryptionKeyset,
								  RESOURCE_IMESSAGE_KEY_GETKEY, &getkeyInfo, 
								  KEYMGMT_ITEM_PRIVATEKEY );

		/* If we managed to get the private key, push it into the envelope.  
		   If the call succeeds, this will import the session key and delete 
		   the required-information list */
		if( status == CRYPT_OK )
			{
			status = addDeenvelopeInfo( envelopeInfoPtr,
										CRYPT_ENVINFO_PRIVATEKEY,
										&getkeyInfo.cryptHandle, 0 );
			krnlSendNotifier( getkeyInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			}

		return( status );
		}

	/* If we've been given a password, create the appropriate encryption
	   context for it and derive the key from the password */
	if( envInfo == CRYPT_ENVINFO_PASSWORD )
		{
		MESSAGE_CREATEOBJECT_INFO createInfo;

		/* Create the appropriate encryption context and derive the key into 
		   it */
		setMessageCreateObjectInfo( &createInfo, contentListPtr->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,
								  &contentListPtr->cryptMode,
								  CRYPT_CTXINFO_MODE );
		if( cryptStatusOK( status ) )
			{
#ifndef NO_PGP
			if( envelopeInfoPtr->type == CRYPT_FORMAT_PGP )
				status = pgpPasswordToKey( createInfo.cryptHandle, value, 
									valueLength, contentListPtr->hashAlgo, 
									contentListPtr->saltOrIVsize ? \
										contentListPtr->saltOrIV : NULL,
									contentListPtr->keySetupIterations );
			else
#endif /* !NO_PGP */
				{
				RESOURCE_DATA msgData;

				/* Load the derivation information into the context */
				status = krnlSendMessage( createInfo.cryptHandle, 
									RESOURCE_IMESSAGE_SETATTRIBUTE,
									&contentListPtr->keySetupIterations, 
									CRYPT_CTXINFO_KEYING_ITERATIONS );
				if( cryptStatusOK( status ) )
					{
					setResourceData( &msgData, contentListPtr->saltOrIV, 
									 contentListPtr->saltOrIVsize );
					status = krnlSendMessage( createInfo.cryptHandle, 
									RESOURCE_IMESSAGE_SETATTRIBUTE_S,
									&msgData, CRYPT_CTXINFO_KEYING_SALT );
					}
				if( cryptStatusOK( status ) )
					{
					setResourceData( &msgData, ( void * ) value, valueLength );
					status = krnlSendMessage( createInfo.cryptHandle, 
									RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
									CRYPT_CTXINFO_KEYING_VALUE );
					}
				}
			}
		if( cryptStatusError( status ) )
			{
			krnlSendNotifier( createInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			return( status );
			}

		/* Recover the session key using the password context and destroy it
		   when we're done with it */
		if( envelopeInfoPtr->type != CRYPT_FORMAT_PGP )
			{
			status = importSessionKey( envelopeInfoPtr, contentListPtr, 
									   createInfo.cryptHandle, &iNewContext );
			krnlSendNotifier( createInfo.cryptHandle, 
							  RESOURCE_IMESSAGE_DECREFCOUNT );
			if( cryptStatusError( status ) )
				return( status );
			}
		else
			/* In PGP there isn't any encrypted session key, so the context
			   created from the password becomes the bulk encryption
			   context */
			iNewContext = createInfo.cryptHandle;
		}

	/* If we've been given a KEK (symmetric or asymmetric), recreate the 
	   session key by importing it using the KEK */
	if( envInfo == CRYPT_ENVINFO_PRIVATEKEY || \
		envInfo == CRYPT_ENVINFO_KEY )
		{
		/* Import the session key using the KEK */
		status = importSessionKey( envelopeInfoPtr, contentListPtr, 
								   cryptHandle, &iNewContext );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* At this point we have the session key, either by recovering it from a
	   key exchange action or by having it passed to us directly.  If we've
	   been given it directly then we must have reached the encryptedContent
	   so we take a copy and set up the decryption with it */
	if( envInfo == CRYPT_ENVINFO_SESSIONKEY )
		{
		status = initEnvelopeEncryption( envelopeInfoPtr, cryptHandle,
					contentListPtr->cryptAlgo, contentListPtr->cryptMode,
					contentListPtr->saltOrIV, contentListPtr->saltOrIVsize, 
					TRUE );
		if( cryptStatusError( status ) )
			return( status );

		/* The session key context is the newly-created internal one */
		iNewContext = envelopeInfoPtr->iCryptContext;
		}
	else
		/* We've recovered the session key from a key exchange action.  If we
		   got as far as the encryptedContent (so there's content info
		   present), we set up the decryption.  If we didn't get this far,
		   it'll be set up by the deenveloping code when we reach it */
		{
		for( contentListPtr = envelopeInfoPtr->contentList;
			 contentListPtr != NULL && \
				contentListPtr->envInfo != CRYPT_ENVINFO_SESSIONKEY;
			 contentListPtr = contentListPtr->next );
		if( contentListPtr != NULL )
			{
			/* We got to the encryptedContent, set up the decryption */
			status = initEnvelopeEncryption( envelopeInfoPtr, iNewContext,
						contentListPtr->cryptAlgo, contentListPtr->cryptMode,
						contentListPtr->saltOrIV, contentListPtr->saltOrIVsize, 
						FALSE );
			if( cryptStatusError( status ) )
				return( status );
			}
		}

	/* Add the recovered session encryption action to the action list */
	if( checkAction( envelopeInfoPtr->actionList, ACTION_CRYPT, 
					 iNewContext ) == ACTION_RESULT_INITED )
		return( CRYPT_ERROR_INITED );
	if( addAction( &envelopeInfoPtr->actionList, ACTION_CRYPT, 
				   iNewContext ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* 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 */
	krnlSendMessage( envelopeInfoPtr->objectHandle, 
					 RESOURCE_IMESSAGE_SETDEPENDENT, &iNewContext, 
					 SETDEP_OPTION_NOINCREF );

	/* Destroy the required information list, which at this point will
	   contain only (now-irrelevant) key exchange items */
	deleteContentList( 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;

	return( status );
	}

/****************************************************************************
*																			*
*					Enveloping Information Management Functions				*
*																			*
****************************************************************************/

/* Check that an object being added is suitable for use with Fortezza data */

static int checkFortezzaUsage( const CRYPT_HANDLE cryptHandle,
							   const ENVELOPE_INFO *envelopeInfoPtr,
							   const CRYPT_ATTRIBUTE_TYPE envInfo )
	{
	CRYPT_ALGO cryptAlgo;
	int device1, device2, status;

	/* Make sure the new session key being added (if there's existing 
	   originator info) or the existing one (if it's originator info being 
	   added) is a Skipjack context */
	status = krnlSendMessage( ( envInfo == CRYPT_ENVINFO_ORIGINATOR ) ? \
							  envelopeInfoPtr->iCryptContext : cryptHandle, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE, &cryptAlgo, 
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusError( status ) || cryptAlgo != CRYPT_ALGO_SKIPJACK )
		return( CRYPT_ARGERROR_NUM1 );

	/* Make sure both objects are present in the same device */
	status = krnlSendMessage( cryptHandle, RESOURCE_IMESSAGE_GETDEPENDENT, 
							  &device1, OBJECT_TYPE_DEVICE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( envelopeInfoPtr->iCryptContext, 
								RESOURCE_IMESSAGE_GETDEPENDENT, &device2, 
								OBJECT_TYPE_DEVICE );
	if( cryptStatusOK( status ) && ( device1 != device2 ) )
		status = CRYPT_ARGERROR_NUM1;

	return( status );
	}

/* Add enveloping information to an envelope */

static int addEnvelopeInfo( ENVELOPE_INFO *envelopeInfoPtr,
							const CRYPT_ATTRIBUTE_TYPE envInfo, 
							const void *value, const int valueLength )
	{
	CRYPT_HANDLE cryptHandle = *( CRYPT_HANDLE * ) value;
	ACTION_LIST *actionListPtr, **actionListHeadPtrPtr, *hashActionPtr;
	ACTION_RESULT actionResult;
	ACTION_TYPE actionType;
	int status;

	/* If it's meta-information, remember the value */
	if( envInfo == CRYPT_ENVINFO_DATASIZE )
		{
		envelopeInfoPtr->payloadSize = *( int * ) value;
		return( CRYPT_OK );
		}
	if( envInfo == CRYPT_ENVINFO_CONTENTTYPE )
		{
		envelopeInfoPtr->contentType = *( int * ) value;
		return( CRYPT_OK );
		}
	if( envInfo == CRYPT_ENVINFO_DETACHEDSIGNATURE || \
		envInfo == CRYPT_ENVINFO_MAC )
		{
		/* Turn a generic zero/nonzero boolean into TRUE or FALSE */
		const int flag = ( *( int * ) value ) ? TRUE : FALSE;

		if( envInfo == CRYPT_ENVINFO_DETACHEDSIGNATURE )
			{
			if( flag )
				envelopeInfoPtr->flags |= ENVELOPE_DETACHED_SIG;
			else
				envelopeInfoPtr->flags &= ~ENVELOPE_DETACHED_SIG;
			}
		else
			/* The MAC flag is somewhat different from the detached-signature
			   one in that the latter is a modifier for an existing envelope
			   usage while the former changes the usage itself.  Because of
			   this it can only be set to TRUE (if it could be reset the 
			   caller could set non-MAC-compatible options by clearing the
			   flag and then setting it again afterwards), since the envelope
			   usage change occurs at a higher level all we do here is make
			   sure the flag isn't being cleared */
			if( !flag )
				return( CRYPT_ARGERROR_NUM1 );
		return( CRYPT_OK );
		}
	if( envInfo == CRYPT_IATTRIBUTE_INCLUDESIGCERT )
		{
		/* This is on by default so we should only be turning it off */
		assert( ( *( int * ) value ) == FALSE );

⌨️ 快捷键说明

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