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

📄 int_msg.c

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

#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;

/****************************************************************************
*																			*
*								Dependency ACLs								*
*																			*
****************************************************************************/

/* The ACL tables for each object dependency type */

static const FAR_BSS DEPENDENCY_ACL dependencyACLTbl[] = {
	/* Envelopes and sessions can have conventional encryption and MAC 
	   contexts attached */
	MK_DEPACL( OBJECT_TYPE_ENVELOPE, ST_NONE, ST_ENV_ANY, \
			   OBJECT_TYPE_CONTEXT, ST_CTX_CONV | ST_CTX_MAC, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_SESSION, ST_NONE, ST_SESS_ANY, \
			   OBJECT_TYPE_CONTEXT, ST_CTX_CONV | ST_CTX_MAC, ST_NONE ),	

	/* PKC contexts can have certs attached and vice versa.  Since the 
	   certificate can change the permissions on the context, we set the
	   DEP_FLAG_UPDATEDEP flag to ensure that the cert permissions get
	   reflected onto the context */
	MK_DEPACL_EX( OBJECT_TYPE_CONTEXT, ST_CTX_PKC, ST_NONE, \
				  OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, 
				  DEP_FLAG_UPDATEDEP ),
	MK_DEPACL_EX( OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, \
				  OBJECT_TYPE_CONTEXT, ST_CTX_PKC, ST_NONE,
				  DEP_FLAG_UPDATEDEP ),

	/* Contexts can have crypto devices attached */
	MK_DEPACL_EX( OBJECT_TYPE_CONTEXT, ST_CTX_ANY, ST_NONE, \
				  OBJECT_TYPE_DEVICE, ST_DEV_ANY_STD, ST_NONE,
				  DEP_FLAG_MORE ),

	/* Anything can have the system device attached, since all objects not
	   created via crypto devices are created via the system device */
	MK_DEPACL( OBJECT_TYPE_CONTEXT, ST_CTX_ANY, ST_NONE, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_CERTIFICATE, ST_CERT_ANY, ST_NONE, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_KEYSET, ST_KEYSET_ANY, ST_NONE, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_ENVELOPE, ST_NONE, ST_ENV_ANY, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_SESSION, ST_NONE, ST_SESS_ANY, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_DEVICE, ST_DEV_ANY_STD, ST_NONE, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),	
	MK_DEPACL( OBJECT_TYPE_USER, ST_NONE, ST_USER_ANY, \
			   OBJECT_TYPE_DEVICE, ST_DEV_SYSTEM, ST_NONE ),

	MK_DEPACL_END()
	};

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

/* Update an action permission.  This implements a ratchet that only allows
   permissions to be made more restrictive after they've initially been set,
   so that once a permission is set to a given level it can't be set back to 
   a less restrictive one (i.e. it's a write-up policy) */

static int updateActionPerms( int currentPerm, const int newPerm )
	{
	int permMask = ACTION_PERM_MASK, i;

	/* For each permission, update its value if the new setting is more
	   restrictive than the current one.  Since smaller values are more
	   restrictive, we can do a simple range comparison and replace the
	   existing value if it's larger than the new one */
	for( i = 0; i < ACTION_PERM_COUNT; i++ )
		{
		if( ( newPerm & permMask ) < ( currentPerm & permMask ) )
			currentPerm = ( currentPerm & ~permMask ) | ( newPerm & permMask );
		permMask <<= ACTION_PERM_BITS;
		}

	/* Postcondition: The new permission is at least as restrictive (or more
	   so) than the old one */
	FORALL( i, 0, ACTION_PERM_COUNT,
			( currentPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) <= \
				( newPerm & ( ACTION_PERM_MASK << ( i * ACTION_PERM_BITS ) ) ) );

	return( currentPerm );
	}

/* Update the action permissions for an object based on the composite
   permissions for it and a dependent object.  This is a special-case
   function because it has to operate with the object table unlocked.  This
   is necessary because the dependent object may be owned by another thread,
   and if we were to leave the object table locked the two would deadlock if
   we were sending the object a message while owning the object table at the
   same time that the other thread was sending a message while owning the 
   object.

   There is one (rather unlikely) potential race condition possible here in 
   which the object is destroyed and replaced by a new one while the object 
   table is unlocked, so we end up updating the action permissions for a 
   different object.  To protect against this, we check the unique ID after 
   we re-lock the object table to make sure that it's the same object */

static int updateDependentObjectPerms( const CRYPT_HANDLE objectHandle,
									   const CRYPT_HANDLE dependentObject )
	{
	const OBJECT_INFO *objectTable = krnlData->objectTable;
	const OBJECT_TYPE objectType = objectTable[ objectHandle ].type;
	const CRYPT_CONTEXT contextHandle = \
		( objectType == OBJECT_TYPE_CONTEXT ) ? objectHandle : dependentObject;
	const CRYPT_CERTIFICATE certHandle = \
		( objectType == OBJECT_TYPE_CERTIFICATE ) ? objectHandle : dependentObject;
	const unsigned int uniqueID = objectTable[ objectHandle ].uniqueID;
	int actionFlags = 0, status;
	ORIGINAL_INT_VAR( oldPerm, objectTable[ contextHandle ].actionFlags );

	/* Preconditions: Objects are valid, one is a cert and the other a
	   context, and they aren't dependent on each other (which would create
	   a dependency update loop).  Note that these checks aren't performed
	   at runtime since they've already been performed by the calling 
	   function, all we're doing here is establishing preconditions rather
	   than performing actual parameter checking */
	PRE( isValidObject( objectHandle ) );
	PRE( isValidHandle( dependentObject ) );
	PRE( ( objectTable[ objectHandle ].type == OBJECT_TYPE_CONTEXT && \
		   objectTable[ dependentObject ].type == OBJECT_TYPE_CERTIFICATE ) || \
		 ( objectTable[ objectHandle ].type == OBJECT_TYPE_CERTIFICATE && \
		   objectTable[ dependentObject ].type == OBJECT_TYPE_CONTEXT ) );
	PRE( objectTable[ objectHandle ].dependentObject != dependentObject || \
		 objectTable[ dependentObject ].dependentObject != objectHandle );

	/* Since we're about to send messages to the dependent object, we have to
	   unlock the object table */
	MUTEX_UNLOCK( objectTable );

	/* Make sure that we're not making a private key dependent on a cert, 
	   which is a public-key object.  We check this here rather than having
	   the caller check it because it requires having the object table
	   unlocked */
	if( objectType == OBJECT_TYPE_CERTIFICATE && \
		cryptStatusOK( \
			krnlSendMessage( dependentObject, IMESSAGE_CHECK, NULL,
							 MESSAGE_CHECK_PKC_PRIVATE ) ) )
		{
		assert( NOTREACHED );
		MUTEX_LOCK( objectTable );
		return( CRYPT_ARGERROR_OBJECT );
		}

	/* For each action type, enable its continued use only if the cert
	   allows it.  Because the certificate may not have been fully 
	   initialised yet (for example if we're attaching a context to a
	   cert that's in the process of being created), we have to perform 
	   a passive-container action-available check that also works on a 
	   low-state object rather than a standard active-object check.
	   
	   Because a key with a certificate attached indicates that it's 
	   (probably) being used for some function that involves interaction 
	   with a relying party (i.e. that it probably has more value than a raw
	   key with no strings attached), we set the action permission to
	   ACTION_PERM_NONE_EXTERNAL rather than allowing ACTION_PERM_ALL.  This
	   both ensures that it's only used in a safe manner via the cryptlib
	   internal mechanisms, and makes sure that it's not possible to utilize
	   the signature/encryption duality of some algorithms to create a
	   signature where it's been disallowed */
	if( cryptStatusOK( krnlSendMessage( certHandle,
				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_SIGN_AVAIL ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_SIGCHECK_AVAIL ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_ENCRYPT_AVAIL ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_DECRYPT_AVAIL ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_KA_EXPORT_AVAIL ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( cryptStatusOK( krnlSendMessage( certHandle,
				IMESSAGE_CHECK, NULL, MESSAGE_CHECK_PKC_KA_IMPORT_AVAIL ) ) )
		actionFlags |= \
			MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );

	/* Inner precondition: The usage shouldn't be all-zero.  Technically it 
	   can be since there are bound to be certs out there broken enough to do
	   this, and certainly under the stricter compliance levels this *will* 
	   happen, so we make it a warning that's only produced in debug mode */
	PRE( actionFlags != 0 );

	/* We're done querying the dependent object, re-lock the object table and
	   make sure that the original object hasn't been touched */
	MUTEX_LOCK( objectTable );
	if( objectTable[ objectHandle ].uniqueID != uniqueID )
		return( CRYPT_ERROR_SIGNALLED );
	status = setPropertyAttribute( contextHandle, CRYPT_IATTRIBUTE_ACTIONPERMS,
								   &actionFlags );

	/* Postcondition: The new permission is at least as restrictive (or more
	   so) than the old one */
	FORALL( i, 0, ACTION_PERM_COUNT,
			( objectTable[ contextHandle ].actionFlags & ( ACTION_PERM_MASK << ( i * 2 ) ) ) <= \
			( ORIGINAL_VALUE( oldPerm ) & ( ACTION_PERM_MASK << ( i * 2 ) ) ) );

	return( status );
	}

/****************************************************************************
*																			*
*							Init/Shutdown Functions							*
*																			*
****************************************************************************/

int initInternalMsgs( KERNEL_DATA *krnlDataPtr )
	{
	int i;

	/* Perform a consistency check on the object dependency ACL */
	for( i = 0; dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE; i++ )
		{
		const DEPENDENCY_ACL *dependencyACL = &dependencyACLTbl[ i ];

		if( dependencyACL->type <= OBJECT_TYPE_NONE || \
			dependencyACL->type >= OBJECT_TYPE_LAST || \
			dependencyACL->dType <= OBJECT_TYPE_NONE || \
			dependencyACL->dType >= OBJECT_TYPE_LAST )
			return( CRYPT_ERROR_FAILED );
		if( ( dependencyACL->subTypeA & SUBTYPE_CLASS_B ) || \
			( dependencyACL->subTypeB & SUBTYPE_CLASS_A ) || \
			( dependencyACL->dSubTypeA & SUBTYPE_CLASS_B ) || \
			( dependencyACL->dSubTypeB & SUBTYPE_CLASS_A ) )
			return( CRYPT_ERROR_FAILED );
		}

	/* Set up the reference to the kernel data block */
	krnlData = krnlDataPtr;

	return( CRYPT_OK );
	}

void endInternalMsgs( void )
	{
	krnlData = NULL;
	}

/****************************************************************************
*																			*
*							Get/Set Property Attributes						*
*																			*
****************************************************************************/

/* Get/set object property attributes.  We differentiate between a small
   number of user-accessible properties such as the object's owner, and
   properties that are only accessible by cryptlib.  The user-accessible
   properties can be locked, which makes them immutable (at least to being
   explicitly set, they can still be implicitly altered, for example setting
   a new object owner decrements the forwardcount value) and also unreadable
   by the user */

int getPropertyAttribute( const int objectHandle,
						  const CRYPT_ATTRIBUTE_TYPE attribute,
						  void *messageDataPtr )
	{
	const OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
	int *valuePtr = ( int * ) messageDataPtr;

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );
	PRE( attribute == CRYPT_PROPERTY_OWNER || \
		 attribute == CRYPT_PROPERTY_FORWARDCOUNT || \
		 attribute == CRYPT_PROPERTY_LOCKED || \
		 attribute == CRYPT_PROPERTY_USAGECOUNT || \
		 attribute == CRYPT_IATTRIBUTE_TYPE || \
		 attribute == CRYPT_IATTRIBUTE_SUBTYPE || \
		 attribute == CRYPT_IATTRIBUTE_STATUS || \
		 attribute == CRYPT_IATTRIBUTE_INTERNAL || \
		 attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );
	PRE( isWritePtr( messageDataPtr, sizeof( int ) ) );

	switch( attribute )
		{
		/* User-accessible properties */
		case CRYPT_PROPERTY_OWNER:
			/* We allow this to be read since its value can be determined
			   anyway with a trial access */
			if( !( objectInfoPtr->flags & OBJECT_FLAG_OWNED ) )
				return( CRYPT_ERROR_NOTINITED );
#ifdef USE_THREADS
  #ifdef NONSCALAR_THREADS
			/* A very small number of pthreads implementations use non-

⌨️ 快捷键说明

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