cryptkrn.c
来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,648 行 · 第 1/5 页
C
1,648 行
* Message Routing *
* *
****************************************************************************/
/* Find the ultimate target of an object attribute manipulation message by
walking down the chain of controlling->dependent objects. For example a
message targeted at a device and sent to a certificate would be routed to
the cert's dependent object (which would typically be a context). The
device message targeted at the context would be routed to the context's
dependent device, which is its final destination */
static int findTargetType( const int originalObjectHandle, const int targets )
{
const OBJECT_TYPE target = targets & 0xFF;
const OBJECT_TYPE altTarget1 = ( targets >> 8 ) & 0xFF;
const OBJECT_TYPE altTarget2 = ( targets >> 16 ) & 0xFF;
OBJECT_TYPE type = objectTable[ originalObjectHandle ].type;
int objectHandle = originalObjectHandle;
int iterations = 0;
/* Preconditions: Source is a valid object, destination(s) are valid
target(s) */
PRE( isValidObject( objectHandle ) );
PRE( isValidType( target ) );
PRE( altTarget1 == OBJECT_TYPE_NONE || isValidType( altTarget1 ) );
PRE( altTarget2 == OBJECT_TYPE_NONE || isValidType( altTarget2 ) );
/* Route the request through any dependent objects as required until we
reach the required target object type. "And thou shalt make
loops..." -- Exodus 24:6 */
while( objectHandle != CRYPT_ERROR && \
!( target == type || \
( altTarget1 != OBJECT_TYPE_NONE && altTarget1 == type ) || \
( altTarget2 != OBJECT_TYPE_NONE && altTarget2 == type ) ) )
{
int newObjectHandle;
/* Loop invariants. "Fifty loops thou shalt make" -- Exodus 24:7
(some of the OT verses shouldn't be taken too literally,
apparently the 50 used here merely means "many" as in "more than
one or two" in the same way that "40 days and nights" is now
generally taken as meaning "Lots, but that's as far as we're
prepared to count") */
INV( isValidObject( objectHandle ) );
INV( iterations++ < 3 );
/* Try sending the message to the primary target */
if( target == OBJECT_TYPE_DEVICE && \
objectTable[ objectHandle ].dependentDevice != CRYPT_ERROR )
newObjectHandle = objectTable[ objectHandle ].dependentDevice;
else
newObjectHandle = objectTable[ objectHandle ].dependentObject;
/* Try whatever we got as the new object handle */
objectHandle = newObjectHandle;
if( objectHandle != CRYPT_ERROR )
type = objectTable[ objectHandle ].type;
/* If we've got a new object, it has the same owner as the original
target candidate */
POST( objectHandle == CRYPT_ERROR || \
isSameOwner( originalObjectHandle, objectHandle ) );
}
/* Postcondition: We ran out of options or we reached the target object */
POST( objectHandle == CRYPT_ERROR || \
( isValidObject( objectHandle ) && \
isSameOwner( originalObjectHandle, objectHandle ) && \
( target == type || \
( altTarget1 != OBJECT_TYPE_NONE && altTarget1 == type ) || \
( altTarget2 != OBJECT_TYPE_NONE && altTarget2 == type ) ) ) );
return( ( objectHandle == CRYPT_ERROR ) ? \
CRYPT_ARGERROR_OBJECT : objectHandle );
}
static int findCompareMessageTarget( const int originalObjectHandle,
const int messageValue )
{
OBJECT_TYPE targetType = OBJECT_TYPE_NONE;
int objectHandle = originalObjectHandle;
/* Preconditions */
PRE( isValidObject( objectHandle ) );
PRE( messageValue == RESOURCE_MESSAGE_COMPARE_HASH || \
messageValue == RESOURCE_MESSAGE_COMPARE_KEYID || \
messageValue == RESOURCE_MESSAGE_COMPARE_SUBJECT || \
messageValue == RESOURCE_MESSAGE_COMPARE_ISSUERANDSERIALNUMBER || \
messageValue == RESOURCE_MESSAGE_COMPARE_FINGERPRINT );
/* Determine the ultimate target type for the message. We don't check for
keysets, envelopes and sessions as dependent objects since this never
occurs */
switch( messageValue )
{
case RESOURCE_MESSAGE_COMPARE_HASH:
case RESOURCE_MESSAGE_COMPARE_KEYID:
targetType = OBJECT_TYPE_CONTEXT;
break;
case RESOURCE_MESSAGE_COMPARE_SUBJECT:
case RESOURCE_MESSAGE_COMPARE_ISSUERANDSERIALNUMBER:
case RESOURCE_MESSAGE_COMPARE_FINGERPRINT:
targetType = OBJECT_TYPE_CERTIFICATE;
break;
default:
assert( NOTREACHED );
}
/* Route the message through to the appropriate object */
objectHandle = findTargetType( objectHandle, targetType );
/* Postcondition */
POST( objectHandle == CRYPT_ARGERROR_OBJECT || \
( isValidObject( objectHandle ) && \
isSameOwner( originalObjectHandle, objectHandle ) ) );
return( objectHandle );
}
/* Sometimes a message is explicitly non-routable (ie it has to be sent
directly to the appropriate target object). The following function checks
that the target object is one of the required types */
static int checkTargetType( const int objectHandle, const int targets )
{
const OBJECT_TYPE target = targets & 0xFF;
const OBJECT_TYPE altTarget = targets >> 8;
/* Precondition: Source is a valid object, destination(s) are valid
target(s) */
PRE( isValidObject( objectHandle ) );
PRE( isValidType( target ) );
PRE( altTarget == OBJECT_TYPE_NONE || isValidType( altTarget ) );
/* Check whether the object matches the required type. We don't have to
check whether the alternative target has a value or not since the
object can never be a OBJECT_TYPE_NONE */
if( objectTable[ objectHandle ].type != target && \
objectTable[ objectHandle ].type != altTarget )
return( CRYPT_ERROR );
/* Postcondition */
POST( objectTable[ objectHandle ].type == target || \
objectTable[ objectHandle ].type == altTarget );
return( objectHandle );
}
/****************************************************************************
* *
* Message Pre-dispatch Handlers *
* *
****************************************************************************/
/* If it's a destroy object message, adjust the reference counts of any
dependent objects and set the object's state to signalled. We have to do
this before we send the destroy message to the object in order that any
further attempts to access it will fail. This avoids a race condition
where other threads may try to use the partially-destroyed object after
the object handler unlocks it but before it and the kernel finish
destroying it */
static int preDispatchSignalDependentObjects( const int objectHandle,
const RESOURCE_MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *dummy )
{
OBJECT_INFO *objectInfoPtr = &objectTable[ objectHandle ];
/* Precondition */
PRE( isValidObject( objectHandle ) && \
objectHandle >= NO_SYSTEM_OBJECTS );
if( objectInfoPtr->dependentDevice != CRYPT_ERROR )
/* Velisurmaaja */
decRefCount( objectInfoPtr->dependentDevice, 0, NULL );
if( objectInfoPtr->dependentObject != CRYPT_ERROR )
decRefCount( objectInfoPtr->dependentObject, 0, NULL );
objectInfoPtr->flags |= OBJECT_FLAG_SIGNALLED;
/* Postcondition: The object is now in the destroyed state as far as
other objects are concerned */
POST( objectInfoPtr->flags & OBJECT_FLAG_SIGNALLED );
return( CRYPT_OK );
}
/* If it's an attribute get/set/delete, check the access conditions for the
object and the message parameters */
static int preDispatchCheckAttributeAccess( const int objectHandle,
const RESOURCE_MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue,
const void *auxInfo )
{
static const OBJECT_INFO optionObjectInfo = \
{ OBJECT_TYPE_NONE + 1, NULL, 0, 0, ST_ANY };
const ATTRIBUTE_ACL *attributeACL = ( ATTRIBUTE_ACL * ) auxInfo;
const OBJECT_INFO *objectInfo = &objectTable[ objectHandle ];
const RESOURCE_MESSAGE_TYPE localMessage = message & RESOURCE_MESSAGE_MASK;
const int isHigh = ( objectInfo->flags & OBJECT_FLAG_HIGH ) ? TRUE : FALSE;
const int subType = objectInfo->subType;
int requiredAccess = \
isIncomingAttributeMessage( localMessage ) ? \
( ( isHigh ) ? ACCESS_FLAG_H_W : ACCESS_FLAG_W ) : \
isOutgoingAttributeMessage( localMessage ) ? \
( ( isHigh ) ? ACCESS_FLAG_H_R : ACCESS_FLAG_R ) : \
( ( isHigh ) ? ACCESS_FLAG_H_D : ACCESS_FLAG_D );
const BOOLEAN isInternalMessage = \
( message & RESOURCE_MESSAGE_INTERNAL ) ? TRUE : FALSE;
const RESOURCE_DATA *msgData = messageDataPtr;
const int *valuePtr = messageDataPtr;
/* Preconditions */
PRE( isValidType( objectInfo->type ) );
PRE( isAttributeMessage( localMessage ) );
PRE( isAttribute( messageValue ) || isInternalAttribute( messageValue ) );
PRE( localMessage == RESOURCE_MESSAGE_DELETEATTRIBUTE || \
messageDataPtr != NULL );
PRE( attributeACL != NULL && attributeACL->attribute == messageValue );
/* If it's an internal message, use the internal access permssions */
if( isInternalMessage )
requiredAccess = MK_ACCESS_INTERNAL( requiredAccess );
/* Make sure that the attribute is valid for this object subtype */
if( !isValidSubtype( attributeACL->subTypeA, subType ) && \
!isValidSubtype( attributeACL->subTypeB, subType ) )
return( CRYPT_ARGERROR_VALUE );
/* Make sure this type of access is valid for this attribute */
if( !( attributeACL->access & requiredAccess ) )
{
/* If it's an internal-only attribute being accessed through an
external message, it isn't visible to the user so we return
an attribute value error */
if( !( attributeACL->access & ACCESS_MASK_EXTERNAL ) && \
!isInternalMessage )
return( CRYPT_ARGERROR_VALUE );
/* It is visible, return a standard permission error */
return( CRYPT_ERROR_PERMISSION );
}
/* Inner precondition: The attribute is valid for this subtype and is
externally visible or it's an internal message, and this type of
access is allowed */
PRE( isValidSubtype( attributeACL->subTypeA, subType ) || \
isValidSubtype( attributeACL->subTypeB, subType ) );
PRE( ( attributeACL->access & ACCESS_MASK_EXTERNAL ) || \
isInternalMessage );
PRE( attributeACL->access & requiredAccess );
/* If it's a delete attribute message, there's no attribute data being
communicated */
if( localMessage == RESOURCE_MESSAGE_DELETEATTRIBUTE )
{
assert( messageDataPtr == NULL );
return( CRYPT_OK );
}
/* Inner precondition: We're getting or setting the value of an attribute */
PRE( localMessage == RESOURCE_MESSAGE_GETATTRIBUTE || \
localMessage == RESOURCE_MESSAGE_GETATTRIBUTE_S || \
localMessage == RESOURCE_MESSAGE_SETATTRIBUTE || \
localMessage == RESOURCE_MESSAGE_SETATTRIBUTE_S );
/* Make sure the attribute type matches the supplied value type. This is
a general type check which checks that the caller has used the correct
message type rather than a check of the message data itself. We assert
the preconditions for internal messages before the general check to
ensure we throw an exception rather than just returning an error code */
switch( attributeACL->valueType )
{
case VALUE_BOOLEAN:
case VALUE_NUMERIC:
/* Inner precondition: If it's an internal message, it must be
a numeric value */
PRE( !isInternalMessage || \
localMessage == RESOURCE_MESSAGE_GETATTRIBUTE || \
localMessage == RESOURCE_MESSAGE_SETATTRIBUTE );
/* Must be a numeric value */
if( localMessage != RESOURCE_MESSAGE_GETATTRIBUTE && \
localMessage != RESOURCE_MESSAGE_SETATTRIBUTE )
return( CRYPT_ARGERROR_VALUE );
break;
case VALUE_OBJECT:
/* Inner precondition: If it's an internal message, it must be
a numeric value */
PRE( !isInternalMessage || \
localMessage == RESOURCE_MESSAGE_GETATTRIBUTE || \
localMessage == RESOURCE_MESSAGE_SETATTRIBUTE );
/* Must be a numeric value */
if( localMessage != RESOURCE_MESSAGE_GETATTRIBUTE && \
localMessage != RESOURCE_MESSAGE_SETATTRIBUTE )
return( CRYPT_ARGERROR_VALUE );
/* If we're sending the data back to the caller, we can't check
it yet */
if( localMessage == RESOURCE_MESSAGE_GETATTRIBUTE )
break;
/* Inner precondition: We're sending data to the object */
PRE( localMessage == RESOURCE_MESSAGE_SETATTRIBUTE );
/* Must contain a valid object handle */
if( !isValidObject( *valuePtr ) || \
!isObjectAccessValid( *valuePtr, message ) || \
!checkObjectOwnership( objectTable[ *valuePtr ] ) )
return( CRYPT_ARGERROR_NUM1 );
if( !isSameOwner( objectHandle, *valuePtr ) )
return( CRYPT_ARGERROR_NUM1 );
/* Postcondition: Object parameter is valid and accessible */
POST( isValidObject( *valuePtr ) && \
isObjectAccessValid( *valuePtr, message ) && \
checkObjectOwnership( objectTable[ *valuePtr ] ) );
POST( isSameOwner( objectHandle, *valuePtr ) );
break;
case VAL
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?