📄 sendmsg.c
字号:
PRE_POST_DISPATCH( CheckCheckParam, ForwardToDependentObject ) },
/* Messages sent from the kernel to object message handlers. These
messages are sent directly to the object from inside the kernel in
response to a control message, so we set the checking to disallow
everything to catch any that arrive from outside */
{ MESSAGE_CHANGENOTIFY, /* Notification of obj.status chge.*/
ROUTE_NONE, ST_NONE, ST_NONE, PARAMTYPE_NONE_NONE },
/* Object-type-specific messages: Contexts */
{ MESSAGE_CTX_ENCRYPT, /* Context: Action = encrypt */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC, ST_NONE,
PARAMTYPE_DATA_LENGTH,
PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
{ MESSAGE_CTX_DECRYPT, /* Context: Action = decrypt */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC, ST_NONE,
PARAMTYPE_DATA_LENGTH,
PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
{ MESSAGE_CTX_SIGN, /* Context: Action = sign */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_PKC, ST_NONE,
PARAMTYPE_DATA_LENGTH,
PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
{ MESSAGE_CTX_SIGCHECK, /* Context: Action = sigcheck */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_PKC, ST_NONE,
PARAMTYPE_DATA_LENGTH,
PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
{ MESSAGE_CTX_HASH, /* Context: Action = hash */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_HASH | ST_CTX_MAC, ST_NONE,
PARAMTYPE_DATA_LENGTH,
PRE_POST_DISPATCH( CheckActionAccess, UpdateUsageCount ) },
{ MESSAGE_CTX_GENKEY, /* Context: Generate a key */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV | ST_CTX_PKC | ST_CTX_MAC, ST_NONE,
PARAMTYPE_NONE_BOOLEAN,
PRE_POST_DISPATCH( CheckState, ChangeState ) },
{ MESSAGE_CTX_GENIV, /* Context: Generate an IV */
ROUTE( OBJECT_TYPE_CONTEXT ), ST_CTX_CONV, ST_NONE,
PARAMTYPE_NONE_NONE },
/* Object-type-specific messages: Certificates */
{ MESSAGE_CRT_SIGN, /* Cert: Action = sign cert */
ROUTE( OBJECT_TYPE_CERTIFICATE ),
ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \
ST_CERT_OCSP_REQ | ST_CERT_OCSP_RESP, ST_NONE,
PARAMTYPE_NONE_ANY,
PRE_POST_DISPATCH( CheckStateParamHandle, ChangeState ) },
{ MESSAGE_CRT_SIGCHECK, /* Cert: Action = check/verify cert */
ROUTE( OBJECT_TYPE_CERTIFICATE ),
ST_CERT_ANY_CERT | ST_CERT_ATTRCERT | ST_CERT_CRL | \
ST_CERT_RTCS_RESP | ST_CERT_OCSP_RESP, ST_NONE,
PARAMTYPE_NONE_ANY,
PRE_DISPATCH( CheckParamHandleOpt ) },
{ MESSAGE_CRT_EXPORT, /* Cert: Export encoded cert data */
ROUTE( OBJECT_TYPE_CERTIFICATE ), ST_CERT_ANY, ST_NONE,
PARAMTYPE_DATA_FORMATTYPE,
PRE_DISPATCH( CheckExportAccess ) },
/* Object-type-specific messages: Devices */
{ MESSAGE_DEV_QUERYCAPABILITY, /* Device: Query capability */
ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_ANY },
{ MESSAGE_DEV_EXPORT, /* Device: Action = export key */
ROUTE( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_MECHTYPE,
PRE_DISPATCH( CheckMechanismWrapAccess ) },
{ MESSAGE_DEV_IMPORT, /* Device: Action = import key */
ROUTE( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_MECHTYPE,
PRE_DISPATCH( CheckMechanismWrapAccess ) },
{ MESSAGE_DEV_SIGN, /* Device: Action = sign */
ROUTE( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_MECHTYPE,
PRE_DISPATCH( CheckMechanismSignAccess ) },
{ MESSAGE_DEV_SIGCHECK, /* Device: Action = sig.check */
ROUTE( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_MECHTYPE,
PRE_DISPATCH( CheckMechanismSignAccess ) },
{ MESSAGE_DEV_DERIVE, /* Device: Action = derive key */
ROUTE( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_MECHTYPE,
PRE_DISPATCH( CheckMechanismDeriveAccess ) },
{ MESSAGE_DEV_CREATEOBJECT, /* Device: Create object */
ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_OBJTYPE,
PRE_POST_DISPATCH( SetObjectOwner, MakeObjectExternal ) },
{ MESSAGE_DEV_CREATEOBJECT_INDIRECT,/* Device: Create obj.from data */
ROUTE_FIXED( OBJECT_TYPE_DEVICE ), ST_DEV_ANY, ST_NONE,
PARAMTYPE_DATA_OBJTYPE,
PRE_POST_DISPATCH( SetObjectOwner, MakeObjectExternal ) },
/* Object-type-specific messages: Envelopes */
{ MESSAGE_ENV_PUSHDATA, /* Envelope: Push data */
ROUTE_FIXED_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),
ST_NONE, ST_ENV_ANY | ST_SESS_ANY_DATA,
PARAMTYPE_DATA_NONE,
PRE_DISPATCH( CheckData ) },
{ MESSAGE_ENV_POPDATA, /* Envelope: Pop data */
ROUTE_FIXED_ALT( OBJECT_TYPE_ENVELOPE, OBJECT_TYPE_SESSION ),
ST_NONE, ST_ENV_ANY | ST_SESS_ANY_DATA,
PARAMTYPE_DATA_NONE,
PRE_DISPATCH( CheckData ) },
/* Object-type-specific messages: Keysets */
{ MESSAGE_KEY_GETKEY, /* Keyset: Instantiate ctx/cert */
ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
PARAMTYPE_DATA_ITEMTYPE,
PRE_POST_DISPATCH( CheckKeysetAccess, MakeObjectExternal ) },
{ MESSAGE_KEY_SETKEY, /* Keyset: Add ctx/cert */
ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
PARAMTYPE_DATA_ITEMTYPE,
PRE_DISPATCH( CheckKeysetAccess ) },
{ MESSAGE_KEY_DELETEKEY, /* Keyset: Delete key */
ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
PARAMTYPE_DATA_ITEMTYPE,
PRE_DISPATCH( CheckKeysetAccess ) },
{ MESSAGE_KEY_GETFIRSTCERT, /* Keyset: Get first cert in sequence */
ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
PARAMTYPE_DATA_ITEMTYPE,
PRE_DISPATCH( CheckKeysetAccess ) },
{ MESSAGE_KEY_GETNEXTCERT, /* Keyset: Get next cert in sequence */
ROUTE_FIXED_ALT( OBJECT_TYPE_KEYSET, OBJECT_TYPE_DEVICE ),
ST_KEYSET_ANY | ST_DEV_ANY_STD, ST_NONE,
PARAMTYPE_DATA_ITEMTYPE,
PRE_POST_DISPATCH( CheckKeysetAccess, MakeObjectExternal ) },
{ MESSAGE_KEY_CERTMGMT, /* Keyset: Cert management */
ROUTE_FIXED( OBJECT_TYPE_KEYSET ),
ST_KEYSET_DBMS_STORE, ST_NONE,
PARAMTYPE_DATA_ANY,
PRE_POST_DISPATCH( CheckCertMgmtAccess, MakeObjectExternal ) }
};
/****************************************************************************
* *
* Init/Shutdown Functions *
* *
****************************************************************************/
int initSendMessage( KERNEL_DATA *krnlDataPtr )
{
int i;
/* Perform a consistency check on various things that need to be set
up in a certain way for things to work properly */
assert( MESSAGE_CTX_DECRYPT == MESSAGE_CTX_ENCRYPT + 1 );
assert( MESSAGE_CTX_SIGN == MESSAGE_CTX_DECRYPT + 1 );
assert( MESSAGE_CTX_SIGCHECK == MESSAGE_CTX_SIGN + 1 );
assert( MESSAGE_CTX_HASH == MESSAGE_CTX_SIGCHECK + 1 );
assert( MESSAGE_CTX_GENKEY == MESSAGE_CTX_HASH + 1 );
assert( MESSAGE_GETATTRIBUTE_S == MESSAGE_GETATTRIBUTE + 1 );
assert( MESSAGE_SETATTRIBUTE == MESSAGE_GETATTRIBUTE_S + 1 );
assert( MESSAGE_SETATTRIBUTE_S == MESSAGE_SETATTRIBUTE + 1 );
assert( MESSAGE_DELETEATTRIBUTE == MESSAGE_SETATTRIBUTE_S + 1 );
/* Perform a consistency check on various internal values and constants */
assert( ACTION_PERM_COUNT == 6 );
/* Perform a consistency check on the parameter ACL */
for( i = 0; messageParamACLTbl[ i ].type != MESSAGE_NONE; i++ )
{
const MESSAGE_ACL *messageParamACL = &messageParamACLTbl[ i ];
if( !isParamMessage( messageParamACL->type ) || \
( messageParamACL->objectACL.subTypeA & SUBTYPE_CLASS_B ) || \
( messageParamACL->objectACL.subTypeB & SUBTYPE_CLASS_A ) )
{
assert( NOTREACHED );
return( CRYPT_ERROR_FAILED );
}
}
/* Perform a consistency check on the message handling information */
for( i = 0; i < MESSAGE_LAST; i++ )
{
const MESSAGE_HANDLING_INFO *messageInfo = &messageHandlingInfo[ i ];
if( messageInfo->messageType != i || \
messageInfo->paramCheck < PARAMTYPE_NONE_NONE || \
messageInfo->paramCheck >= PARAMTYPE_LAST || \
( messageInfo->subTypeA & SUBTYPE_CLASS_B ) || \
( messageInfo->subTypeB & SUBTYPE_CLASS_A ) )
{
assert( NOTREACHED );
return( CRYPT_ERROR_FAILED );
}
}
/* Set up the reference to the kernel data block */
krnlData = krnlDataPtr;
return( CRYPT_OK );
}
void endSendMessage( void )
{
krnlData = NULL;
}
/****************************************************************************
* *
* Message Queue *
* *
****************************************************************************/
/* Enqueue a message */
static int enqueueMessage( const int objectHandle,
const MESSAGE_HANDLING_INFO *handlingInfoPtr,
const MESSAGE_TYPE message,
const void *messageDataPtr,
const int messageValue )
{
MESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;
int queuePos, i;
/* Precondition: It's a valid message being sent to a valid object */
PRE( isValidObject( objectHandle ) );
PRE( isReadPtr( handlingInfoPtr, sizeof( MESSAGE_HANDLING_INFO ) ) );
PRE( isValidMessage( message & MESSAGE_MASK ) );
/* Make sure that we don't overflow the queue (this object is not
responding to messages... now all we need is GPF's). We return a
timeout error to indicate that there are too many messages queued
for this (or other) objects */
if( krnlData->queueEnd < 0 || \
krnlData->queueEnd >= MESSAGE_QUEUE_SIZE - 1 )
{
assert( NOTREACHED );
return( CRYPT_ERROR_TIMEOUT );
}
/* Precondition: There's room to enqueue the message */
PRE( krnlData->queueEnd >= 0 && \
krnlData->queueEnd < MESSAGE_QUEUE_SIZE );
/* Check whether a message to this object is already present in the
queue */
for( queuePos = krnlData->queueEnd - 1; queuePos >= 0; queuePos-- )
if( messageQueue[ queuePos ].objectHandle == objectHandle )
break;
/* Postcondition: queuePos = -1 if not present, position in queue if
present */
POST( queuePos == -1 || \
( queuePos >= 0 && queuePos < krnlData->queueEnd ) );
/* Enqueue the message */
queuePos++; /* Insert after current position */
for( i = krnlData->queueEnd - 1; i >= queuePos; i-- )
messageQueue[ i + 1 ] = messageQueue[ i ];
messageQueue[ queuePos ].objectHandle = objectHandle;
messageQueue[ queuePos ].handlingInfoPtr = handlingInfoPtr;
messageQueue[ queuePos ].message = message;
messageQueue[ queuePos ].messageDataPtr = messageDataPtr;
messageQueue[ queuePos ].messageValue = messageValue;
krnlData->queueEnd++;
if( queuePos )
/* A message for this object is already present, tell the caller to
defer processing */
return( OK_SPECIAL );
return( CRYPT_OK );
}
/* Dequeue a message */
static void dequeueMessage( const int messagePosition )
{
MESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;
int i;
/* Precondition: We're deleting a valid queue position */
PRE( messagePosition >= 0 && messagePosition < krnlData->queueEnd );
/* Move the remaining messages down and clear the last entry */
for( i = messagePosition; i < krnlData->queueEnd - 1; i++ )
messageQueue[ i ] = messageQueue[ i + 1 ];
zeroise( &messageQueue[ krnlData->queueEnd - 1 ],
sizeof( MESSAGE_QUEUE_DATA ) );
krnlData->queueEnd--;
/* Postcondition: all queue entries are valid, all non-queue entries are
empty */
FORALL( i, 0, krnlData->queueEnd,
messageQueue[ i ].handlingInfoPtr != NULL );
FORALL( i, krnlData->queueEnd, MESSAGE_QUEUE_SIZE,
messageQueue[ i ].handlingInfoPtr == NULL );
}
/* Get the next message in the queue */
static BOOLEAN getNextMessage( const int objectHandle,
MESSAGE_QUEUE_DATA *messageQueueInfo )
{
MESSAGE_QUEUE_DATA *messageQueue = krnlData->messageQueue;
int i;
PRE( messageQueueInfo == NULL || \
isWritePtr( messageQueueInfo, sizeof( MESSAGE_QUEUE_DATA ) ) );
/* Find the next message for this object. Since other messages can have
come and gone in the meantime, we have to scan from the start each
time */
for( i = 0; i < krnlData->queueEnd; i++ )
{
if( messageQueue[ i ].objectHandle == objectHandle )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -