📄 int_msg.c
字号:
POST( isInternalObject( objectHandle ) );
}
/* Decrement an object's reference count */
if( objectTable[ objectHandle ].referenceCount > 0 )
{
objectTable[ objectHandle ].referenceCount--;
/* Postconditions: We decremented the reference count and it's
greater than or equal to zero (the ground state) */
POST( objectTable[ objectHandle ].referenceCount >= 0 );
POST( objectTable[ objectHandle ].referenceCount == \
ORIGINAL_VALUE( refCt ) - 1 );
return( CRYPT_OK );
}
/* We're already at a single reference, destroy the object. Since this
can entail arbitrary amounts of processing during the object shutdown
phase, we have to unlock the object table around the call */
MUTEX_UNLOCK( objectTable );
status = krnlSendNotifier( objectHandle, IMESSAGE_DESTROY );
MUTEX_LOCK( objectTable );
return( status );
}
/* Get/set dependent objects for an object */
int getDependentObject( const int objectHandle, const int targetType,
const void *messageDataPtr, const BOOLEAN dummy )
{
int *valuePtr = ( int * ) messageDataPtr, localObjectHandle;
/* Preconditions */
PRE( isValidObject( objectHandle ) );
PRE( isValidType( targetType ) );
PRE( messageDataPtr != NULL );
/* Clear return value */
*valuePtr = CRYPT_ERROR;
localObjectHandle = findTargetType( objectHandle, targetType );
if( cryptStatusError( localObjectHandle ) )
{
/* Postconditions: No dependent object found */
POST( *valuePtr == CRYPT_ERROR );
return( CRYPT_ARGERROR_OBJECT );
}
*valuePtr = localObjectHandle;
/* Postconditions: We found a dependent object */
POST( isValidObject( *valuePtr ) && \
isSameOwningObject( objectHandle, *valuePtr ) );
return( CRYPT_OK );
}
int setDependentObject( const int objectHandle, const int incReferenceCount,
const void *messageDataPtr, const BOOLEAN dummy )
{
OBJECT_INFO *objectTable = krnlData->objectTable;
OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
const OBJECT_INFO *dependentObjectInfoPtr = &objectTable[ objectHandle ];
const int dependentObject = *( ( int * ) messageDataPtr );
const DEPENDENCY_ACL *dependencyACL = NULL;
int *objectHandlePtr, i, status;
/* Preconditions: Parameters are valid */
PRE( isValidObject( objectHandle ) );
PRE( incReferenceCount == TRUE || incReferenceCount == FALSE );
PRE( isValidHandle( dependentObject ) );
/* Make sure that the object is valid, it may have been signalled after
the message was sent */
if( !isValidObject( dependentObject ) )
return( CRYPT_ERROR_SIGNALLED );
dependentObjectInfoPtr = &objectTable[ dependentObject ];
objectHandlePtr = ( dependentObjectInfoPtr->type == OBJECT_TYPE_DEVICE ) ? \
&objectInfoPtr->dependentDevice : &objectInfoPtr->dependentObject;
/* Basic validity checks: There can't already be a dependent object set */
if( *objectHandlePtr != CRYPT_ERROR )
{
/* There's already a dependent object present and we're trying to
overwrite it with a new one, something is seriously wrong */
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* More complex validity checks to ensure that the object table is
consistent: The object isn't already dependent on the dependent object
(making the dependent object then dependent on the object would
create a loop), and the object won't be dependent on its own object
type unless it's a device dependent on the system device */
if( ( ( ( objectInfoPtr->type == OBJECT_TYPE_DEVICE ) ? \
dependentObjectInfoPtr->dependentDevice : \
dependentObjectInfoPtr->dependentObject ) == objectHandle ) || \
( objectInfoPtr->type == dependentObjectInfoPtr->type && \
dependentObject != SYSTEM_OBJECT_HANDLE ) )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* Find the dependency ACL entry for this object/dependent object
combination. Since there can be more than one dependent object
type for an object, we check subtypes as well */
for( i = 0; dependencyACLTbl[ i ].type != OBJECT_TYPE_NONE; i++ )
if( dependencyACLTbl[ i ].type == objectInfoPtr->type && \
dependencyACLTbl[ i ].dType == dependentObjectInfoPtr->type && \
( isValidSubtype( dependencyACLTbl[ i ].dSubTypeA, \
dependentObjectInfoPtr->subType ) || \
isValidSubtype( dependencyACLTbl[ i ].dSubTypeB, \
dependentObjectInfoPtr->subType ) ) )
{
dependencyACL = &dependencyACLTbl[ i ];
break;
}
if( dependencyACL == NULL )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* Inner precondition: We have the appropriate ACL for this combination
of object and dependent object */
PRE( dependencyACL->type == objectInfoPtr->type && \
dependencyACL->dType == dependentObjectInfoPtr->type && \
( isValidSubtype( dependencyACL->dSubTypeA, \
dependentObjectInfoPtr->subType ) || \
isValidSubtype( dependencyACL->dSubTypeB, \
dependentObjectInfoPtr->subType ) ) );
/* Type-specific checks. For PKC context -> cert and cert -> PKC context
attaches we should also check that the primary PKC object is a
private-key object and the dependent PKC object is a public-key object
to catch things like a private key depending on a (public-key) cert,
however this requires unlocking the object table in order to send the
context a check message. Since this requires additional precautions,
we leave it for updateDependentObjectPerms(), which has to unlock the
table for its own update operations */
if( !isValidSubtype( dependencyACL->subTypeA, \
objectInfoPtr->subType ) && \
!isValidSubtype( dependencyACL->subTypeB, \
objectInfoPtr->subType ) )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
if( !isValidSubtype( dependencyACL->dSubTypeA, \
dependentObjectInfoPtr->subType ) && \
!isValidSubtype( dependencyACL->dSubTypeB, \
dependentObjectInfoPtr->subType ) )
{
assert( NOTREACHED );
return( CRYPT_ARGERROR_VALUE );
}
/* Inner precondition */
PRE( *objectHandlePtr == CRYPT_ERROR );
PRE( isSameOwningObject( objectHandle, dependentObject ) );
/* Certs and contexts have special relationships in that the cert can
constrain the use of the context beyond its normal level. If we're
performing this type of object attachment, we have to adjust one
object's behaviour based on the permissions of the other one. We do
this before we increment the reference count because the latter can
never fail so we don't have to worry about undoing the update */
if( dependencyACL->flags & DEP_FLAG_UPDATEDEP )
{
status = updateDependentObjectPerms( objectHandle, dependentObject );
if( cryptStatusError( status ) )
return( status );
}
/* Update the dependent object's reference count if required and record
the new status in the object table. Dependent objects can be
established in one of two ways, by taking an existing object and
attaching it to another object (which increments its reference count,
since it's now being referred to by the original owner and by the
object it's attached to), or by creating a new object and attaching
it to another object (which doesn't increment the reference count
since it's only referred to by the controlling object). An example of
the former operation is adding a context from a cert request to a cert
(the cert request is referenced by both the caller and the cert), an
example of the latter operation is attaching a data-only cert to a
context (the cert is only referenced by the context) */
if( incReferenceCount )
{
status = incRefCount( dependentObject, 0, NULL, TRUE );
if( cryptStatusError( status ) )
return( status );
}
*objectHandlePtr = dependentObject;
/* Postconditions */
POST( isValidObject( *objectHandlePtr ) && \
isSameOwningObject( objectHandle, *objectHandlePtr ) );
return( CRYPT_OK );
}
/* Clone an object. The older copy-on-write implementation didn't actually
do anything at this point except check that the access was valid and set
the aliased and cloned flags to indicate that the object needed to be
handled specially if a write access was made to it, but with the kernel
tracking instance data we can do a copy immediately to create two
distinct objects */
int cloneObject( const int objectHandle, const int clonedObject,
const void *dummy1, const BOOLEAN dummy2 )
{
OBJECT_INFO *objectInfoPtr = &krnlData->objectTable[ objectHandle ];
OBJECT_INFO *clonedObjectInfoPtr = &krnlData->objectTable[ clonedObject ];
int actionFlags, status;
/* Preconditions */
PRE( isValidObject( objectHandle ) && \
objectHandle >= NO_SYSTEM_OBJECTS );
PRE( !isClonedObject( objectHandle ) && \
!isAliasedObject( objectHandle ) );
PRE( objectInfoPtr->type == OBJECT_TYPE_CONTEXT );
PRE( isValidObject( clonedObject ) && \
clonedObject >= NO_SYSTEM_OBJECTS );
PRE( !isClonedObject( clonedObject ) && \
!isAliasedObject( clonedObject ) );
PRE( clonedObjectInfoPtr->type == OBJECT_TYPE_CONTEXT );
PRE( objectHandle != clonedObject );
/* Make sure that the original object is in the high state. This will
have been checked by the caller anyway, but we check again here to
make sure */
if( !isInHighState( objectHandle ) )
return( CRYPT_ERROR_NOTINITED );
/* 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 that 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 that they'll be
aware of potential problems with this approach */
if( objectInfoPtr->dependentDevice != SYSTEM_OBJECT_HANDLE )
return( incRefCount( objectHandle, 0, NULL, TRUE ) );
/* Since this is an internal-use-only object, lock down the action
permissions so that only encryption and hash actions from internal
sources are allowed (assuming they were allowed to begin with).
Keygen is disabled entirely (there should already be a key loaded),
and signing isn't possible with a non-PKC object anyway. This takes
advantage of the ratchet enforced for the action permissions, which
can only make them more restrictive than the existing permissions, to
avoid having to read and modify each permission individually */
actionFlags = \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_HASH, ACTION_PERM_NONE_EXTERNAL );
status = setPropertyAttribute( clonedObject, CRYPT_IATTRIBUTE_ACTIONPERMS,
&actionFlags );
if( cryptStatusError( status ) )
return( status );
/* Postcondition: The cloned object can only be used internally */
POST( ( clonedObjectInfoPtr->actionFlags & ~ACTION_PERM_NONE_EXTERNAL_ALL ) == 0 );
/* Inner precondition: The instance data is valid and ready to be
copied */
PRE( isWritePtr( objectInfoPtr->objectPtr, objectInfoPtr->objectSize ) );
PRE( isWritePtr( clonedObjectInfoPtr->objectPtr,
clonedObjectInfoPtr->objectSize ) );
PRE( objectInfoPtr->objectSize == clonedObjectInfoPtr->objectSize );
#if 0 /* 18/2/04 No need for copy-on-write any more since we can just copy
across the instance data referenced in the object table */
/* Mark the two objects as being aliases, and the (incomplete) clone as
a cloned object */
objectInfoPtr->flags |= OBJECT_FLAG_ALIASED;
objectInfoPtr->clonedObject = clonedObject;
clonedObjectInfoPtr->flags |= OBJECT_FLAG_ALIASED | OBJECT_FLAG_CLONE;
clonedObjectInfoPtr->clonedObject = objectHandle;
/* Postconditions: The objects are marked as aliased objects and the
cloned object as a clone */
POST( isAliasedObject( objectHandle ) && !isClonedObject( objectHandle ) );
POST( isAliasedObject( clonedObject ) && isClonedObject( clonedObject ) );
POST( !isClonedObject( clonedObjectInfoPtr->clonedObject ) );
POST( isClonedObject( objectInfoPtr->clonedObject ) );
POST( objectHandle != clonedObject );
#else
/* Copy across the object contents and reset any instance-specific
information. We only update the owning object if required, in
almost all cases this will be the system device so there's no need
to perform the update */
memcpy( clonedObjectInfoPtr->objectPtr, objectInfoPtr->objectPtr,
objectInfoPtr->objectSize );
objectInfoPtr->messageFunction( clonedObjectInfoPtr->objectPtr,
MESSAGE_CHANGENOTIFY,
( void * ) &clonedObject,
MESSAGE_CHANGENOTIFY_OBJHANDLE );
if( objectInfoPtr->owner != clonedObjectInfoPtr->owner )
objectInfoPtr->messageFunction( clonedObjectInfoPtr->objectPtr,
MESSAGE_CHANGENOTIFY,
&clonedObjectInfoPtr->owner,
MESSAGE_CHANGENOTIFY_OWNERHANDLE );
/* We've copied across the object's state, the cloned object is now
initialised ready for use */
clonedObjectInfoPtr->flags |= OBJECT_FLAG_HIGH;
#endif /* 0 */
return( CRYPT_OK );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -