📄 pkcs11_init.c
字号:
/****************************************************************************
* *
* cryptlib PKCS #11 Init/Shutdown Routines *
* Copyright Peter Gutmann 1998-2005 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "context.h"
#include "device.h"
#include "pkcs11_api.h"
#include "asn1.h"
#else
#include "crypt.h"
#include "context/context.h"
#include "device/device.h"
#include "device/pkcs11_api.h"
#include "misc/asn1.h"
#endif /* Compiler-specific includes */
#ifdef USE_PKCS11
/* The max. number of drivers we can work with and the max.number of slots
per driver */
#define MAX_PKCS11_DRIVERS 5
#define MAX_PKCS11_SLOTS 16
/* The default slot to look for tokens in */
#define DEFAULT_SLOT 0
/* Define the following to explicitly link each PKCS #11 function rather than
using C_GetFunctionList(). Note that this will require changes to the way
the functions are accessed, since currently it's done via a global function
pointer table in the pkcs11Info struct */
/* #define USE_EXPLICIT_LINKING */
/* Prototypes for functions in pkcs11.c */
time_t getTokenTime( CK_TOKEN_INFO *tokenInfo );
int genericEndFunction( CONTEXT_INFO *contextInfoPtr );
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Get random data from the device */
static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
const int length,
MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
{
CK_RV status;
PKCS11_INFO *pkcs11Info = deviceInfo->devicePKCS11;
status = C_GenerateRandom( pkcs11Info->hSession, buffer, length );
return( pkcs11MapError( pkcs11Info, status, CRYPT_ERROR_FAILED ) );
}
/* Perform a self-test */
static int selfTestFunction( void )
{
/* PKCS #11 doesn't provide any explicit means of performing a self-
test of a capability, and having to go through the gyrations needed
to do this via the PKCS #11 interface is excessively complex, so we
just assume that everything is OK. In general what a device does is
device-specific, for example as part of FIPS 140 requirements or even
just as general good engineering many will perform a self-test on
power-up while others (typically smart cards) barely do any checking
at all. The result that we return here is an implicit "whatever the
device does" */
return( CRYPT_ERROR_NOTAVAIL );
}
/****************************************************************************
* *
* Init/Shutdown Routines *
* *
****************************************************************************/
/* Whether the PKCS #11 library has been initialised or not, this is
initialised on demand the first time it's accessed */
static BOOLEAN pkcs11Initialised = FALSE;
#ifdef DYNAMIC_LOAD
/* Since we can be using multiple PKCS #11 drivers, we define an array of
them and access the appropriate one by name */
typedef struct {
char name[ 32 + 1 + 8 ]; /* Name of device */
INSTANCE_HANDLE hPKCS11; /* Handle to driver */
CK_FUNCTION_LIST_PTR functionListPtr; /* Driver access info */
#ifdef USE_EXPLICIT_LINKING
CK_C_CloseSession pC_CloseSession; /* Interface function pointers */
CK_C_CreateObject pC_CreateObject;
CK_C_Decrypt pC_Decrypt;
CK_C_DecryptInit pC_DecryptInit;
CK_C_DestroyObject pC_DestroyObject;
CK_C_Encrypt pC_Encrypt;
CK_C_EncryptInit pC_EncryptInit;
CK_C_Finalize pC_Finalize;
CK_C_FindObjects pC_FindObjects;
CK_C_FindObjectsFinal pC_FindObjectsFinal;
CK_C_FindObjectsInit pC_FindObjectsInit;
CK_C_GenerateKey pC_GenerateKey;
CK_C_GenerateKeyPair pC_GenerateKeyPair;
CK_C_GenerateRandom pC_GenerateRandom;
CK_C_GetAttributeValue pC_GetAttributeValue;
CK_C_GetMechanismInfo pC_GetMechanismInfo;
CK_C_GetSlotInfo pC_GetSlotInfo;
CK_C_GetSlotList pC_GetSlotList;
CK_C_GetTokenInfo pC_GetTokenInfo;
CK_C_InitPIN pC_InitPIN;
CK_C_InitToken pC_InitToken;
CK_C_Login pC_Login;
CK_C_Logout pC_Logout;
CK_C_OpenSession pC_OpenSession;
CK_C_SetAttributeValue pC_SetAttributeValue;
CK_C_SetPIN pC_SetPIN;
CK_C_Sign pC_Sign;
CK_C_SignFinal pC_SignFinal;
CK_C_SignInit pC_SignInit;
CK_C_SignUpdate pC_SignUpdate;
CK_C_UnwrapKey pC_UnwrapKey;
CK_C_Verify pC_Verify;
CK_C_VerifyInit pC_VerifyInit;
#endif /* USE_EXPLICIT_LINKING */
} PKCS11_DRIVER_INFO;
static PKCS11_DRIVER_INFO pkcs11InfoTbl[ MAX_PKCS11_DRIVERS + 8 ];
/* The use of dynamically bound function pointers vs.statically linked
functions requires a bit of sleight of hand since we can't give the
pointers the same names as prototyped functions. To get around this we
redefine the actual function names to the names of the pointers */
#ifdef USE_EXPLICIT_LINKING
#define C_CloseSession pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_CloseSession
#define C_CreateObject pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_CreateObject
#define C_Decrypt pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Decrypt
#define C_DecryptInit pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_DecryptInit
#define C_DestroyObject pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_DestroyObject
#define C_Encrypt pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Encrypt
#define C_EncryptInit pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_EncryptInit
#define C_Finalize pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Finalize
#define C_FindObjects pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_FindObjects
#define C_FindObjectsFinal pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_FindObjectsFinal
#define C_FindObjectsInit pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_FindObjectsInit
#define C_GenerateKey pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GenerateKey
#define C_GenerateKeyPair pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GenerateKeyPair
#define C_GenerateRandom pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GenerateRandom
#define C_GetAttributeValue pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GetAttributeValue
#define C_GetMechanismInfo pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GetMechanismInfo
#define C_GetSlotInfo pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GetSlotInfo
#define C_GetSlotList pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GetSlotList
#define C_GetTokenInfo pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_GetTokenInfo
#define C_Initialize pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Initialize
#define C_InitPIN pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_InitPIN
#define C_InitToken pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_InitToken
#define C_Login pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Login
#define C_Logout pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Logout
#define C_OpenSession pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_OpenSession
#define C_SetAttributeValue pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_SetAttributeValue
#define C_SetPIN pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_SetPIN
#define C_Sign pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Sign
#define C_SignFinal pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_SignFinal
#define C_SignInit pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_SignInit
#define C_SignUpdate pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_SignUpdate
#define C_UnwrapKey pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_UnwrapKey
#define C_Verify pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_Verify
#define C_VerifyInit pkcs11InfoTbl[ pkcs11Info->deviceNo ].pC_VerifyInit
#endif /* USE_EXPLICIT_LINKING */
/* Dynamically load and unload any necessary PKCS #11 drivers */
static int loadPKCS11driver( PKCS11_DRIVER_INFO *pkcs11Info,
const char *driverName )
{
#ifdef USE_EXPLICIT_LINKING
CK_C_GetInfo pC_GetInfo;
CK_C_Initialize pC_Initialize;
#else
CK_C_GetFunctionList pC_GetFunctionList;
#endif /* USE_EXPLICIT_LINKING */
CK_INFO info;
CK_RV status;
#ifdef __WIN16__
UINT errorMode;
#endif /* __WIN16__ */
BOOLEAN isInitialised = FALSE;
int i = 32;
/* Obtain a handle to the device driver module */
#ifdef __WIN16__
errorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX );
pkcs11Info->hPKCS11 = LoadLibrary( driverName );
SetErrorMode( errorMode );
if( pkcs11Info->hPKCS11 < HINSTANCE_ERROR )
{
pkcs11Info->hPKCS11 = NULL_HINSTANCE;
return( CRYPT_ERROR );
}
#else
if( ( pkcs11Info->hPKCS11 = DynamicLoad( driverName ) ) == NULL_INSTANCE )
return( CRYPT_ERROR );
#endif /* OS-specific dynamic load */
/* Now get pointers to the functions */
#ifdef USE_EXPLICIT_LINKING
pC_GetInfo = ( CK_C_GetInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetInfo" );
pC_Initialize = ( CK_C_Initialize ) DynamicBind( pkcs11Info->hPKCS11, "C_Initialize" );
pkcs11Info->pC_CloseSession = ( CK_C_CloseSession ) DynamicBind( pkcs11Info->hPKCS11, "C_CloseSession" );
pkcs11Info->pC_CreateObject = ( CK_C_CreateObject ) DynamicBind( pkcs11Info->hPKCS11, "C_CreateObject" );
pkcs11Info->pC_Decrypt = ( CK_C_Decrypt ) DynamicBind( pkcs11Info->hPKCS11, "C_Decrypt" );
pkcs11Info->pC_DecryptInit = ( CK_C_DecryptInit ) DynamicBind( pkcs11Info->hPKCS11, "C_DecryptInit" );
pkcs11Info->pC_DestroyObject = ( CK_C_DestroyObject ) DynamicBind( pkcs11Info->hPKCS11, "C_DestroyObject" );
pkcs11Info->pC_Encrypt = ( CK_C_Encrypt ) DynamicBind( pkcs11Info->hPKCS11, "C_Encrypt" );
pkcs11Info->pC_EncryptInit = ( CK_C_EncryptInit ) DynamicBind( pkcs11Info->hPKCS11, "C_EncryptInit" );
pkcs11Info->pC_Finalize = ( CK_C_Finalize ) DynamicBind( pkcs11Info->hPKCS11, "C_Finalize" );
pkcs11Info->pC_FindObjects = ( CK_C_FindObjects ) DynamicBind( pkcs11Info->hPKCS11, "C_FindObjects" );
pkcs11Info->pC_FindObjectsFinal = ( CK_C_FindObjectsFinal ) DynamicBind( pkcs11Info->hPKCS11, "C_FindObjectsFinal" );
pkcs11Info->pC_FindObjectsInit = ( CK_C_FindObjectsInit ) DynamicBind( pkcs11Info->hPKCS11, "C_FindObjectsInit" );
pkcs11Info->pC_GenerateKey = ( CK_C_GenerateKey ) DynamicBind( pkcs11Info->hPKCS11, "C_GenerateKey" );
pkcs11Info->pC_GenerateKeyPair = ( CK_C_GenerateKeyPair ) DynamicBind( pkcs11Info->hPKCS11, "C_GenerateKeyPair" );
pkcs11Info->pC_GenerateRandom = ( CK_C_GenerateRandom ) DynamicBind( pkcs11Info->hPKCS11, "C_GenerateRandom" );
pkcs11Info->pC_GetAttributeValue = ( CK_C_GetAttributeValue ) DynamicBind( pkcs11Info->hPKCS11, "C_GetAttributeValue" );
pkcs11Info->pC_GetMechanismInfo = ( CK_C_GetMechanismInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetMechanismInfo" );
pkcs11Info->pC_GetSlotInfo = ( CK_C_GetSlotInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetSlotInfo" );
pkcs11Info->pC_GetSlotList = ( CK_C_GetSlotList ) DynamicBind( pkcs11Info->hPKCS11, "C_GetSlotList" );
pkcs11Info->pC_GetTokenInfo = ( CK_C_GetTokenInfo ) DynamicBind( pkcs11Info->hPKCS11, "C_GetTokenInfo" );
pkcs11Info->pC_InitPIN = ( CK_C_InitPIN ) DynamicBind( pkcs11Info->hPKCS11, "C_InitPIN" );
pkcs11Info->pC_InitToken = ( CK_C_InitToken ) DynamicBind( pkcs11Info->hPKCS11, "C_InitToken" );
pkcs11Info->pC_Login = ( CK_C_Login ) DynamicBind( pkcs11Info->hPKCS11, "C_Login" );
pkcs11Info->pC_Logout = ( CK_C_Logout ) DynamicBind( pkcs11Info->hPKCS11, "C_Logout" );
pkcs11Info->pC_OpenSession = ( CK_C_OpenSession ) DynamicBind( pkcs11Info->hPKCS11, "C_OpenSession" );
pkcs11Info->pC_SetAttributeValue = ( CK_C_SetAttributeValue ) DynamicBind( pkcs11Info->hPKCS11, "C_SetAttributeValue" );
pkcs11Info->pC_SetPIN = ( CK_C_SetPIN ) DynamicBind( pkcs11Info->hPKCS11, "C_SetPIN" );
pkcs11Info->pC_SignFinal = ( CK_C_SignFinal ) DynamicBind( pkcs11Info->hPKCS11, "C_SignFinal" );
pkcs11Info->pC_SignInit = ( CK_C_SignInit ) DynamicBind( pkcs11Info->hPKCS11, "C_SignInit" );
pkcs11Info->pC_SignUpdate = ( CK_C_SignUpdate ) DynamicBind( pkcs11Info->hPKCS11, "C_SignUpdate" );
pkcs11Info->pC_UnwrapKey = ( CK_C_UnwrapKey ) DynamicBind( pkcs11Info->hPKCS11, "C_UnwrapKey" );
pkcs11Info->pC_Verify = ( CK_C_Verify ) DynamicBind( pkcs11Info->hPKCS11, "C_Verify" );
pkcs11Info->pC_VerifyInit = ( CK_C_VerifyInit ) DynamicBind( pkcs11Info->hPKCS11, "C_VerifyInit" );
/* Make sure that we got valid pointers for every device function.
C_FindObjectsFinal() wasn't added until 2.x and some drivers don't
implement it (a smaller subset of them nevertheless claim to be 2.x
drivers), so we allow this to be null - the code won't call it if it's
not present */
if( pC_GetInfo == NULL || pC_Initialize == NULL ||
pkcs11Info->pC_CloseSession == NULL ||
pkcs11Info->pC_CreateObject == NULL ||
pkcs11Info->pC_Decrypt == NULL ||
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_GenerateKey == 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_SignFinal == NULL || pkcs11Info->pC_SignInit == NULL ||
pkcs11Info->pC_SignUpdate == 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -