📄 pkcs11.c
字号:
pkcs11Info->pC_DecryptInit == NULL ||
pkcs11Info->pC_DestroyObject == NULL ||
pkcs11Info->pC_Encrypt == NULL ||
pkcs11Info->pC_EncryptInit == NULL ||
pkcs11Info->pC_Finalize == NULL ||
pkcs11Info->pC_FindObjects == NULL ||
pkcs11Info->pC_FindObjectsInit == NULL ||
pkcs11Info->pC_GenerateRandom == NULL ||
pkcs11Info->pC_GenerateKeyPair == NULL ||
pkcs11Info->pC_GetAttributeValue == NULL ||
pkcs11Info->pC_GetMechanismInfo == NULL ||
pkcs11Info->pC_GetSlotInfo == NULL ||
pkcs11Info->pC_GetSlotList == NULL ||
pkcs11Info->pC_GetTokenInfo == NULL ||
pkcs11Info->pC_InitPIN == NULL ||
pkcs11Info->pC_InitToken == NULL || pkcs11Info->pC_Login == NULL ||
pkcs11Info->pC_Logout == NULL || pkcs11Info->pC_OpenSession == NULL ||
pkcs11Info->pC_SetAttributeValue == NULL ||
pkcs11Info->pC_SetPIN == NULL || pkcs11Info->pC_Sign == NULL ||
pkcs11Info->pC_SignInit == NULL || pkcs11Info->pC_UnwrapKey == NULL ||
pkcs11Info->pC_Verify == NULL || pkcs11Info->pC_VerifyInit == NULL )
{
/* Free the library reference and clear the info */
DynamicUnload( pkcs11Info->hPKCS11 );
memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
return( CRYPT_ERROR );
}
/* Initialise the PKCS #11 library and get info on the device. There are
four types of PKCS #11 driver around: v1, v1-like claiming to be v2,
v2-like claiming to be v1, and v2. cryptlib can in theory handle all
of these, however there are some problem areas with v1 (for example v1
uses 16-bit values while v2 uses 32-bit ones, this is usually OK
because data is passed around as 32-bit values with the high bits
zeroed but some implementations may leave garbage in the high 16 bits
that leads to all sorts of confusion). Because of this we explicitly
fail if something claims to be v1 even though it might work in
practice */
status = pC_Initialize( NULL_PTR ) & 0xFFFF;
if( status == CKR_OK || status == CKR_CRYPTOKI_ALREADY_INITIALIZED )
{
isInitialised = TRUE;
status = pC_GetInfo( &info ) & 0xFFFF;
}
if( status == CKR_OK && info.cryptokiVersion.major <= 1 )
/* It's v1, we can't work with it */
status = CKR_FUNCTION_NOT_SUPPORTED;
if( status != CKR_OK )
{
if( isInitialised )
pkcs11Info->pC_Finalize( NULL_PTR );
DynamicUnload( pkcs11Info->hPKCS11 );
memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
return( CRYPT_ERROR );
}
#else
/* Get the access information for the PKCS #11 library, initialise it,
and get info on the device. There are four types of PKCS #11 driver
around: v1, v1-like claiming to be v2, v2-like claiming to be v1, and
v2. cryptlib can in theory handle all of these, however there are
some problem areas with v1 (for example v1 uses 16-bit values while
v2 uses 32-bit ones, this is usually OK because data is passed around
as 32-bit values with the high bits zeroed but some implementations
may leave garbage in the high 16 bits that leads to all sorts of
confusion). Because of this we explicitly fail if something claims
to be v1 even though it might work in practice */
pC_GetFunctionList = ( CK_C_GetFunctionList ) DynamicBind( pkcs11Info->hPKCS11, "C_GetFunctionList" );
if( pC_GetFunctionList == NULL )
status = CKR_GENERAL_ERROR;
else
status = pC_GetFunctionList( &pkcs11Info->functionListPtr ) & 0xFFFF;
if( status != CKR_OK )
{
/* Free the library reference and clear the info */
DynamicUnload( pkcs11Info->hPKCS11 );
memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
return( CRYPT_ERROR );
}
status = C_Initialize( NULL_PTR ) & 0xFFFF;
if( status == CKR_OK || status == CKR_CRYPTOKI_ALREADY_INITIALIZED )
{
isInitialised = TRUE;
status = C_GetInfo( &info ) & 0xFFFF;
}
if( status == CKR_OK && info.cryptokiVersion.major <= 1 )
/* It's v1, we can't work with it */
status = CKR_FUNCTION_NOT_SUPPORTED;
if( status != CKR_OK )
{
if( isInitialised )
C_Finalize( NULL_PTR );
DynamicUnload( pkcs11Info->hPKCS11 );
memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) );
return( CRYPT_ERROR );
}
#endif /* USE_EXPLICIT_LINKING */
/* Copy out the device driver's name so that the user can access it by
name. Some vendors erroneously null-terminate the string so we check
for nulls as well */
memcpy( pkcs11Info->name, info.libraryDescription, 32 );
while( i > 0 && ( pkcs11Info->name[ i - 1 ] == ' ' || \
!pkcs11Info->name[ i - 1 ] ) )
i--;
pkcs11Info->name[ i ] = '\0';
return( CRYPT_OK );
}
void deviceEndPKCS11( void )
{
int i;
if( pkcs11Initialised )
for( i = 0; i < MAX_PKCS11_DRIVERS; i++ )
{
if( pkcs11InfoTbl[ i ].hPKCS11 != NULL_INSTANCE )
{
#ifdef USE_EXPLICIT_LINKING
pkcs11InfoTbl[ i ].pC_Finalize( NULL_PTR );
#else
PKCS11_DRIVER_INFO *pkcs11Info = &pkcs11InfoTbl[ i ];
C_Finalize( NULL_PTR );
#endif /* USE_EXPLICIT_LINKING */
DynamicUnload( pkcs11InfoTbl[ i ].hPKCS11 );
}
pkcs11InfoTbl[ i ].hPKCS11 = NULL_INSTANCE;
}
pkcs11Initialised = FALSE;
}
int deviceInitPKCS11( void )
{
int tblIndex = 0, optionIndex;
/* If we've previously tried to init the drivers, don't try it again */
if( pkcs11Initialised )
return( CRYPT_OK );
memset( pkcs11InfoTbl, 0, sizeof( pkcs11InfoTbl ) );
/* Try and link in each driver specified in the config options. Since
this is a general systemwide config option, we always query the built-
in default user object */
for( optionIndex = 0; optionIndex < MAX_PKCS11_DRIVERS; optionIndex++ )
{
RESOURCE_DATA msgData;
char deviceDriverName[ MAX_PATH_LENGTH + 1 ];
int status;
setMessageData( &msgData, deviceDriverName, MAX_PATH_LENGTH );
status = krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
optionIndex + CRYPT_OPTION_DEVICE_PKCS11_DVR01 );
if( cryptStatusError( status ) )
continue;
deviceDriverName[ msgData.length ] = '\0';
status = loadPKCS11driver( &pkcs11InfoTbl[ tblIndex ],
deviceDriverName );
if( cryptStatusOK( status ) )
{
tblIndex++;
pkcs11Initialised = TRUE;
}
}
return( pkcs11Initialised ? CRYPT_OK : CRYPT_ERROR );
}
#else
int deviceInitPKCS11( void )
{
int status;
/* If we've previously tried to init the drivers, don't try it again */
if( pkcs11Initialised )
return( CRYPT_OK );
status = C_Initialize( NULL_PTR );
if( status != CKR_OK && status != CKR_CRYPTOKI_ALREADY_INITIALIZED )
return( CRYPT_ERROR );
pkcs11Initialised = TRUE;
return( CRYPT_OK );
}
void deviceEndPKCS11( void )
{
if( pkcs11Initialised )
C_Finalize( NULL_PTR );
pkcs11Initialised = FALSE;
}
#endif /* DYNAMIC_LOAD */
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Map a PKCS #11-specific error to a cryptlib error */
static int mapError( PKCS11_INFO *pkcs11Info, const CK_RV errorCode,
const int defaultError )
{
pkcs11Info->errorCode = ( int ) errorCode;
switch( ( int ) errorCode )
{
case CKR_OK:
return( CRYPT_OK );
case CKR_HOST_MEMORY:
case CKR_DEVICE_MEMORY:
return( CRYPT_ERROR_MEMORY );
case CKR_DEVICE_ERROR:
case CKR_DEVICE_REMOVED:
case CKR_TOKEN_NOT_PRESENT:
return( CRYPT_ERROR_SIGNALLED );
case CKR_PIN_INCORRECT:
case CKR_PIN_INVALID:
case CKR_PIN_LEN_RANGE:
case CKR_PIN_EXPIRED:
case CKR_PIN_LOCKED:
return( CRYPT_ERROR_WRONGKEY );
case CKR_DATA_INVALID:
case CKR_ENCRYPTED_DATA_INVALID:
case CKR_WRAPPED_KEY_INVALID:
return( CRYPT_ERROR_BADDATA );
case CKR_SIGNATURE_INVALID:
return( CRYPT_ERROR_SIGNATURE );
case CKR_KEY_NOT_WRAPPABLE:
case CKR_KEY_UNEXTRACTABLE:
case CKR_TOKEN_WRITE_PROTECTED:
case CKR_INFORMATION_SENSITIVE:
return( CRYPT_ERROR_PERMISSION );
case CKR_DATA_LEN_RANGE:
case CKR_ENCRYPTED_DATA_LEN_RANGE:
case CKR_SIGNATURE_LEN_RANGE:
case CKR_UNWRAPPING_KEY_SIZE_RANGE:
case CKR_WRAPPING_KEY_SIZE_RANGE:
case CKR_WRAPPED_KEY_LEN_RANGE:
return( CRYPT_ERROR_OVERFLOW );
case CKR_SESSION_EXISTS:
case CKR_SESSION_READ_ONLY_EXISTS:
case CKR_SESSION_READ_WRITE_SO_EXISTS:
case CKR_USER_ALREADY_LOGGED_IN:
case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
case CKR_CRYPTOKI_NOT_INITIALIZED:
return( CRYPT_ERROR_INITED );
case CKR_USER_NOT_LOGGED_IN:
case CKR_USER_PIN_NOT_INITIALIZED:
case CKR_CRYPTOKI_ALREADY_INITIALIZED:
return( CRYPT_ERROR_NOTINITED );
case CKR_RANDOM_NO_RNG:
return( CRYPT_ERROR_RANDOM );
case CKR_OPERATION_ACTIVE:
return( CRYPT_ERROR_TIMEOUT );
case CKR_TOKEN_NOT_RECOGNIZED:
return( CRYPT_ERROR_NOTFOUND );
}
return( defaultError );
}
/* Extract the time from a PKCS #11 tokenInfo structure */
static time_t getTokenTime( CK_TOKEN_INFO *tokenInfo )
{
STREAM stream;
BYTE buffer[ 32 ];
time_t theTime = MIN_TIME_VALUE + 1;
int length, status;
/* Convert the token time to an ASN.1 time string that we can read using
the standard ASN.1 routines by writing a dummy time value and inserting
the token's time string in its place */
sMemOpen( &stream, buffer, 32 );
writeGeneralizedTime( &stream, theTime, DEFAULT_TAG );
length = stell( &stream );
sMemDisconnect( &stream );
memcpy( buffer + 2, tokenInfo->utcTime, 14 );
sMemConnect( &stream, buffer, length );
status = readGeneralizedTime( &stream, &theTime );
sMemDisconnect( &stream );
return( ( cryptStatusOK( status ) ) ? theTime : 0 );
}
/* Find an object based on a given template. There are two variations of
this, one that finds one and only one object, and the other that returns
the first object it finds without treating the presence of multiple
objects as an error.
The way in which this call works has special significance, there are PKCS
#11 implementations that don't allow any other calls during the init/find/
final sequence, so the code is structured to always call them one after
the other without any intervening calls. In addition some drivers are
confused over whether they're 1.x or 2.x and may or may not implement
C_FindObjectsFinal(). Because of this we call it if it exists, if it
doesn't we assume that the driver can handle cleanup itself (this
situation shouldn't occur because we've checked for 1.x drivers earlier,
but there are one or two drivers where it does happen) */
static int findDeviceObjects( PKCS11_INFO *pkcs11Info,
CK_OBJECT_HANDLE *hObject,
const CK_ATTRIBUTE *objectTemplate,
const CK_ULONG templateCount,
const BOOLEAN onlyOne )
{
CK_OBJECT_HANDLE hObjectArray[ 2 ];
CK_ULONG ulObjectCount;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -