int open_session_and_login()
{
	CK_RV rv = CKR_OK;

	rv = C_Initialize(NULL_PTR);
	if (CKR_OK != rv)
		return EXIT_FAILURE;

	rv = C_OpenSession(FEPKCS11_APP0_TOKEN_SLOT_ID,
			   CKF_RW_SESSION | CKF_SERIAL_SESSION,
			   NULL,
			   NULL,
			   &hSession);
	if (CKR_OK != rv) {
		C_Finalize(NULL_PTR);
		return EXIT_FAILURE;
	}

	rv = C_Login(hSession, CKU_USER, NULL_PTR, 0);
	if (CKR_OK != rv) {
		C_CloseSession(hSession);
		C_Finalize(NULL_PTR);
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}
void InfoTests::testGetTokenInfo()
{
	CK_RV rv;
	CK_TOKEN_INFO tokenInfo;

	// Just make sure that we finalize any previous failed tests
	C_Finalize(NULL_PTR);

	rv = C_GetTokenInfo(SLOT_NO_INIT_TOKEN, &tokenInfo);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_GetTokenInfo(SLOT_NO_INIT_TOKEN, NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_GetTokenInfo(SLOT_INVALID, &tokenInfo);
	CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);

	rv = C_GetTokenInfo(SLOT_NO_INIT_TOKEN, &tokenInfo);
	CPPUNIT_ASSERT(rv == CKR_OK);

	CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0);

	rv = C_GetTokenInfo(SLOT_INIT_TOKEN, &tokenInfo);
	CPPUNIT_ASSERT(rv == CKR_OK);

	CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);

	C_Finalize(NULL_PTR);
}
void InfoTests::testGetSlotList()
{
	CK_RV rv;
	CK_ULONG ulSlotCount = 0;
	CK_SLOT_ID_PTR pSlotList;

	// Just make sure that we finalize any previous failed tests
	C_Finalize(NULL_PTR);

	rv = C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_GetSlotList(CK_FALSE, NULL_PTR, NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	// Get the size of the buffer
	rv = C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	pSlotList = (CK_SLOT_ID_PTR)malloc(ulSlotCount * sizeof(CK_SLOT_ID));

	// Check if we have a too small buffer
	ulSlotCount = 0;
	rv = C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);

	// Get the slot list
	rv = C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	free(pSlotList);

	// Get the number of slots with tokens
	rv = C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	pSlotList = (CK_SLOT_ID_PTR)malloc(ulSlotCount * sizeof(CK_SLOT_ID));

	// Check if we have a too small buffer
	ulSlotCount = 0;
	rv = C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);

	// Get the slot list
	rv = C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	free(pSlotList);

	C_Finalize(NULL_PTR);
}
void TokenTests::testInitToken()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR label[32];
	CK_SESSION_HANDLE hSession;

	memset(label, ' ', 32);
	memcpy(label, "token1", strlen("token1"));

	// Just make sure that we finalize any previous failed tests
	C_Finalize(NULL_PTR);

	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_InitToken(SLOT_INIT_TOKEN, NULL_PTR, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_InitToken(SLOT_INVALID, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);

	// Initialize
	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Initialize with wrong password
	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength - 1, label);
	CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_SESSION_EXISTS);

	rv = C_CloseSession(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Re-initialize
	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_OK);

	C_Finalize(NULL_PTR);
}
Exemple #5
0
void UserTests::testLogout()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Login(hSession, CKU_SO, pin, pinLength);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Logout(CK_INVALID_HANDLE);
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_Logout(hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);
}
void logout_and_close_session()
{
	C_Logout(hSession);
	C_CloseSession(hSession);
	C_Finalize(NULL_PTR);
	hSession = CK_INVALID_HANDLE;
}
void SymmetricAlgorithmTests::testDesEncryptDecrypt()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	// CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	// CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSessionRO;
	CK_SESSION_HANDLE hSessionRW;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Open read-only session on when the token is not initialized should fail
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	// Initialize the library and start the test.
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-only session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-write session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Login USER into the sessions so we can create a private objects
	rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
	CPPUNIT_ASSERT(rv==CKR_OK);

	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;

	// Generate all combinations of session/token keys.
	rv = generateDesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	desEncryptDecrypt(CKM_DES_ECB,hSessionRO,hKey);
	desEncryptDecrypt(CKM_DES_CBC,hSessionRO,hKey);

	CK_OBJECT_HANDLE hKey2 = CK_INVALID_HANDLE;

	// Generate all combinations of session/token keys.
	rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey2);
	CPPUNIT_ASSERT(rv == CKR_OK);

	des3EncryptDecrypt(CKM_DES3_ECB,hSessionRO,hKey2);
	des3EncryptDecrypt(CKM_DES3_CBC,hSessionRO,hKey2);

	CK_OBJECT_HANDLE hKey3 = CK_INVALID_HANDLE;

	// Generate all combinations of session/token keys.
	rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey3);
	CPPUNIT_ASSERT(rv == CKR_OK);

	des3EncryptDecrypt(CKM_DES3_ECB,hSessionRO,hKey3);
	des3EncryptDecrypt(CKM_DES3_CBC,hSessionRO,hKey3);
}
void SymmetricAlgorithmTests::testAesWrapUnwrap()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	// CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	// CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSession;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Initialize the library and start the test.
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Login USER into the session so we can create a private object
	rv = C_Login(hSession,CKU_USER,pin,pinLength);
	CPPUNIT_ASSERT(rv==CKR_OK);

	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;

	// Generate a wrapping session public key
	rv = generateAesKey(hSession,IN_SESSION,IS_PUBLIC,hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	aesWrapUnwrap(CKM_AES_KEY_WRAP, hSession, hKey);
#ifdef HAVE_AES_KEY_WRAP_PAD
	aesWrapUnwrap(CKM_AES_KEY_WRAP_PAD, hSession, hKey);
#endif
}
void SymmetricAlgorithmTests::testNullTemplate()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_SESSION_HANDLE hSession;
	CK_MECHANISM mechanism1 = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
	CK_MECHANISM mechanism2 = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Initialize the library and start the test.
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-write session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Login USER into the sessions so we can create a private objects
	rv = C_Login(hSession, CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv==CKR_OK);

	rv = C_GenerateKey(hSession, &mechanism1, NULL_PTR, 0, &hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_DestroyObject(hSession, hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_GenerateKey(hSession, &mechanism2, NULL_PTR, 0, &hKey);
	CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCOMPLETE);
}
Exemple #10
0
void DigestTests::testDigestKey()
{
	CK_RV rv;
	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
	CK_MECHANISM mechanism = {
		CKM_SHA512, NULL_PTR, 0
	};
	CK_BYTE data[] = {"Text to digest"};

	// Just make sure that we finalize any previous tests
	CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );

	rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, (CK_OBJECT_HANDLE)123UL) );
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Create the generic secret key to digest
	CK_BBOOL bFalse = CK_FALSE;
	CK_BBOOL bTrue = CK_TRUE;
	CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
	CK_KEY_TYPE genKeyType = CKK_GENERIC_SECRET;
	CK_ATTRIBUTE attribs[] = {
		{ CKA_CLASS, &secretClass, sizeof(secretClass) },
		{ CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
		{ CKA_TOKEN, &bFalse, sizeof(bFalse) },
		{ CKA_PRIVATE, &bFalse, sizeof(bFalse) },
		{ CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
		{ CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
		{ CKA_VALUE, data, sizeof(data) - 1 }
	};
	CK_OBJECT_HANDLE hKey;

	hKey = CK_INVALID_HANDLE;
	rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hKey) );
	CPPUNIT_ASSERT(rv == CKR_OK);
	CPPUNIT_ASSERT(hKey != CK_INVALID_HANDLE);

	rv = CRYPTOKI_F_PTR( C_DigestKey(CK_INVALID_HANDLE, hKey) );
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
	
	rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, hKey) );
	CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);

	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, CK_INVALID_HANDLE) );
	CPPUNIT_ASSERT(rv == CKR_KEY_HANDLE_INVALID);

	rv = CRYPTOKI_F_PTR( C_DigestKey(hSession, hKey) );
	CPPUNIT_ASSERT(rv == CKR_OK);
}
void InfoTests::testGetMechanismInfo()
{
	CK_RV rv;
	CK_MECHANISM_INFO info;
	CK_ULONG ulMechCount = 0;
	CK_MECHANISM_TYPE_PTR pMechanismList;

	// Just make sure that we finalize any previous failed tests
	C_Finalize(NULL_PTR);

	rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, CKM_RSA_PKCS, &info);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Get the mechanism list
	rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	CPPUNIT_ASSERT(ulMechCount != 0);
	pMechanismList = (CK_MECHANISM_TYPE_PTR)malloc(ulMechCount * sizeof(CK_MECHANISM_TYPE_PTR));
	rv = C_GetMechanismList(SLOT_INIT_TOKEN, pMechanismList, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, pMechanismList[0], NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_GetMechanismInfo(SLOT_INVALID, pMechanismList[0], &info);
	CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);

	rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, CKM_VENDOR_DEFINED, &info);
	CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);

	for (unsigned int i = 0; i < ulMechCount; i++)
	{
		rv = C_GetMechanismInfo(SLOT_INIT_TOKEN, pMechanismList[i], &info);
		CPPUNIT_ASSERT(rv == CKR_OK);
	}

	free(pMechanismList);

	C_Finalize(NULL_PTR);
}
Exemple #12
0
void DigestTests::testDigest()
{
	CK_RV rv;
	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
	CK_MECHANISM mechanism = {
		CKM_SHA512, NULL_PTR, 0
	};
	CK_ULONG digestLen;
	CK_BYTE_PTR digest;
	CK_BYTE data[] = {"Text to digest"};

	// Just make sure that we finalize any previous tests
	CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_Digest(CK_INVALID_HANDLE, data, sizeof(data)-1, NULL_PTR, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
	
	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);

	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, NULL_PTR, sizeof(data)-1, NULL_PTR, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	digest = (CK_BYTE_PTR)malloc(digestLen);
	digestLen = 0;

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
	CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
	free(digest);
}
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);
}
Exemple #14
0
static void crypto_token_logout(CK_SESSION_HANDLE hSession)
{
	CK_RV rv = CKR_OK;

	rv = C_Logout(hSession);
	assert(rv == CKR_OK);

	rv = C_CloseSession(hSession);
	assert(rv == CKR_OK);

	rv = C_Finalize(NULL_PTR);
	assert(rv == CKR_OK);
}
void InfoTests::testGetMechanismList()
{
	CK_RV rv;
	CK_ULONG ulMechCount = 0;
	CK_MECHANISM_TYPE_PTR pMechanismList;

	// Just make sure that we finalize any previous failed tests
	C_Finalize(NULL_PTR);

	rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = C_GetMechanismList(SLOT_INVALID, NULL_PTR, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);

	// Get the size of the buffer
	rv = C_GetMechanismList(SLOT_INIT_TOKEN, NULL_PTR, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	pMechanismList = (CK_MECHANISM_TYPE_PTR)malloc(ulMechCount * sizeof(CK_MECHANISM_TYPE_PTR));

	// Check if we have a too small buffer
	ulMechCount = 0;
	rv = C_GetMechanismList(SLOT_INIT_TOKEN, pMechanismList, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);

	// Get the mechanism list
	rv = C_GetMechanismList(SLOT_INIT_TOKEN, pMechanismList, &ulMechCount);
	CPPUNIT_ASSERT(rv == CKR_OK);
	free(pMechanismList);

	C_Finalize(NULL_PTR);
}
void CUsbKeyOperation::ExitInstance(void)
{
	CK_RV rv;
	rv = C_Finalize(NULL);
	if(CKR_OK != rv)
	{
		LOG(ERROR)<<"Can't Unload PKCS#11 ET199 Library!";
	}
	else
	{
		LOG(INFO)<<"Unload PKCS#11 USBKEY Library OK.";
	}
	return;
}
Exemple #17
0
void DigestTests::testDigestAll()
{
	CK_RV rv;
	CK_SESSION_HANDLE hSession;
	CK_MECHANISM mechanisms[] = {
#ifndef WITH_FIPS
		{ CKM_MD5, NULL_PTR, 0 },
#endif
		{ CKM_SHA_1, NULL_PTR, 0 },
		{ CKM_SHA224, NULL_PTR, 0 },
		{ CKM_SHA256, NULL_PTR, 0 },
		{ CKM_SHA384, NULL_PTR, 0 },
		{ CKM_SHA512, NULL_PTR, 0 },
#ifdef WITH_GOST
		{ CKM_GOSTR3411, NULL_PTR, 0 },
#endif
	};
	CK_ULONG digestLen;
	CK_BYTE_PTR digest;
	CK_BYTE data[] = {"Text to digest"};

	// Just make sure that we finalize any previous tests
	CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );

	rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	for (unsigned int i = 0; i < sizeof(mechanisms)/sizeof(CK_MECHANISM); i++)
	{
		rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanisms[i]) );
		CPPUNIT_ASSERT(rv == CKR_OK);

		rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, NULL_PTR, &digestLen) );
		CPPUNIT_ASSERT(rv == CKR_OK);

		digest = (CK_BYTE_PTR)malloc(digestLen);

		rv = CRYPTOKI_F_PTR( C_Digest(hSession, data, sizeof(data)-1, digest, &digestLen) );
		CPPUNIT_ASSERT(rv == CKR_OK);
		free(digest);
	}
}
Exemple #18
0
BOOL CPKCSDemoApp::InitInstance()
{
	AfxEnableControlContainer();

	CK_RV rv;

	rv = C_Initialize(NULL_PTR);
	if(CKR_OK != rv)
	{
		AfxMessageBox("Can not load ePassNG PKCS#11 runtime!", MB_OK | MB_ICONERROR);
		return FALSE;
	}

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	CPKCSDemoDlg dlg;
	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with Cancel
	}

	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.

	C_Finalize(NULL_PTR);

	return FALSE;
}
void EncryptDecryptTests::testRsaEncryptDecrypt()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR sopin[] = SLOT_0_SO1_PIN;
	CK_ULONG sopinLength = sizeof(sopin) - 1;
	CK_SESSION_HANDLE hSessionRO;
	CK_SESSION_HANDLE hSessionRW;

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Open read-only session on when the token is not initialized should fail
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	// Initialize the library and start the test.
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-only session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-write session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Login USER into the sessions so we can create a private objects
	rv = C_Login(hSessionRO,CKU_USER,pin,pinLength);
	CPPUNIT_ASSERT(rv==CKR_OK);

	CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
	CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;

	// Generate all combinations of session/token public/private key pairs.
	rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rsaEncryptDecrypt(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
	rsaEncryptDecrypt(CKM_RSA_X_509,hSessionRO,hPublicKey,hPrivateKey);
	rsaEncryptDecrypt(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
}
Exemple #20
0
void UserTests::setUp()
{
//    printf("\nUserTests\n");

	setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);

	CK_UTF8CHAR pin[] = SLOT_0_SO1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_UTF8CHAR label[32];
	memset(label, ' ', 32);
	memcpy(label, "token1", strlen("token1"));

	// (Re)initialize the token
	CK_RV rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);
	rv = C_InitToken(SLOT_INIT_TOKEN, pin, pinLength, label);
	CPPUNIT_ASSERT(rv == CKR_OK);
	C_Finalize(NULL_PTR);
}
Exemple #21
0
/*
 * close all the opened sessions when finished with Cryptoki library.
 */
