void InfoTests::testGetInfo() { CK_RV rv; CK_INFO ckInfo; // Just make sure that we finalize any previous failed tests C_Finalize(NULL_PTR); rv = C_GetInfo(&ckInfo); CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED); rv = C_Initialize(NULL_PTR); CPPUNIT_ASSERT(rv == CKR_OK); rv = C_GetInfo(NULL_PTR); CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD); rv = C_GetInfo(&ckInfo); CPPUNIT_ASSERT(rv == CKR_OK); C_Finalize(NULL_PTR); }
static int loadPKCS11driver( PKCS11_DRIVER_INFO *pkcs11Info, const char *driverName ) { CK_C_GetFunctionList pC_GetFunctionList; CK_INFO info DUMMY_INIT_STRUCT; CK_RV status; #ifdef __WIN16__ UINT errorMode; #endif /* __WIN16__ */ BOOLEAN isInitialised = FALSE; int i = 32; assert( isWritePtr( pkcs11Info, sizeof( PKCS11_DRIVER_INFO ) ) ); assert( isReadPtr( driverName, 4 ) ); /* 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 */ /* Get the access information for the PKCS #11 library, initialise it, and get information 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 { CK_FUNCTION_LIST_PTR functionListPtr; /* The following two-step initialisation is needed because PKCS #11 uses a 1-byte alignment on structs, which means that if we pass in the pkcs11Info member address directly we run into alignment problems with 64-bit architectures */ status = pC_GetFunctionList( &functionListPtr ) & 0xFFFF; if( status == CKR_OK ) pkcs11Info->functionListPtr = functionListPtr; } if( status != CKR_OK ) { /* Free the library reference and clear the information */ DynamicUnload( pkcs11Info->hPKCS11 ); memset( pkcs11Info, 0, sizeof( PKCS11_DRIVER_INFO ) ); return( CRYPT_ERROR ); } status = C_Initialize( NULL_PTR ) & 0xFFFF; if( status == CKR_ARGUMENTS_BAD && \ strFindStr( driverName, strlen( driverName ), "softokn3.", 9 ) >= 0 ) { typedef struct CK_C_INITIALIZE_ARGS { CK_CREATEMUTEX CreateMutex; CK_DESTROYMUTEX DestroyMutex; CK_LOCKMUTEX LockMutex; CK_UNLOCKMUTEX UnlockMutex; CK_FLAGS flags; CK_VOID_PTR LibraryParameters; CK_VOID_PTR pReserved; } Netscape_CK_C_INITIALIZE_ARGS; Netscape_CK_C_INITIALIZE_ARGS initArgs; /* Netscape invented their own extension to CK_C_INITIALIZE_ARGS, adding a 'LibraryParameters' string to allow the specification of free-form parameters. If the Netscape library's C_Initialize() is called then it'll return CKR_ARGUMENTS_BAD (rather than assuming sensible default values), so that we have to call it again with explicitly-specified parameters. Even this doesn't work properly though, according to the Netscape docs we can set LibraryParameters to NULL, but this still results in C_Initialize() returning CKR_ARGUMENTS_BAD. Later in the docs is a requirement that the softokn3 library be passed a "parameters=" string, but it's unclear what parameters need to be set, to what values, and what effect these values may have on the behaviour of existing configs for applications like Firefox. The following config lets the C_Initialize() call succeed but causes odd failures later in other PKCS #11 functions */ DEBUG_DIAG(( "Driver is the buggy Netscape/NSS one that requires " "nonstandard initialisation, see the code comment for " "details" )); assert( DEBUG_WARN ); memset( &initArgs, 0, sizeof( Netscape_CK_C_INITIALIZE_ARGS ) ); initArgs.LibraryParameters = \ "configdir='.' certPrefix='' keyPrefix='' secmod='secmod.db' " "flags=noModDB,noCertDB,noKeyDB,optimizeSpace,readOnly"; status = C_Initialize( &initArgs ); } 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 ); } /* 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 ); }