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

📄 obj_acc.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*							Object Alternative Access						*
*						Copyright Peter Gutmann 1997-2004					*
*																			*
****************************************************************************/

/* Sending a message to an object only makes the one object which is the
   target of the message available for use.  When we need simultaneous
   access to two objects (for example when copying a collection of cert
   extensions from one cert to another), we have to use the
   krnlAcquireObject()/krnlReleaseObject() functions to obtain access to
   the second object's internals.

   There is a second situation in which we need access to an object's
   internals, and that occurs when we need to export/import a key from/to
   a context.  This is handled via the key extract functions at the end
   of this module, see the comments there for further information */

#if defined( INC_ALL )
  #include "crypt.h"
  #include "acl.h"
  #include "kernel.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "acl.h"
  #include "kernel.h"
#else
  #include "crypt.h"
  #include "kernel/acl.h"
  #include "kernel/kernel.h"
#endif /* Compiler-specific includes */

/* A pointer to the kernel data block */

static KERNEL_DATA *krnlData = NULL;

/****************************************************************************
*																			*
*								Utility Functions							*
*																			*
****************************************************************************/

/* The type of checking that we perform for the object access.  The check 
   types are:

	CHECK_EXTERNAL
		Kernel-external call with a cert or user object.

	CHECK_EXTERNAL_RELEASE
		Kernel-external call, as CHECK_EXTERNAL except that we can also 
		release the system object when we don't need it any more but need to 
		carry out further operations with other objects.

	CHECK_KEYACCESS
		Kernel-internal call with a context for key export/import */

typedef enum {
	ACCESS_CHECK_NONE,		/* No access check type */
	ACCESS_CHECK_EXTERNAL,	/* Generic external call: Cert or user obj.*/
	ACCESS_CHECK_EXTERNAL_RELEASE,	/* Generic external call: Cert or user obj.*/
	ACCESS_CHECK_KEYACCESS,	/* Internal call: Context for key export */
	ACCESS_CHECK_LAST		/* Last access check type */
	} ACCESS_CHECK_TYPE;

/* Check that this is an object for which direct access is valid.  We can 
   only access the following object types:

	Contexts: Used when importing/exporting keys to/from contexts during
		key wrap/unwrap operations.

	Certificates: Used when copying internal state such as cert extensions 
		or CRL info from one cert object to another.
	
	Crypto hardware devices other than the system object: Used when a 
		context tied to a device needs to perform an operation using the 
		device.
	
	User objects: Used when committing config data to persistent storage, we 
		don't actually use the object data but merely unlock it to allow 
		others access while performing the potentially lengthy update */

static int checkAccessValid( const int objectHandle,
							 const ACCESS_CHECK_TYPE checkType,
							 const int errorCode )
	{
	OBJECT_INFO *objectTable = krnlData->objectTable;
	OBJECT_INFO *objectInfoPtr;

	PRE( checkType > ACCESS_CHECK_NONE && checkType < ACCESS_CHECK_LAST );
	PRE( errorCode < 0 );

	/* Perform similar access checks to the ones performed in
	   krnlSendMessage(): It's a valid object owned by the calling
	   thread */
	if( !isValidObject( objectHandle ) || \
		!checkObjectOwnership( objectTable[ objectHandle ] ) )
		return( errorCode );

	/* It's a valid object, get its info */
	objectInfoPtr = &objectTable[ objectHandle ];

	/* Make sure that the object access is valid */
	switch( objectInfoPtr->type )
		{
		case OBJECT_TYPE_CONTEXT:
			/* Used when exporting/importing keying info, valid for contexts 
			   with keys when called from within the kernel */
			if( checkType != ACCESS_CHECK_KEYACCESS )
				return( errorCode );
			if( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_CONV ) && \
				!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_MAC ) && \
				!isValidSubtype( objectInfoPtr->subType, SUBTYPE_CTX_PKC ) )
				return( errorCode );
			break;

		case OBJECT_TYPE_CERTIFICATE:
			/* Used when copying internal state such as cert extensions or
			   CRL info from one cert object to another.  This is valid for
			   all cert types when called from the cert code outside the 
			   kernel */
			if( checkType != ACCESS_CHECK_EXTERNAL && \
				checkType != ACCESS_CHECK_EXTERNAL_RELEASE )
				return( errorCode );
			break;

		case OBJECT_TYPE_DEVICE:
			/* Used when a context tied to a crypto hardware device needs to
			   perform an operation using the device.  This is valid for all 
			   devices other than the system object, however it can be used 
			   to release the system object during a lengthy operation */
			if( checkType != ACCESS_CHECK_EXTERNAL && \
				checkType != ACCESS_CHECK_EXTERNAL_RELEASE )
				return( CRYPT_ERROR );
			if( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_FORTEZZA ) && \
				!isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_PKCS11 ) && \
				!isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_CRYPTOAPI ) && \
				!( checkType == ACCESS_CHECK_EXTERNAL_RELEASE && \
				   isValidSubtype( objectInfoPtr->subType, SUBTYPE_DEV_SYSTEM ) ) )
				return( errorCode );

			/* Perform an additional explicit check for the system object */
			if( checkType != ACCESS_CHECK_EXTERNAL_RELEASE && \
				objectHandle == SYSTEM_OBJECT_HANDLE )
				return( errorCode );
			break;

		case OBJECT_TYPE_USER:
			/* Used when updating config data, which can take awhile.  The 
			   default user is an SO user, which is why we check for this 
			   user type */
			if( checkType != ACCESS_CHECK_EXTERNAL && \
				checkType != ACCESS_CHECK_EXTERNAL_RELEASE )
				return( errorCode );
			if( !isValidSubtype( objectInfoPtr->subType, SUBTYPE_USER_SO ) )
				return( errorCode );
			break;

		default:
			assert( NOTREACHED );
			return( errorCode );
		}

	/* Postcondition: The object is of the appropriate type for the access */
	POST( ( ( checkType == ACCESS_CHECK_EXTERNAL || \
			  checkType == ACCESS_CHECK_EXTERNAL_RELEASE ) && \
			( objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE || \
			  objectInfoPtr->type == OBJECT_TYPE_DEVICE || \
			  objectInfoPtr->type == OBJECT_TYPE_USER ) ) || \
		  ( checkType == ACCESS_CHECK_KEYACCESS && \
		    objectInfoPtr->type == OBJECT_TYPE_CONTEXT ) );

	return( CRYPT_OK );
	}

