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

📄 crypt.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 5 页
字号:
											messageDataPtr, messageValue );
				break;

			default:
				assert( NOTREACHED );
			}
		unlockResourceExit( cryptInfoPtr, status );
		}

	/* Process messages which compare object properties or clone the object */
	if( message == RESOURCE_MESSAGE_COMPARE )
		{
		const RESOURCE_DATA *msgData = ( RESOURCE_DATA * ) messageDataPtr;

		assert( messageValue == RESOURCE_MESSAGE_COMPARE_HASH || \
				messageValue == RESOURCE_MESSAGE_COMPARE_KEYID );

		status = CRYPT_ERROR;	/* Default = failed comparison */
		if( messageValue == RESOURCE_MESSAGE_COMPARE_HASH )
			{
			const int hashSize = cryptInfoPtr->capabilityInfo->blockSize;

			/* If it's a hash or MAC context, compare the hash value */
			if( cryptInfoPtr->type == CONTEXT_HASH )
				{
				if( !cryptInfoPtr->ctxHash.done )
					status = CRYPT_ERROR_INCOMPLETE;
				else
					if( msgData->length == hashSize && \
						!memcmp( msgData->data, cryptInfoPtr->ctxHash.hash,
								 hashSize ) )
						status = CRYPT_OK;
				}
			if( cryptInfoPtr->type == CONTEXT_MAC )
				{
				if( !cryptInfoPtr->ctxMAC.done )
					status = CRYPT_ERROR_INCOMPLETE;
				else
					if( msgData->length == hashSize && \
						!memcmp( msgData->data, cryptInfoPtr->ctxMAC.mac,
								 hashSize ) )
						status = CRYPT_OK;
				}
			}
		if( messageValue == RESOURCE_MESSAGE_COMPARE_KEYID )
			{
			/* If it's a PKC context, compare the key ID */
			if( cryptInfoPtr->type == CONTEXT_PKC && \
				msgData->length == KEYID_SIZE && \
				!memcmp( msgData->data, cryptInfoPtr->ctxPKC.keyID, 
						 KEYID_SIZE ) )
				status = CRYPT_OK;
			}
		unlockResourceExit( cryptInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_CLONE )
		{
		CRYPT_CONTEXT *iDestContext = ( CRYPT_CONTEXT * ) messageDataPtr;
		int deviceObjectHandle;

		*iDestContext = CRYPT_ERROR;

		/* Cloning of non-native contexts is somewhat complex because we
		   usually can't clone a device object, so we have to detect requests
		   to clone these objects and increment their reference count
		   instead.  This isn't a major problem because cryptlib always
		   creates native contexts for clonable algorithms, if the user
		   explicitly overrides this by using their own device-specific
		   context then the usage will usually be create, add to envelope,
		   destroy, so there's no need to clone the context anyway.  The
		   only time there's a potential problem is if they override the use
		   of native contexts by adding device contexts to multiple envelopes,
		   but in that case it's assumed they'll be aware of potential
		   problems with this approach */
		krnlSendMessage( cryptContext, RESOURCE_IMESSAGE_GETDEPENDENT,
						 &deviceObjectHandle, OBJECT_TYPE_DEVICE );
		if( deviceObjectHandle != SYSTEM_OBJECT_HANDLE )
			{
			status = krnlSendNotifier( cryptContext,
									   RESOURCE_IMESSAGE_INCREFCOUNT );
			if( cryptStatusOK( status ) )
				*iDestContext = cryptContext;
			}
		else
			status = cloneContext( messageDataPtr, cryptContext );
		unlockResourceExit( cryptInfoPtr, status );
		}

	/* Process messages which check a context */
	if( message == RESOURCE_MESSAGE_CHECK )
		{
		status = checkContext( cryptInfoPtr, messageValue );
		unlockResourceExit( cryptInfoPtr, status );
		}

	/* Process messages which lock/unlock an object for exclusive use */
	if( message == RESOURCE_MESSAGE_LOCK )
		/* Exit without unlocking the object.  Any other threads trying to
		   use the object after this point will be blocked */
		return( CRYPT_OK );
	if( message == RESOURCE_MESSAGE_UNLOCK )
		{
		/* "Wenn drei Leute in ein Zimmer reingehen und fuenf kommen raus,
			dann muessen erst mal zwei wieder reingehen bis das Zimmer leer
			ist" */
		unlockResource( cryptInfoPtr );	/* Undo RESOURCE_MESSAGE_LOCK lock */
		unlockResourceExit( cryptInfoPtr, CRYPT_OK );
		}

	/* Process internal notification messages */
	if( message == RESOURCE_MESSAGE_CHANGENOTIFY && \
		messageValue == CRYPT_IATTRIBUTE_STATUS )
		{
		/* If the context is still busy and we're trying to reset its status
		   from CRYPT_ERROR_BUSY back to CRYPT_OK, set the abort flag to
		   indicate that the operation which is keeping it busy should be
		   cancelled, and return an error so that the busy status is
		   maintained until the context has processed the abort */
		if( !cryptInfoPtr->done )
			{
			cryptInfoPtr->doAbort = TRUE;
			status = CRYPT_ERROR_BUSY;
			}
		else
			/* The context finished whatever it was doing, reset the status
			   back to normal */
			status = CRYPT_OK;

		unlockResourceExit( cryptInfoPtr, status );
		}

	/* Process object-specific messages */
	if( message == RESOURCE_MESSAGE_CTX_GENKEY )
		{
		assert( cryptInfoPtr->type == CONTEXT_CONV || \
				cryptInfoPtr->type == CONTEXT_MAC ||
				cryptInfoPtr->type == CONTEXT_PKC );
		assert( needsKey( cryptInfoPtr ) );

		/* If it's a private key context, we need to have a key label set
		   before we can continue */
		if( cryptInfoPtr->type == CONTEXT_PKC && !cryptInfoPtr->labelSize )
			{
			setErrorInfo( cryptInfoPtr, CRYPT_CTXINFO_LABEL,
						  CRYPT_ERRTYPE_ATTR_ABSENT );
			unlockResourceExit( cryptInfoPtr, CRYPT_ERROR_NOTINITED );
			}

		/* Generate a new key into the context */
		status = generateKey( cryptInfoPtr, messageValue );
		unlockResourceExit( cryptInfoPtr, status );
		}
	if( message == RESOURCE_MESSAGE_CTX_GENIV )
		{
		BYTE buffer[ CRYPT_MAX_IVSIZE ];

		assert( cryptInfoPtr->type == CONTEXT_CONV );

		/* If it's not a conventional encryption context or a mode which
		   doesn't use an IV, the generate IV operation is meaningless */
		if( !needsIV( cryptInfoPtr->ctxConv.mode ) || \
			isStreamCipher ( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
			unlockResourceExit( cryptInfoPtr, CRYPT_ERROR_NOTAVAIL );

		/* Generate a new IV and load it */
		getNonce( buffer, CRYPT_MAX_IVSIZE );
		cryptInfoPtr->capabilityInfo->initIVFunction( cryptInfoPtr, buffer,
													  CRYPT_USE_DEFAULT );
		unlockResourceExit( cryptInfoPtr, CRYPT_OK );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/* Create an encryption context based on an encryption capability template.
   This is a common function called by devices to create a context once
   they've got the appropriate capability template */

int createContextFromCapability( CRYPT_CONTEXT *cryptContext,
								 const CRYPT_USER cryptOwner,
								 const CAPABILITY_INFO *capabilityInfoPtr,
								 const int objectFlags )
	{
	const CRYPT_ALGO cryptAlgo = capabilityInfoPtr->cryptAlgo;
	const CONTEXT_TYPE contextType = \
		( ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL ) && \
		  ( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) ) ? CONTEXT_CONV : \
		( ( cryptAlgo >= CRYPT_ALGO_FIRST_PKC ) && \
		  ( cryptAlgo <= CRYPT_ALGO_LAST_PKC ) ) ? CONTEXT_PKC : \
		( ( cryptAlgo >= CRYPT_ALGO_FIRST_HASH ) && \
		  ( cryptAlgo <= CRYPT_ALGO_LAST_HASH ) ) ? CONTEXT_HASH : CONTEXT_MAC;
	CRYPT_INFO *cryptInfoPtr;
	const int createFlags = objectFlags | \
							( needsSecureMemory( contextType ) ? \
							CREATEOBJECT_FLAG_SECUREMALLOC : 0 );
	int initStatus = CRYPT_OK, subType, status;
	int actionFlags = 0, actionPerms = ACTION_PERM_ALL;

	assert( cryptAlgo > CRYPT_ALGO_NONE && cryptAlgo < CRYPT_ALGO_LAST_MAC );

	/* Clear the return values */
	*cryptContext = CRYPT_ERROR;

	/* Set up the initial permitted action flags */
	switch( contextType )
		{
		case CONTEXT_CONV:
			subType = SUBTYPE_CTX_CONV;
			if( capabilityInfoPtr->encryptFunction != NULL || \
				capabilityInfoPtr->encryptCBCFunction != NULL || \
				capabilityInfoPtr->encryptCFBFunction != NULL || \
				capabilityInfoPtr->encryptOFBFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
											   ACTION_PERM_ALL );
			if( capabilityInfoPtr->decryptFunction != NULL || \
				capabilityInfoPtr->decryptCBCFunction != NULL || \
				capabilityInfoPtr->decryptCFBFunction != NULL || \
				capabilityInfoPtr->decryptOFBFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
											   ACTION_PERM_ALL );
			if( capabilityInfoPtr->generateKeyFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_GENKEY,
											   ACTION_PERM_ALL );
			break;

		case CONTEXT_PKC:
			subType = SUBTYPE_CTX_PKC;
			if( isDlpAlgo( cryptAlgo ) )
				/* The DLP-based PKC's have somewhat specialised usage
				   requirements so we don't allow direct access by users */
				actionPerms = ACTION_PERM_NONE_EXTERNAL;
			if( capabilityInfoPtr->encryptFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT,
											   actionPerms );
			if( capabilityInfoPtr->decryptFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT,
											   actionPerms );
			if( capabilityInfoPtr->signFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN,
											   actionPerms );
			if( capabilityInfoPtr->sigCheckFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK,
											   actionPerms );
			if( capabilityInfoPtr->generateKeyFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_GENKEY,
											   actionPerms );
			break;

		case CONTEXT_HASH:
			subType = SUBTYPE_CTX_HASH;
			actionFlags = \
				MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_HASH, ACTION_PERM_ALL );
			break;

		case CONTEXT_MAC:
			subType = SUBTYPE_CTX_MAC;
			actionFlags = \
				MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_HASH, ACTION_PERM_ALL );
			if( capabilityInfoPtr->generateKeyFunction != NULL )
				actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_GENKEY,
											   ACTION_PERM_ALL );
			break;
		}

	/* Create the context and initialise the variables in it */
	status = krnlCreateObject( ( void ** ) &cryptInfoPtr, cryptOwner,
							   OBJECT_TYPE_CONTEXT, subType,
							   sizeof( CRYPT_INFO ), createFlags,
							   actionFlags, contextMessageFunction );
	if( cryptStatusError( status ) )
		return( status );
	initResourceLock( cryptInfoPtr );
	lockResource( cryptInfoPtr );
	*cryptContext = cryptInfoPtr->objectHandle = status;
	cryptInfoPtr->ownerHandle = cryptOwner;
	cryptInfoPtr->capabilityInfo = capabilityInfoPtr;
	cryptInfoPtr->type = contextType;
	if( cryptInfoPtr->type == CONTEXT_PKC && \
		!( objectFlags & CREATEOBJECT_FLAG_DUMMY ) )
		{
		cryptInfoPtr->ctxPKC.keySizeBits = 0;

		/* Initialise the bignum information */
		cryptInfoPtr->ctxPKC.param1 = BN_new();
		cryptInfoPtr->ctxPKC.param2 = BN_new();
		cryptInfoPtr->ctxPKC.param3 = BN_new();
		cryptInfoPtr->ctxPKC.param4 = BN_new();
		cryptInfoPtr->ctxPKC.param5 = BN_new();
		cryptInfoPtr->ctxPKC.param6 = BN_new();
		cryptInfoPtr->ctxPKC.param7 = BN_new();
		cryptInfoPtr->ctxPKC.param8 = BN_new();
		}
	if( cryptInfoPtr->type == CONTEXT_CONV )
		/* Set the default encryption mode, which is always CBC if possible */
		cryptInfoPtr->ctxConv.mode = isStreamCipher( cryptAlgo ) ? \
									 CRYPT_MODE_OFB : CRYPT_MODE_CBC;

	/* Perform any algorithm-specific initialization */
	if( capabilityInfoPtr->initFunction != NULL && \
		!( objectFlags & CREATEOBJECT_FLAG_DUMMY ) )
		{
		initStatus = capabilityInfoPtr->initFunction( cryptInfoPtr );
		if( cryptStatusError( initStatus ) )
			/* The algorithm-specific init failed, make sure the object gets
			   destroyed when we notify the kernel that the setup process is
			   complete */
			krnlSendNotifier( *cryptContext, RESOURCE_IMESSAGE_DESTROY );
		}
	if( cryptStatusOK( initStatus ) )
		cryptInfoPtr->keyingInfoInited = TRUE;

	/* We've finished setting up the object-type-specific info, tell the
	   kernel the object is ready for use */
	unlockResource( cryptInfoPtr );
	status = krnlSendMessage( *cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
							  MESSAGE_VALUE_OK, CRYPT_IATTRIBUTE_STATUS );
	if( cryptStatusError( initStatus ) )
		status = initStatus;
	if( cryptStatusError( status ) )
		{
		*cryptContext = CRYPT_ERROR;
		return( status );
		}
	if( cryptInfoPtr->type == CONTEXT_HASH )
		/* If it's a hash context there's no explicit keygen or load so we
		   need to send an "object initialised" message to get the kernel to
		   move it into the high state.  If this isn't done, any attempt to
		   use the context will be blocked */
		krnlSendMessage( *cryptContext, RESOURCE_IMESSAGE_SETATTRIBUTE,
						 MESSAGE_VALUE_UNUSED, CRYPT_IATTRIBUTE_INITIALISED );
	return( CRYPT_OK );
	}

/* Create an encryption context object */

int createContext( MESSAGE_CREATEOBJECT_INFO *createInfo,
				   const void *auxDataPtr, const int auxValue )
	{
	CRYPT_CONTEXT iCryptContext;
	const CAPABILITY_INFO FAR_BSS *capabilityInfoPtr;
	int status;

	assert( auxDataPtr != NULL );

	/* Perform basic error checking */
	if( createInfo->arg1 <= CRYPT_ALGO_NONE || \
		createInfo->arg1 >= CRYPT_ALGO_LAST )
		return( CRYPT_ARGERROR_NUM1 );

	/* Find the capability correspo

⌨️ 快捷键说明

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