static int free_slots (int majorID, int minorID, void *serverarg, void *clientarg)
{
    int slotcount, i;

    if (pSlot != NULL)
    {
        slotcount = pSlot->count;
        for (i = 0; i < slotcount; i++)
        {
            if (pSlot->pSession->hdl != NULL)
            {
                free (pSlot->pSession->hdl);
            }
        }
        free (pSlot);
    }

    (void) C_Finalize (NULL);
    return 0;
}
void AsymEncryptDecryptTests::testRsaEncryptDecrypt()
{
	CK_RV rv;
	CK_SESSION_HANDLE hSessionRO;
	CK_SESSION_HANDLE hSessionRW;

	// Just make sure that we finalize any previous tests
	CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );

	// Open read-only session on when the token is not initialized should fail
	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	// Initialize the library and start the test.
	rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-only session
	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-write session
	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Login USER into the sessions so we can create a private objects
	rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
	CPPUNIT_ASSERT(rv==CKR_OK);

	CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
	CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;

	// Generate all combinations of session/token public/private key pairs.
	rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPublicKey,hPrivateKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rsaOAEPParams(hSessionRO,hPublicKey);
	rsaEncryptDecrypt(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
	rsaEncryptDecrypt(CKM_RSA_X_509,hSessionRO,hPublicKey,hPrivateKey);
	rsaEncryptDecrypt(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
}
Exemple #23
0
void deviceEndPKCS11( void )
	{
	int i;

	if( pkcs11Initialised )
		{
		for( i = 0; i < MAX_PKCS11_DRIVERS; i++ )
			{
			if( pkcs11InfoTbl[ i ].hPKCS11 != NULL_INSTANCE )
				{
				PKCS11_DRIVER_INFO *pkcs11Info = &pkcs11InfoTbl[ i ];
						/* Needed in macro-ised form of C_Finalize() */

				C_Finalize( NULL_PTR );

				DynamicUnload( pkcs11InfoTbl[ i ].hPKCS11 );
				}
			pkcs11InfoTbl[ i ].hPKCS11 = NULL_INSTANCE;
			}
		}
	pkcs11Initialised = FALSE;
	}
/******************************************************************************
** Function: DllMain
**
** Required entry point for WIN32 DLL's
**
** Parameters:
**  hModule            -
**  ul_reason_for_call -
**  lpReserved         -
**
** Returns:
**  TRUE
*******************************************************************************/
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            log_Log(LOG_LOW, "WIN32DLL: Process attach");
            break;
        case DLL_THREAD_ATTACH:
            log_Log(LOG_LOW, "WIN32DLL: Thread attach");
            break;
        case DLL_THREAD_DETACH:
            log_Log(LOG_LOW, "WIN32DLL: Thread detach");
            break;
        case DLL_PROCESS_DETACH:
            log_Log(LOG_LOW, "WIN32DLL: Process detach");
            C_Finalize(0);
            break;
    }
    return TRUE;
}
Exemple #25
0
void DigestTests::testDigestInit()
{
	CK_RV rv;
	CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
	CK_MECHANISM mechanism = {
		CKM_VENDOR_DEFINED, NULL_PTR, 0
	};

	// Just make sure that we finalize any previous tests
	CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );

	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);

	rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, NULL_PTR) );
	CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);

	rv = CRYPTOKI_F_PTR( C_DigestInit(CK_INVALID_HANDLE, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);

	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);

	mechanism.mechanism = CKM_SHA512;
	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) );
	CPPUNIT_ASSERT(rv == CKR_OPERATION_ACTIVE);
}
CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
{
	CK_RV rv;
#if !defined(_WIN32)
	pid_t current_pid = getpid();
#endif
	int rc;
	unsigned int i;
	sc_context_param_t ctx_opts;

#if !defined(_WIN32)
	/* Handle fork() exception */
	if (current_pid != initialized_pid) {
		if (context)
			context->flags |= SC_CTX_FLAG_TERMINATE;
		C_Finalize(NULL_PTR);
	}
	initialized_pid = current_pid;
	in_finalize = 0;
#endif

	if (context != NULL) {
		sc_log(context, "C_Initialize(): Cryptoki already initialized\n");
		return CKR_CRYPTOKI_ALREADY_INITIALIZED;
	}

	rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pInitArgs);
	if (rv != CKR_OK)
		goto out;

	/* set context options */
	memset(&ctx_opts, 0, sizeof(sc_context_param_t));
	ctx_opts.ver        = 0;
	ctx_opts.app_name   = MODULE_APP_NAME;
	ctx_opts.thread_ctx = &sc_thread_ctx;

	rc = sc_context_create(&context, &ctx_opts);
	if (rc != SC_SUCCESS) {
		rv = CKR_GENERAL_ERROR;
		goto out;
	}

	/* Load configuration */
	load_pkcs11_parameters(&sc_pkcs11_conf, context);

	/* List of sessions */
	list_init(&sessions);
	list_attributes_seeker(&sessions, session_list_seeker);

	/* List of slots */
	list_init(&virtual_slots);
	list_attributes_seeker(&virtual_slots, slot_list_seeker);

	/* Create a slot for a future "PnP" stuff. */
	if (sc_pkcs11_conf.plug_and_play) {
		create_slot(NULL);
	}

	/* Create slots for readers found on initialization, only if in 2.11 mode */
	if (!sc_pkcs11_conf.plug_and_play) {
		for (i=0; i<sc_ctx_get_reader_count(context); i++) {
			initialize_reader(sc_ctx_get_reader(context, i));
		}
	}