/* Get a pointer to an object's data from its handle */

int getObject( const int objectHandle, const OBJECT_TYPE type,
			   const ACCESS_CHECK_TYPE checkType, void **objectPtr, 
			   const int errorCode )
	{
	OBJECT_INFO *objectTable = krnlData->objectTable;
	OBJECT_INFO *objectInfoPtr;
	int status = CRYPT_OK;

	/* Preconditions: It's a valid object */
	PRE( isValidHandle( objectHandle ) && \
		 objectHandle != SYSTEM_OBJECT_HANDLE );
	PRE( isValidType( type ) && \
		 ( type == OBJECT_TYPE_CONTEXT || type == OBJECT_TYPE_CERTIFICATE || \
		   type == OBJECT_TYPE_DEVICE || type == OBJECT_TYPE_USER ) );
	PRE( checkType == ACCESS_CHECK_EXTERNAL || \
		 checkType == ACCESS_CHECK_KEYACCESS );
	PRE( isWritePtr( objectPtr, sizeof( void * ) ) );

	/* Clear the return value */
	*objectPtr = NULL;

	MUTEX_LOCK( objectTable );

	/* Perform similar access checks to the ones performed in
	   krnlSendMessage(), as well as situation-specific additional checks 
	   for correct object types */
	status = checkAccessValid( objectHandle, checkType, errorCode );
	if( cryptStatusError( status ) )
		{
		MUTEX_UNLOCK( objectTable );
		assert( NOTREACHED );
		return( status );
		}

	/* Perform additional checks for correct object types */
	if( objectHandle == SYSTEM_OBJECT_HANDLE || \
		objectTable[ objectHandle ].type != type )
		{
		MUTEX_UNLOCK( objectTable );
		assert( NOTREACHED );
		return( errorCode );
		}

	/* It's a valid object, get its info */
	objectInfoPtr = &objectTable[ objectHandle ];

	/* Inner precondition: The object is of the requested type */
	PRE( objectInfoPtr->type == type && \
		 ( objectInfoPtr->type == OBJECT_TYPE_CONTEXT || \
		   objectInfoPtr->type == OBJECT_TYPE_CERTIFICATE || \
		   objectInfoPtr->type == OBJECT_TYPE_DEVICE || \
		   objectInfoPtr->type == OBJECT_TYPE_USER ) );

	/* If the object is busy, wait for it to become available */
	if( isInUse( objectHandle ) && !isObjectOwner( objectHandle ) )
		status = waitForObject( objectHandle, &objectInfoPtr );
	if( cryptStatusOK( status ) )
		{
		objectInfoPtr->lockCount++;
#ifdef USE_THREADS
		objectInfoPtr->lockOwner = THREAD_SELF();
#endif /* USE_THREADS */
		*objectPtr = objectInfoPtr->objectPtr;
		}

	MUTEX_UNLOCK( objectTable );
	return( status );
	}

/* Release an object that we previously acquired directly.  Note that we can
   release the system object here (done when we don't need it any more but
   need to carry out further operations with other objects), but we can't
   ever acquire it */

static int releaseObject( const int objectHandle,
						  const ACCESS_CHECK_TYPE checkType )
	{
	OBJECT_INFO *objectTable = krnlData->objectTable;
	OBJECT_INFO *objectInfoPtr;
	int status;
	DECLARE_ORIGINAL_INT( lockCount );

	MUTEX_LOCK( objectTable );

	/* Preconditions: It's a valid object in use by the caller */
	PRE( isValidObject( objectHandle ) );
	PRE( isInUse( objectHandle ) && isObjectOwner( objectHandle ) );
	PRE( checkType == ACCESS_CHECK_EXTERNAL_RELEASE || \
		 checkType == ACCESS_CHECK_KEYACCESS );

	/* Perform similar access checks to the ones performed in
	   krnlSendMessage(), as well as situation-specific additional checks 
	   for correct object types */
	status = checkAccessValid( objectHandle, checkType, 
							   CRYPT_ERROR_PERMISSION );
	if( cryptStatusError( status ) )
		{
		MUTEX_UNLOCK( objectTable );
		assert( NOTREACHED );
		return( status );
		}

	/* Perform additional checks for correct object types.  The ownership 
	   check in checkAccessValid() checks whether the current thread is the
	   overall object owner, isObjectOwner() checks whether the current 
	   thread owns the current lock on the object */
	if( !isInUse( objectHandle ) || !isObjectOwner( objectHandle ) )
		{
		MUTEX_UNLOCK( objectTable );
		assert( NOTREACHED );

⌨️ 快捷键说明

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