cryptkrn.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,648 行 · 第 1/5 页

C
1,648
字号
	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 */

static int updateDependentObjectPerms( const CRYPT_HANDLE objectHandle,
									   const CRYPT_HANDLE dependentObject )
	{
	const CRYPT_CONTEXT contextHandle = \
		( objectTable[ objectHandle ].type == OBJECT_TYPE_CONTEXT ) ? \
		objectHandle : dependentObject;
	int actionFlags = 0, status;
	ORIGINAL_INT_VAR( oldPerm, objectTable[ contextHandle ].actionFlags );

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );
	PRE( isValidHandle( dependentObject ) );

	/* For each action type, enable its continued use only if the cert
	   allows it (we send the permission query message to the objectHandle
	   no matter what it is since it'll be forwarded to the appropriate
	   objects by the kernel).  The actions specified as ACTION_PERM_ALL
	   will remain unchanged (since we can only further constrain existing
	   usage), ACTION_PERM_NONE_EXTERNAL will be constrained if they're
	   currently ACTION_PERM_ALL, and all other actions will be disabled */
	if( !cryptStatusError( krnlSendMessage( objectHandle,
			RESOURCE_IMESSAGE_CHECK, NULL, RESOURCE_MESSAGE_CHECK_PKC_SIGN ) ) )
		actionFlags |= \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN, ACTION_PERM_NONE_EXTERNAL );
	if( !cryptStatusError( krnlSendMessage( objectHandle,
			RESOURCE_IMESSAGE_CHECK, NULL, RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK ) ) )
		actionFlags |= \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK, ACTION_PERM_NONE_EXTERNAL );
	if( !cryptStatusError( krnlSendMessage( objectHandle,
			RESOURCE_IMESSAGE_CHECK, NULL, RESOURCE_MESSAGE_CHECK_PKC_ENCRYPT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( !cryptStatusError( krnlSendMessage( objectHandle,
			RESOURCE_IMESSAGE_CHECK, NULL, RESOURCE_MESSAGE_CHECK_PKC_DECRYPT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( !cryptStatusError( krnlSendMessage( objectHandle,
			RESOURCE_IMESSAGE_CHECK, NULL, RESOURCE_MESSAGE_CHECK_PKC_KA_EXPORT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL );
	if( !cryptStatusError( krnlSendMessage( objectHandle,
			RESOURCE_IMESSAGE_CHECK, NULL, RESOURCE_MESSAGE_CHECK_PKC_KA_IMPORT ) ) )
		actionFlags |= \
			MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
	status = krnlSendMessage( contextHandle, RESOURCE_IMESSAGE_SETATTRIBUTE,
							  &actionFlags, CRYPT_IATTRIBUTE_ACTIONPERMS );

	/* 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_VAR( oldPerm ) & ( ACTION_PERM_MASK << ( i * 2 ) ) ) );

	return( status );
	}

/* Get/set object property attributes.  We differentiate between a small
   number of user-accessible properties such as the object's owner, and
   properties which 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 forwardable counter) and also unreadable
   by the user */

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

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );
	PRE( attribute == CRYPT_PROPERTY_OWNER || \
		 attribute == CRYPT_PROPERTY_FORWARDABLE || \
		 attribute == CRYPT_PROPERTY_LOCKED || \
		 attribute == CRYPT_PROPERTY_USAGECOUNT || \
		 attribute == CRYPT_IATTRIBUTE_TYPE || \
		 attribute == CRYPT_IATTRIBUTE_STATUS || \
		 attribute == CRYPT_IATTRIBUTE_INTERNAL || \
		 attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );
	PRE( messageDataPtr != NULL );

	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 */
			*valuePtr = ( int ) getObjectOwnership( objectInfoPtr );
			break;

		case CRYPT_PROPERTY_FORWARDABLE:
			if( objectInfoPtr->flags & OBJECT_FLAG_LOCKED )
				return( CRYPT_ERROR_PERMISSION );
			*valuePtr = objectInfoPtr->forwardCount;
			break;

		case CRYPT_PROPERTY_LOCKED:
			/* We allow this to be read since its value can be determined
			   anyway with a trial write */
			*( ( BOOLEAN * ) messageDataPtr ) = \
						( objectInfoPtr->flags & OBJECT_FLAG_LOCKED ) ? \
						TRUE : FALSE;
			break;

		case CRYPT_PROPERTY_USAGECOUNT:
			*valuePtr = objectInfoPtr->usageCount;
			break;

		/* Internal properties */
		case CRYPT_IATTRIBUTE_TYPE :
			*valuePtr = objectInfoPtr->type;
			break;

		case CRYPT_IATTRIBUTE_STATUS:
			*valuePtr = objectInfoPtr->flags & OBJECT_FLAGMASK_STATUS;
			break;

		case CRYPT_IATTRIBUTE_INTERNAL:
			*( ( BOOLEAN * ) messageDataPtr ) = \
					( objectInfoPtr->flags & OBJECT_FLAG_INTERNAL ) ? \
					TRUE : FALSE;
			break;

		case CRYPT_IATTRIBUTE_ACTIONPERMS:
			*valuePtr = objectInfoPtr->actionFlags;
			break;

		default:
			assert( NOTREACHED );
		}

	return( CRYPT_OK );
	}

static int setPropertyAttribute( const int objectHandle,
								 const CRYPT_ATTRIBUTE_TYPE attribute,
								 void *messageDataPtr )
	{
	OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
	const int value = *( ( int * ) messageDataPtr );

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );
	PRE( attribute == CRYPT_PROPERTY_OWNER || \
		 attribute == CRYPT_PROPERTY_FORWARDABLE || \
		 attribute == CRYPT_PROPERTY_LOCKED || \
		 attribute == CRYPT_PROPERTY_USAGECOUNT || \
		 attribute == CRYPT_IATTRIBUTE_STATUS || \
		 attribute == CRYPT_IATTRIBUTE_INTERNAL || \
		 attribute == CRYPT_IATTRIBUTE_ACTIONPERMS );
	PRE( messageDataPtr != NULL );
	PRE( objectHandle >= NO_SYSTEM_OBJECTS || \
		 attribute == CRYPT_IATTRIBUTE_STATUS );

	switch( attribute )
		{
		/* User-accessible properties */
		case CRYPT_PROPERTY_OWNER:
			/* This property can still be changed (even if the object is
			   locked) until the forwarding count drops to zero, otherwise
			   locking the object would prevent any forwarding */
			if( objectInfoPtr->forwardCount != CRYPT_UNUSED )
				{
				if( objectInfoPtr->forwardCount <= 0 )
					return( CRYPT_ERROR_PERMISSION );
				objectInfoPtr->forwardCount--;
				}
			setObjectOwnership( objectInfoPtr, value );
			break;

		case CRYPT_PROPERTY_FORWARDABLE:
			if( objectInfoPtr->flags & OBJECT_FLAG_LOCKED )
				return( CRYPT_ERROR_PERMISSION );
			objectInfoPtr->forwardCount = value;
			break;

		case CRYPT_PROPERTY_LOCKED:
			/* Precondition: This property can only be set to true */
			PRE( *( ( BOOLEAN * ) messageDataPtr ) );

			objectInfoPtr->flags |= OBJECT_FLAG_LOCKED;
			break;

		case CRYPT_PROPERTY_USAGECOUNT:
			if( ( objectInfoPtr->flags & OBJECT_FLAG_LOCKED ) || \
				( objectInfoPtr->usageCount != CRYPT_UNUSED ) )
				return( CRYPT_ERROR_PERMISSION );
			objectInfoPtr->usageCount = value;
			break;

		/* Internal properties */
		case CRYPT_IATTRIBUTE_STATUS:
			/* We're clearing an error/abnormal state or setting the object
			   to the busy state */
			PRE( value == CRYPT_OK || value == CRYPT_ERROR_BUSY );

			if( isInvalidObjectState( objectHandle ) )
				{
				/* If the object is in an abnormal state, we can only (try to)
				   return it back to the normal state after the problem is
				   resolved */
				PRE( value == CRYPT_OK );

				/* If we're resetting the object status from busy to OK,
				   notify the object in case there's any extra processing to
				   be done */
				if( objectInfoPtr->flags & OBJECT_FLAG_BUSY )
					{
					/* Precondition: Only contexts can be busy */
					PRE( objectInfoPtr->type == OBJECT_TYPE_CONTEXT );

					/* If the notification returns an error, the object is
					   still performing some sort of processing (eg cleanup/
					   shutdown), don't reset the status (it'll be done later
					   when the object is ready) */
					if( objectInfoPtr->messageFunction( objectHandle,
								RESOURCE_MESSAGE_CHANGENOTIFY, messageDataPtr,
								CRYPT_IATTRIBUTE_STATUS ) == CRYPT_OK )
						objectInfoPtr->flags &= ~OBJECT_FLAG_BUSY;
					break;
					}

				/* If we're processing a notification from the caller that
				   the object init is complete and the object was destroyed
				   while it was being created (which sets its state to
				   CRYPT_ERROR_SIGNALLED), tell the caller to convert the
				   message to a destroy object message unless it's the system
				   object, which can't be explicitly destroyed.  In this case
				   we just return an error so the cryptlib init fails */
				if( objectInfoPtr->flags & OBJECT_FLAG_SIGNALLED )
					return( ( objectHandle < NO_SYSTEM_OBJECTS ) ?
							CRYPT_ERROR_SIGNALLED : OK_SPECIAL );

				/* We're transitioning the object to the initialised state */
				PRE( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED );
				objectInfoPtr->flags &= ~OBJECT_FLAG_NOTINITED;
				POST( !( objectInfoPtr->flags & OBJECT_FLAG_NOTINITED ) );
				break;
				}

			/* Inner precondition: The object is in a valid state */
			PRE( !isInvalidObjectState( objectHandle ) );

			/* We're setting the object's busy flag because it's about to
			   perform an async op */
			if( value == CRYPT_ERROR_BUSY )
				objectInfoPtr->flags |= OBJECT_FLAG_BUSY;
			break;

		case CRYPT_IATTRIBUTE_INTERNAL:
			if( *( ( BOOLEAN * ) messageDataPtr ) )
				objectInfoPtr->flags |= OBJECT_FLAG_INTERNAL;
			else
				objectInfoPtr->flags &= ~OBJECT_FLAG_INTERNAL;
			break;

		case CRYPT_IATTRIBUTE_ACTIONPERMS:
			objectInfoPtr->actionFlags = \
					updateActionPerms( objectInfoPtr->actionFlags, value );
			break;

		default:
			assert( NOTREACHED );
		}

	return( CRYPT_OK );
	}

/* Increment/decrement the reference count for an object.  This adjusts the
   reference count as appropriate and sends destroy messages if the reference
   count goes negative */

static int incRefCount( const int objectHandle, const int dummy1,
						const void *dummy2 )
	{
	ORIGINAL_INT_VAR( refCt, objectTable[ objectHandle ].referenceCount );

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );

	/* Increment an object's reference count */
	objectTable[ objectHandle ].referenceCount++;

	/* Postcondition: We incremented the reference count and it's now greater
	   than zero (the ground state) */
	POST( objectTable[ objectHandle ].referenceCount >= 1 );
	POST( objectTable[ objectHandle ].referenceCount == \
		  ORIGINAL_VALUE_VAR( refCt ) + 1 );

	return( CRYPT_OK );
	}

static int decRefCount( const int objectHandle, const int dummy1,
						const void *dummy2 )
	{
	ORIGINAL_INT_VAR( refCt, objectTable[ objectHandle ].referenceCount );

	/* Preconditions */
	PRE( isValidObject( objectHandle ) );

	/* Decrement an object's reference count */
	if( objectTable[ objectHandle ].referenceCount )
		{

⌨️ 快捷键说明

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