out:
	if (context != NULL)
		sc_log(context, "C_Initialize() = %s", lookup_enum ( RV_T, rv ));

	if (rv != CKR_OK) {
		if (context != NULL) {
			sc_release_context(context);
			context = NULL;
		}
		/* Release and destroy the mutex */
		sc_pkcs11_free_lock();
	}

	return rv;
}
void SymmetricAlgorithmTests::tearDown()
{
	C_Finalize(NULL_PTR);
}
void SymmetricAlgorithmTests::testNonModifiableDesKeyGeneration()
{
	CK_RV rv;
	CK_UTF8CHAR pin[] = SLOT_0_USER1_PIN;
	CK_ULONG pinLength = sizeof(pin) - 1;
	CK_SESSION_HANDLE hSession;
	CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
	CK_BBOOL bFalse = CK_FALSE;
	CK_BBOOL bTrue = CK_TRUE;
	CK_BBOOL bToken = IN_SESSION;

	CK_ATTRIBUTE keyAttribs[] =
		{
		{ CKA_TOKEN, &bToken, sizeof(bToken) },
		{ CKA_PRIVATE, &bTrue, sizeof(bTrue) },
		{ CKA_MODIFIABLE, &bTrue, sizeof(bTrue) },
		{ CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
		{ CKA_DECRYPT, &bTrue, sizeof(bTrue) },
		{ CKA_WRAP, &bTrue, sizeof(bTrue) }
	};

	// Just make sure that we finalize any previous tests
	C_Finalize(NULL_PTR);

	// Initialize the library and start the test.
	rv = C_Initialize(NULL_PTR);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Open read-write session
	rv = C_OpenSession(SLOT_INIT_TOKEN, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Login USER into the sessions so we can create a private objects
	rv = C_Login(hSession, CKU_USER, pin, pinLength);
	CPPUNIT_ASSERT(rv==CKR_OK);

	rv = C_GenerateKey(hSession, &mechanism,
		keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
		&hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	rv = C_DestroyObject(hSession, hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// The C_GenerateKey call failed if CKA_MODIFIABLE was bFalse
	// This was a bug in the SoftHSM implementation
	keyAttribs[2].pValue = &bFalse;
	keyAttribs[2].ulValueLen = sizeof(bFalse);

	rv = C_GenerateKey(hSession, &mechanism,
		keyAttribs, sizeof(keyAttribs) / sizeof(CK_ATTRIBUTE),
		&hKey);
	// The call would fail with CKR_ATTRIBUTE_READ_ONLY
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Now create a template where the CKA_MODIFIABLE attribute is last in the list
	CK_ATTRIBUTE keyAttribs1[] =
	{
		{ CKA_TOKEN, &bToken, sizeof(bToken) },
		{ CKA_PRIVATE, &bTrue, sizeof(bTrue) },
		{ CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
		{ CKA_DECRYPT, &bTrue, sizeof(bTrue) },
		{ CKA_WRAP, &bTrue, sizeof(bTrue) },
		{ CKA_MODIFIABLE, &bTrue, sizeof(bTrue) }
	};

	rv = C_GenerateKey(hSession, &mechanism,
		keyAttribs1, sizeof(keyAttribs1) / sizeof(CK_ATTRIBUTE),
		&hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);

	// Now when CKA_MODIFIABLE is bFalse the key generation succeeds
	keyAttribs1[2].pValue = &bFalse;
	keyAttribs1[2].ulValueLen = sizeof(bFalse);

	rv = C_GenerateKey(hSession, &mechanism,
		keyAttribs1, sizeof(keyAttribs1) / sizeof(CK_ATTRIBUTE),
		&hKey);
	CPPUNIT_ASSERT(rv == CKR_OK);
}
Exemple #29
0
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 );
	}
void InfoTests::tearDown()
{
	// Just make sure that we finalize any previous failed tests
	C_Finalize(NULL_PTR);
}