📄 pkcs11_init.c
字号:
if( capabilityInfo->keySize < capabilityInfo->minKeySize )
capabilityInfo->keySize = capabilityInfo->minKeySize;
capabilityInfo->maxKeySize = min( maxKeySize,
capabilityInfo->maxKeySize );
if( capabilityInfo->maxKeySize < capabilityInfo->minKeySize )
{
/* Serious braindamage in the driver, we'll just have to make
a sensible guess */
assert( DEBUG_WARN );
capabilityInfo->maxKeySize = \
( cryptAlgo == CRYPT_ALGO_RSA || \
isDlpAlgo( cryptAlgo ) ) ? 128 : 16;
}
if( capabilityInfo->keySize > capabilityInfo->maxKeySize )
capabilityInfo->keySize = capabilityInfo->maxKeySize;
capabilityInfo->endFunction = genericEndFunction;
}
/* Set up the device-specific handlers */
capabilityInfo->selfTestFunction = selfTestFunction;
capabilityInfo->getInfoFunction = getDefaultInfo;
if( cryptAlgo != CRYPT_ALGO_DH && cryptAlgo != CRYPT_ALGO_RSA && \
cryptAlgo != CRYPT_ALGO_DSA )
capabilityInfo->initKeyParamsFunction = initKeyParams;
capabilityInfo->endFunction = mechanismInfoPtr->endFunction;
capabilityInfo->initKeyFunction = mechanismInfoPtr->initKeyFunction;
if( pMechanism.flags & keyGenFlag )
capabilityInfo->generateKeyFunction = \
mechanismInfoPtr->generateKeyFunction;
if( pMechanism.flags & CKF_SIGN )
{
/* cryptlib treats hashing as an encrypt/decrypt operation while
PKCS #11 treats it as a sign/verify operation, so we have to
juggle the function pointers based on the underlying algorithm
type */
if( isPKC )
capabilityInfo->signFunction = mechanismInfoPtr->signFunction;
else
capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
}
if( pMechanism.flags & CKF_VERIFY )
{
/* See comment above */
if( isPKC )
capabilityInfo->sigCheckFunction = mechanismInfoPtr->sigCheckFunction;
else
capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
}
if( pMechanism.flags & CKF_ENCRYPT )
{
/* Not all devices implement all modes, so we have to be careful to
set up the pointer for the exact mode that's supported */
switch( mechanismInfoPtr->cryptMode )
{
case CRYPT_MODE_CBC:
capabilityInfo->encryptCBCFunction = mechanismInfoPtr->encryptFunction;
break;
case CRYPT_MODE_CFB:
capabilityInfo->encryptCFBFunction = mechanismInfoPtr->encryptFunction;
break;
case CRYPT_MODE_OFB:
capabilityInfo->encryptOFBFunction = mechanismInfoPtr->encryptFunction;
break;
default: /* ECB or a PKC */
capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
break;
}
}
if( pMechanism.flags & CKF_DECRYPT )
{
/* Not all devices implement all modes, so we have to be careful to
set up the pointer for the exact mode that's supported */
switch( mechanismInfoPtr->cryptMode )
{
case CRYPT_MODE_CBC:
capabilityInfo->decryptCBCFunction = mechanismInfoPtr->decryptFunction;
break;
case CRYPT_MODE_CFB:
capabilityInfo->decryptCFBFunction = mechanismInfoPtr->decryptFunction;
break;
case CRYPT_MODE_OFB:
capabilityInfo->decryptOFBFunction = mechanismInfoPtr->decryptFunction;
break;
default: /* ECB or a PKC */
capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
break;
}
}
if( cryptAlgo == CRYPT_ALGO_DH && pMechanism.flags & CKF_DERIVE )
{
/* DH is a special-case that doesn't really have an encrypt function
and where "decryption" is actually a derivation */
capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
}
/* Keygen capabilities are generally present as separate mechanisms,
sometimes CKF_GENERATE/CKF_GENERATE_KEY_PAIR is set for the main
mechanism and sometimes it's set for the separate one so if it isn't
present in the main one we check the alternative one */
if( !( pMechanism.flags & keyGenFlag ) && \
( mechanismInfoPtr->keygenMechanism != CKM_NONE ) )
{
status = C_GetMechanismInfo( pkcs11Info->slotID,
mechanismInfoPtr->keygenMechanism,
&pMechanism );
if( status == CKR_OK && ( pMechanism.flags & keyGenFlag ) && \
( !hardwareOnly || ( pMechanism.flags & CKF_HW ) ) )
/* Some tinkertoy tokens don't implement key generation in
hardware but instead do it on the host PC (!!!) and load the
key into the token afterwards, so we have to perform another
check here to make sure that they're doing things right */
capabilityInfo->generateKeyFunction = \
mechanismInfoPtr->generateKeyFunction;
}
/* Record mechanism-specific parameters if required */
if( ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) || \
( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \
cryptAlgo <= CRYPT_ALGO_LAST_MAC ) )
{
capabilityInfo->paramKeyType = mechanismInfoPtr->keyType;
capabilityInfo->paramKeyGen = mechanismInfoPtr->keygenMechanism;
capabilityInfo->paramDefaultMech = mechanismInfoPtr->defaultMechanism;
}
/* If it's not a conventional encryption algo, we're done */
if( cryptAlgo < CRYPT_ALGO_FIRST_CONVENTIONAL || \
cryptAlgo > CRYPT_ALGO_LAST_CONVENTIONAL )
return( ( CAPABILITY_INFO * ) capabilityInfo );
/* PKCS #11 handles encryption modes by defining a separate mechanism for
each one. In order to enumerate all the modes available for a
particular algorithm we check for each mechanism in turn and set up
the appropriate function pointers if it's available */
for( mechanismInfoPtr++, iterationCount = 0;
mechanismInfoPtr->cryptAlgo == cryptAlgo && \
iterationCount < maxMechanisms;
mechanismInfoPtr++, iterationCount++ )
{
/* There's a different form of the existing mechanism available,
check whether the driver implements it */
status = C_GetMechanismInfo( pkcs11Info->slotID,
mechanismInfoPtr->mechanism,
&pMechanism );
if( status != CKR_OK )
continue;
/* Set up the pointer for the appropriate encryption mode */
switch( mechanismInfoPtr->cryptMode )
{
case CRYPT_MODE_CBC:
if( pMechanism.flags & CKF_ENCRYPT )
capabilityInfo->encryptCBCFunction = \
mechanismInfoPtr->encryptFunction;
if( pMechanism.flags & CKF_DECRYPT )
capabilityInfo->decryptCBCFunction = \
mechanismInfoPtr->decryptFunction;
break;
case CRYPT_MODE_CFB:
if( pMechanism.flags & CKF_ENCRYPT )
capabilityInfo->encryptCFBFunction = \
mechanismInfoPtr->encryptFunction;
if( pMechanism.flags & CKF_DECRYPT )
capabilityInfo->decryptCFBFunction = \
mechanismInfoPtr->decryptFunction;
break;
case CRYPT_MODE_OFB:
if( pMechanism.flags & CKF_ENCRYPT )
capabilityInfo->encryptOFBFunction = \
mechanismInfoPtr->encryptFunction;
if( pMechanism.flags & CKF_DECRYPT )
capabilityInfo->decryptOFBFunction = \
mechanismInfoPtr->decryptFunction;
break;
default:
retIntError_Null();
}
}
if( iterationCount >= maxMechanisms )
retIntError_Null();
return( ( CAPABILITY_INFO * ) capabilityInfo );
}
/* Set the capability information based on device capabilities. Since
PKCS #11 devices can have assorted capabilities (and can vary depending
on what's plugged in), we have to build this up on the fly rather than
using a fixed table like the built-in capabilities */
static void freeCapabilities( DEVICE_INFO *deviceInfo )
{
CAPABILITY_INFO_LIST *capabilityInfoListPtr = \
( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList;
/* If the list was empty, return now */
if( capabilityInfoListPtr == NULL )
return;
deviceInfo->capabilityInfoList = NULL;
while( capabilityInfoListPtr != NULL )
{
CAPABILITY_INFO_LIST *listItemToFree = capabilityInfoListPtr;
CAPABILITY_INFO *itemToFree = ( CAPABILITY_INFO * ) listItemToFree->info;
capabilityInfoListPtr = capabilityInfoListPtr->next;
zeroise( itemToFree, sizeof( CAPABILITY_INFO ) );
clFree( "freeCapabilities", itemToFree );
zeroise( listItemToFree, sizeof( CAPABILITY_INFO_LIST ) );
clFree( "freeCapabilities", listItemToFree );
}
}
static int getCapabilities( DEVICE_INFO *deviceInfo,
const PKCS11_MECHANISM_INFO *mechanismInfoPtr,
const int maxMechanisms )
{
CAPABILITY_INFO_LIST *capabilityInfoListTail = \
( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList;
int i;
assert( sizeof( CAPABILITY_INFO ) == sizeof( VARIABLE_CAPABILITY_INFO ) );
/* Find the end of the list to add new capabilities */
if( capabilityInfoListTail != NULL )
{
while( capabilityInfoListTail->next != NULL )
capabilityInfoListTail = capabilityInfoListTail->next;
}
/* Add capability information for each recognised mechanism type */
for( i = 0; mechanismInfoPtr[ i ].mechanism != CKM_NONE && \
i < maxMechanisms; i++ )
{
CAPABILITY_INFO_LIST *newCapabilityList;
CAPABILITY_INFO *newCapability;
const CRYPT_ALGO_TYPE cryptAlgo = mechanismInfoPtr[ i ].cryptAlgo;
/* If the assertion below triggers then the PKCS #11 driver is
broken since it's returning inconsistent information such as
illegal key length data, conflicting algorithm information, etc
etc. This assertion is included here to detect buggy drivers
early on rather than forcing users to step through the PKCS #11
glue code to find out why an operation is failing.
Because some tinkertoy implementations support only the bare
minimum functionality (e.g.RSA private key ops and nothing else),
we allow asymmetric functionality for PKCs */
newCapability = getCapability( deviceInfo, &mechanismInfoPtr[ i ],
maxMechanisms - i );
if( newCapability == NULL )
continue;
REQUIRES( sanityCheckCapability( newCapability,
( newCapability->cryptAlgo >= CRYPT_ALGO_FIRST_PKC && \
newCapability->cryptAlgo <= CRYPT_ALGO_LAST_PKC ) ? \
TRUE : FALSE ) );
if( ( newCapabilityList = \
clAlloc( "getCapabilities", \
sizeof( CAPABILITY_INFO_LIST ) ) ) == NULL )
{
clFree( "getCapabilities", newCapability );
continue;
}
newCapabilityList->info = newCapability;
newCapabilityList->next = NULL;
if( deviceInfo->capabilityInfoList == NULL )
deviceInfo->capabilityInfoList = newCapabilityList;
else
capabilityInfoListTail->next = newCapabilityList;
capabilityInfoListTail = newCapabilityList;
/* Since there may be alternative mechanisms to the current one
defined, we have to skip mechanisms until we find a ones for a
new algorithm */
while( mechanismInfoPtr[ i + 1 ].cryptAlgo == cryptAlgo && \
i < maxMechanisms )
i++;
if( i >= maxMechanisms )
retIntError();
}
if( i >= maxMechanisms )
retIntError();
return( ( deviceInfo->capabilityInfoList == NULL ) ? CRYPT_ERROR : CRYPT_OK );
}
/****************************************************************************
* *
* Device Init/Shutdown/Device Control Routines *
* *
****************************************************************************/
/* Close a previously-opened session with the device. We have to have this
before the init function since it may be called by it if the init process
fails */
static void shutdownFunction( DEVICE_INFO *deviceInfo )
{
PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
/* Log out and close the session with the device */
if( deviceInfo->flags & DEVICE_LOGGEDIN )
C_Logout( pkcs11Info->hSession );
C_CloseSession( pkcs11Info->hSession );
pkcs11Info->hSession = CK_OBJECT_NONE;
deviceInfo->flags &= ~( DEVICE_ACTIVE | DEVICE_LOGGEDIN );
/* Free the device capability information */
freeCapabilities( deviceInfo );
}
/* Open a session with the device */
static int initFunction( DEVICE_INFO *deviceInfo, const char *name,
const int nameLength )
{
CK_SESSION_HANDLE hSession;
CK_SLOT_ID slotList[ MAX_PKCS11_SLOTS + 8 ];
CK_ULONG slotCount = MAX_PKCS11_SLOTS;
CK_SLOT_INFO slotInfo;
CK_TOKEN_INFO tokenInfo;
CK_RV status;
PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
const PKCS11_MECHANISM_INFO *mechanismInfoPtr;
char *labelPtr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -