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 + -
显示快捷键?