📄 cryptdev.c
字号:
/****************************************************************************
* *
* cryptlib Crypto Device Routines *
* Copyright Peter Gutmann 1997-2007 *
* *
****************************************************************************/
#include "crypt.h"
#ifdef INC_ALL
#include "capabil.h"
#include "device.h"
#else
#include "device/capabil.h"
#include "device/device.h"
#endif /* Compiler-specific includes */
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Process a crypto mechanism message */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 4, 5 ) ) \
static int processMechanismMessage( INOUT DEVICE_INFO *deviceInfoPtr,
IN_MESSAGE const MESSAGE_TYPE action,
IN_ENUM( MECHANISM ) \
const MECHANISM_TYPE mechanism,
INOUT void *mechanismInfo,
INOUT MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
{
CRYPT_DEVICE localCryptDevice = deviceInfoPtr->objectHandle;
MECHANISM_FUNCTION mechanismFunction = NULL;
int refCount, i, status;
assert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );
assert( isWritePtr( messageExtInfo, sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );
REQUIRES( isMechanismActionMessage( action ) );
REQUIRES( mechanism > MECHANISM_NONE && mechanism < MECHANISM_LAST );
REQUIRES( mechanismInfo != NULL );
/* Find the function to handle this action and mechanism */
if( deviceInfoPtr->mechanismFunctions != NULL )
{
for( i = 0;
deviceInfoPtr->mechanismFunctions[ i ].action != MESSAGE_NONE && \
i < deviceInfoPtr->mechanismFunctionCount && \
i < FAILSAFE_ITERATIONS_LARGE;
i++ )
{
if( deviceInfoPtr->mechanismFunctions[ i ].action == action && \
deviceInfoPtr->mechanismFunctions[ i ].mechanism == mechanism )
{
mechanismFunction = \
deviceInfoPtr->mechanismFunctions[ i ].function;
break;
}
}
ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
ENSURES( i < deviceInfoPtr->mechanismFunctionCount );
}
if( mechanismFunction == NULL && \
localCryptDevice != SYSTEM_OBJECT_HANDLE )
{
/* This isn't the system object, fall back to the system object and
see if it can handle the mechanism. We do it this way rather
than sending the message through the kernel a second time because
all the kernel checking of message parameters has already been
done, this saves the overhead of a second, redundant kernel pass.
This code is currently only ever used with Fortezza devices, with
PKCS #11 devices the support for various mechanisms is too patchy
to allow us to rely on it so we always use system mechanisms
which we know will get it right. Because it should never be used
in normal use, we throw an exception if we get here inadvertently
(if this doesn't stop execution then the krnlAcquireObject() will
since it will refuse to allocate the system object) */
assert( INTERNAL_ERROR );
setMessageObjectUnlocked( messageExtInfo );
status = krnlSuspendObject( deviceInfoPtr->objectHandle, &refCount );
ENSURES( cryptStatusOK( status ) );
localCryptDevice = SYSTEM_OBJECT_HANDLE;
status = krnlAcquireObject( SYSTEM_OBJECT_HANDLE, /* Will always fail */
OBJECT_TYPE_DEVICE,
( void ** ) &deviceInfoPtr,
CRYPT_ERROR_SIGNALLED );
if( cryptStatusError( status ) )
return( status );
assert( deviceInfoPtr->mechanismFunctions != NULL );
for( i = 0;
deviceInfoPtr->mechanismFunctions[ i ].action != MESSAGE_NONE && \
i < deviceInfoPtr->mechanismFunctionCount && \
i < FAILSAFE_ITERATIONS_LARGE;
i++ )
{
if( deviceInfoPtr->mechanismFunctions[ i ].action == action && \
deviceInfoPtr->mechanismFunctions[ i ].mechanism == mechanism )
{
mechanismFunction = \
deviceInfoPtr->mechanismFunctions[ i ].function;
break;
}
}
ENSURES( i < FAILSAFE_ITERATIONS_LARGE );
ENSURES( i < deviceInfoPtr->mechanismFunctionCount );
}
if( mechanismFunction == NULL )
return( CRYPT_ERROR_NOTAVAIL );
/* If the message has been sent to the system object, unlock it to allow
it to be used by others and dispatch the message */
if( localCryptDevice == SYSTEM_OBJECT_HANDLE )
{
setMessageObjectUnlocked( messageExtInfo );
status = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );
ENSURES( cryptStatusOK( status ) );
assert( ( action == MESSAGE_DEV_DERIVE &&
mechanism >= MECHANISM_DERIVE_PKCS5 && \
mechanism <= MECHANISM_DERIVE_PGP && \
refCount <= 2 ) || \
refCount == 1 );
/* The system object can send itself a derive mechanism
message during the self-test */
return( mechanismFunction( NULL, mechanismInfo ) );
}
/* Send the message to the device */
return( mechanismFunction( deviceInfoPtr, mechanismInfo ) );
}
/****************************************************************************
* *
* Device API Functions *
* *
****************************************************************************/
/* Default object creation routines used when the device code doesn't set
anything up */
static const CREATEOBJECT_FUNCTION_INFO defaultCreateFunctions[] = {
{ OBJECT_TYPE_CONTEXT, createContext },
{ OBJECT_TYPE_NONE, NULL }
};
/* Handle a message sent to a device object */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int deviceMessageFunction( INOUT TYPECAST( MESSAGE_FUNCTION_EXTINFO * ) \
void *objectInfoPtr,
IN_MESSAGE const MESSAGE_TYPE message,
void *messageDataPtr,
IN_INT_SHORT_Z const int messageValue )
{
MESSAGE_FUNCTION_EXTINFO *messageExtInfo = \
( MESSAGE_FUNCTION_EXTINFO * ) objectInfoPtr;
DEVICE_INFO *deviceInfoPtr = \
( DEVICE_INFO * ) messageExtInfo->objectInfoPtr;
int status;
assert( isWritePtr( objectInfoPtr, sizeof( MESSAGE_FUNCTION_EXTINFO ) ) );
assert( isWritePtr( deviceInfoPtr, sizeof( DEVICE_INFO ) ) );
REQUIRES( message > MESSAGE_NONE && message < MESSAGE_LAST );
REQUIRES( messageValue >= 0 && messageValue < MAX_INTLENGTH_SHORT );
/* Process the destroy object message */
if( message == MESSAGE_DESTROY )
{
/* Shut down the device if required */
if( deviceInfoPtr->flags & DEVICE_ACTIVE && \
deviceInfoPtr->shutdownFunction != NULL )
deviceInfoPtr->shutdownFunction( deviceInfoPtr );
return( CRYPT_OK );
}
/* Process attribute get/set/delete messages */
if( isAttributeMessage( message ) )
{
REQUIRES( message == MESSAGE_GETATTRIBUTE || \
message == MESSAGE_GETATTRIBUTE_S || \
message == MESSAGE_SETATTRIBUTE || \
message == MESSAGE_SETATTRIBUTE_S );
REQUIRES( isAttribute( messageValue ) || \
isInternalAttribute( messageValue ) );
if( message == MESSAGE_GETATTRIBUTE )
return( getDeviceAttribute( deviceInfoPtr,
( int * ) messageDataPtr,
messageValue, messageExtInfo ) );
if( message == MESSAGE_GETATTRIBUTE_S )
return( getDeviceAttributeS( deviceInfoPtr,
( MESSAGE_DATA * ) messageDataPtr,
messageValue, messageExtInfo ) );
if( message == MESSAGE_SETATTRIBUTE )
{
/* CRYPT_IATTRIBUTE_INITIALISED is purely a notification message
with no parameters so we don't pass it down to the attribute-
handling code */
if( messageValue == CRYPT_IATTRIBUTE_INITIALISED )
return( CRYPT_OK );
return( setDeviceAttribute( deviceInfoPtr,
*( ( int * ) messageDataPtr ),
messageValue, messageExtInfo ) );
}
if( message == MESSAGE_SETATTRIBUTE_S )
{
const MESSAGE_DATA *msgData = ( MESSAGE_DATA * ) messageDataPtr;
return( setDeviceAttributeS( deviceInfoPtr, msgData->data,
msgData->length, messageValue,
messageExtInfo ) );
}
retIntError();
}
/* Process action messages */
if( isMechanismActionMessage( message ) )
{
return( processMechanismMessage( deviceInfoPtr, message,
messageValue, messageDataPtr,
messageExtInfo ) );
}
/* Process messages that check a device */
if( message == MESSAGE_CHECK )
{
/* The check for whether this device type can contain an object that
can perform the requested operation has already been performed by
the kernel so there's nothing further to do here */
REQUIRES( ( messageValue == MESSAGE_CHECK_PKC_ENCRYPT_AVAIL || \
messageValue == MESSAGE_CHECK_PKC_DECRYPT_AVAIL || \
messageValue == MESSAGE_CHECK_PKC_SIGCHECK_AVAIL || \
messageValue == MESSAGE_CHECK_PKC_SIGN_AVAIL ) && \
( deviceInfoPtr->type == CRYPT_DEVICE_FORTEZZA || \
deviceInfoPtr->type == CRYPT_DEVICE_PKCS11 || \
deviceInfoPtr->type == CRYPT_DEVICE_CRYPTOAPI ) );
return( CRYPT_OK );
}
/* Process object-specific messages */
if( message == MESSAGE_SELFTEST )
return( deviceInfoPtr->selftestFunction( deviceInfoPtr,
messageExtInfo ) );
if( message == MESSAGE_KEY_GETKEY )
{
MESSAGE_KEYMGMT_INFO *getkeyInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
assert( deviceInfoPtr->getItemFunction != NULL );
/* Create a context via an object in the device */
return( deviceInfoPtr->getItemFunction( deviceInfoPtr,
&getkeyInfo->cryptHandle, messageValue,
getkeyInfo->keyIDtype, getkeyInfo->keyID,
getkeyInfo->keyIDlength, getkeyInfo->auxInfo,
&getkeyInfo->auxInfoLength,
getkeyInfo->flags ) );
}
if( message == MESSAGE_KEY_SETKEY )
{
MESSAGE_KEYMGMT_INFO *setkeyInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
assert( deviceInfoPtr->setItemFunction != NULL );
/* Update the device with the cert */
return( deviceInfoPtr->setItemFunction( deviceInfoPtr,
setkeyInfo->cryptHandle ) );
}
if( message == MESSAGE_KEY_DELETEKEY )
{
MESSAGE_KEYMGMT_INFO *deletekeyInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
assert( deviceInfoPtr->deleteItemFunction != NULL );
/* Delete an object in the device */
return( deviceInfoPtr->deleteItemFunction( deviceInfoPtr,
messageValue, deletekeyInfo->keyIDtype,
deletekeyInfo->keyID, deletekeyInfo->keyIDlength ) );
}
if( message == MESSAGE_KEY_GETFIRSTCERT )
{
MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
assert( deviceInfoPtr->getFirstItemFunction != NULL );
REQUIRES( getnextcertInfo->auxInfoLength == sizeof( int ) );
REQUIRES( messageValue == KEYMGMT_ITEM_PUBLICKEY );
/* Fetch a cert in a cert chain from the device */
return( deviceInfoPtr->getFirstItemFunction( deviceInfoPtr,
&getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,
getnextcertInfo->keyIDtype, getnextcertInfo->keyID,
getnextcertInfo->keyIDlength, messageValue,
getnextcertInfo->flags ) );
}
if( message == MESSAGE_KEY_GETNEXTCERT )
{
MESSAGE_KEYMGMT_INFO *getnextcertInfo = \
( MESSAGE_KEYMGMT_INFO * ) messageDataPtr;
assert( deviceInfoPtr->getNextItemFunction != NULL );
REQUIRES( getnextcertInfo->auxInfoLength == sizeof( int ) );
/* Fetch a cert in a cert chain from the device */
return( deviceInfoPtr->getNextItemFunction( deviceInfoPtr,
&getnextcertInfo->cryptHandle, getnextcertInfo->auxInfo,
getnextcertInfo->flags ) );
}
if( message == MESSAGE_DEV_QUERYCAPABILITY )
{
const void FAR_BSS *capabilityInfoPtr;
CRYPT_QUERY_INFO *queryInfo = ( CRYPT_QUERY_INFO * ) messageDataPtr;
/* Find the information for this algorithm and return the appropriate
information */
capabilityInfoPtr = findCapabilityInfo( deviceInfoPtr->capabilityInfoList,
messageValue );
if( capabilityInfoPtr == NULL )
return( CRYPT_ERROR_NOTAVAIL );
getCapabilityInfo( queryInfo, capabilityInfoPtr );
return( CRYPT_OK );
}
if( message == MESSAGE_DEV_CREATEOBJECT )
{
CRYPT_DEVICE iCryptDevice = deviceInfoPtr->objectHandle;
CREATEOBJECT_FUNCTION createObjectFunction = NULL;
const void *auxInfo = NULL;
REQUIRES( messageValue > OBJECT_TYPE_NONE && \
messageValue < OBJECT_TYPE_LAST );
/* If the device can't have objects created within it, complain */
if( deviceInfoPtr->flags & DEVICE_READONLY )
return( CRYPT_ERROR_PERMISSION );
/* Find the function to handle this object */
if( deviceInfoPtr->createObjectFunctions != NULL )
{
int i;
for( i = 0;
deviceInfoPtr->createObjectFunctions[ i ].type != OBJECT_TYPE_NONE && \
i < deviceInfoPtr->createObjectFunctionCount && \
i < FAILSAFE_ITERATIONS_MED; i++ )
{
if( deviceInfoPtr->createObjectFunctions[ i ].type == messageValue )
{
createObjectFunction = \
deviceInfoPtr->createObjectFunctions[ i ].function;
break;
}
}
ENSURES( i < FAILSAFE_ITERATIONS_MED );
ENSURES( i < deviceInfoPtr->createObjectFunctionCount );
}
if( createObjectFunction == NULL )
return( CRYPT_ERROR_NOTAVAIL );
/* Get any auxiliary info that we may need to create the object */
if( messageValue == OBJECT_TYPE_CONTEXT )
auxInfo = deviceInfoPtr->capabilityInfoList;
/* If the message has been sent to the system object, unlock it to
allow it to be used by others and dispatch the message. This is
safe because the auxInfo for the system device is in a static,
read-only segment and persists even if the system device is
destroyed */
if( deviceInfoPtr->objectHandle == SYSTEM_OBJECT_HANDLE )
{
int refCount;
setMessageObjectUnlocked( messageExtInfo );
status = krnlSuspendObject( SYSTEM_OBJECT_HANDLE, &refCount );
ENSURES( cryptStatusOK( status ) );
assert( refCount == 1 );
status = createObjectFunction( messageDataPtr, auxInfo,
CREATEOBJECT_FLAG_NONE );
}
else
{
/* Create a dummy object, with all details handled by the device.
Unlike the system device we don't unlock the device info
before we call the create object function because there may be
auxiliary info held in the device object that we need in order
to create the object. This is OK since we're not tying up the
system device but only some auxiliary crypto device */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -