aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/test
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/test')
-rw-r--r--SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp206
-rw-r--r--SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h55
-rw-r--r--SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp228
-rw-r--r--SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h55
-rw-r--r--SoftHSMv2/src/lib/test/DeriveTests.cpp737
-rw-r--r--SoftHSMv2/src/lib/test/DeriveTests.h73
-rw-r--r--SoftHSMv2/src/lib/test/DigestTests.cpp326
-rw-r--r--SoftHSMv2/src/lib/test/DigestTests.h60
-rw-r--r--SoftHSMv2/src/lib/test/InfoTests.cpp320
-rw-r--r--SoftHSMv2/src/lib/test/InfoTests.h65
-rw-r--r--SoftHSMv2/src/lib/test/InitTests.cpp247
-rw-r--r--SoftHSMv2/src/lib/test/InitTests.h65
-rw-r--r--SoftHSMv2/src/lib/test/Makefile.am40
-rw-r--r--SoftHSMv2/src/lib/test/ObjectTests.cpp2393
-rw-r--r--SoftHSMv2/src/lib/test/ObjectTests.h194
-rw-r--r--SoftHSMv2/src/lib/test/README17
-rw-r--r--SoftHSMv2/src/lib/test/RandomTests.cpp94
-rw-r--r--SoftHSMv2/src/lib/test/RandomTests.h51
-rw-r--r--SoftHSMv2/src/lib/test/SessionTests.cpp176
-rw-r--r--SoftHSMv2/src/lib/test/SessionTests.h57
-rw-r--r--SoftHSMv2/src/lib/test/SignVerifyTests.cpp830
-rw-r--r--SoftHSMv2/src/lib/test/SignVerifyTests.h73
-rw-r--r--SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp998
-rw-r--r--SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h80
-rw-r--r--SoftHSMv2/src/lib/test/TestsBase.cpp49
-rw-r--r--SoftHSMv2/src/lib/test/TestsBase.h44
-rw-r--r--SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp160
-rw-r--r--SoftHSMv2/src/lib/test/TestsNoPINInitBase.h78
-rw-r--r--SoftHSMv2/src/lib/test/TokenTests.cpp98
-rw-r--r--SoftHSMv2/src/lib/test/TokenTests.h50
-rw-r--r--SoftHSMv2/src/lib/test/UserTests.cpp270
-rw-r--r--SoftHSMv2/src/lib/test/UserTests.h56
-rw-r--r--SoftHSMv2/src/lib/test/p11test.cpp92
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2-alt.conf.in6
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2-alt.conf.win326
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2.conf.in6
-rw-r--r--SoftHSMv2/src/lib/test/softhsm2.conf.win326
-rw-r--r--SoftHSMv2/src/lib/test/tokens/dummy.in0
38 files changed, 8361 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp
new file mode 100644
index 0000000..6f06a42
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymEncryptDecryptTests.cpp
+
+ Contains test cases for C_EncryptInit, C_Encrypt, C_DecryptInit, C_Decrypt
+ using asymmetrical algorithms (i.e., RSA)
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "AsymEncryptDecryptTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AsymEncryptDecryptTests);
+
+CK_RV AsymEncryptDecryptTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+void AsymEncryptDecryptTests::rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, 1, NULL_PTR, 0 };
+ CK_BYTE plainText[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE cipherText[256];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE recoveredText[256];
+ CK_ULONG ulRecoveredTextLen;
+ CK_RV rv;
+
+ if (mechanismType == CKM_RSA_PKCS_OAEP)
+ {
+ mechanism.pParameter = &oaepParams;
+ mechanism.ulParameterLen = sizeof(oaepParams);
+ }
+
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulCipherTextLen = sizeof(cipherText);
+ rv =CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText),cipherText,&ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulRecoveredTextLen = sizeof(recoveredText);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CPPUNIT_ASSERT(memcmp(plainText, &recoveredText[ulRecoveredTextLen-sizeof(plainText)], sizeof(plainText)) == 0);
+}
+
+// Check that RSA OAEP mechanism properly validates all input parameters
+void AsymEncryptDecryptTests::rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey)
+{
+ // This is only supported combination of parameters
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 };
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_OAEP, NULL, 0 };
+ CK_RV rv;
+
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ mechanism.pParameter = &oaepParams;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ mechanism.ulParameterLen = sizeof(oaepParams);
+
+ oaepParams.hashAlg = CKM_AES_CBC;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.hashAlg = CKM_SHA_1;
+ oaepParams.mgf = CKG_MGF1_SHA256;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.mgf = CKG_MGF1_SHA1;
+ oaepParams.source = CKZ_DATA_SPECIFIED - 1;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.source = CKZ_DATA_SPECIFIED;
+ oaepParams.pSourceData = &oaepParams;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.ulSourceDataLen = sizeof(oaepParams);
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+
+ oaepParams.pSourceData = NULL;
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD);
+}
+
+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);
+}
diff --git a/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h
new file mode 100644
index 0000000..0b8db04
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymEncryptDecryptTests.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymEncryptDecryptTests.h
+
+ Contains test cases for C_EncryptInit, C_Encrypt, C_DecryptInit, C_Decrypt
+ using asymmetrical algorithms (i.e., RSA)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
+#define _SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class AsymEncryptDecryptTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(AsymEncryptDecryptTests);
+ CPPUNIT_TEST(testRsaEncryptDecrypt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaEncryptDecrypt();
+
+protected:
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void rsaEncryptDecrypt(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+ void rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey);
+};
+
+#endif // !_SOFTHSM_V2_ASYMENCRYPTDECRYPTTESTS_H
diff --git a/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp
new file mode 100644
index 0000000..9614e69
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2014 Red Hat
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymWrapUnwrapTests.cpp
+
+ Contains test cases for C_WrapKey and C_UnwrapKey
+ using asymmetrical algorithms (RSA)
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "AsymWrapUnwrapTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AsymWrapUnwrapTests);
+
+// Generate throw-away (session) symmetric key
+CK_RV AsymWrapUnwrapTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bFalse, sizeof(bTrue) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV AsymWrapUnwrapTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bFalse, sizeof(bFalse) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bFalse, sizeof(bFalse) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+void AsymWrapUnwrapTests::rsaWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_RSA_PKCS_OAEP_PARAMS oaepParams = { CKM_SHA_1, CKG_MGF1_SHA1, CKZ_DATA_SPECIFIED, NULL_PTR, 0 };
+ CK_BYTE cipherText[2048];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE symValue[64];
+ CK_ULONG ulSymValueLen = sizeof(symValue);
+ CK_BYTE unwrappedValue[64];
+ CK_ULONG ulUnwrappedValueLen = sizeof(unwrappedValue);
+ CK_OBJECT_HANDLE symKey = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE unwrappedKey = CK_INVALID_HANDLE;
+ CK_RV rv;
+ CK_ULONG wrappedLenEstimation;
+
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE unwrapTemplate[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_ATTRIBUTE valueTemplate[] = {
+ { CKA_VALUE, &symValue, ulSymValueLen }
+ };
+
+ CK_MECHANISM_INFO mechInfo;
+
+ if (mechanismType == CKM_RSA_PKCS_OAEP)
+ {
+ mechanism.pParameter = &oaepParams;
+ mechanism.ulParameterLen = sizeof(oaepParams);
+ }
+
+ // Generate temporary symmetric key and remember it's value
+ rv = generateAesKey(hSession, symKey);
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, symKey, valueTemplate, sizeof(valueTemplate)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ ulSymValueLen = valueTemplate[0].ulValueLen;
+
+ // CKM_RSA_PKCS Wrap/Unwrap support
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, CKM_RSA_PKCS, &mechInfo) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(mechInfo.flags&CKF_WRAP);
+ CPPUNIT_ASSERT(mechInfo.flags&CKF_UNWRAP);
+
+ // Estimate wrapped length
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hPublicKey, symKey, NULL_PTR, &wrappedLenEstimation) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(wrappedLenEstimation>0);
+
+ // This should always fail because wrapped data have to be longer than 0 bytes
+ ulCipherTextLen = 0;
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hPublicKey, symKey, cipherText, &ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_BUFFER_TOO_SMALL);
+
+ // Do real wrapping
+ ulCipherTextLen = sizeof(cipherText);
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hPublicKey, symKey, cipherText, &ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ // Check length 'estimation'
+ CPPUNIT_ASSERT(wrappedLenEstimation>=ulCipherTextLen);
+
+ rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hPrivateKey, cipherText, ulCipherTextLen, unwrapTemplate, sizeof(unwrapTemplate)/sizeof(CK_ATTRIBUTE), &unwrappedKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ valueTemplate[0].pValue = &unwrappedValue;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, unwrappedKey, valueTemplate, sizeof(valueTemplate)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ ulUnwrappedValueLen = valueTemplate[0].ulValueLen;
+
+ CPPUNIT_ASSERT(ulSymValueLen == ulUnwrappedValueLen);
+ CPPUNIT_ASSERT(memcmp(symValue, unwrappedValue, ulSymValueLen) == 0);
+}
+
+void AsymWrapUnwrapTests::testRsaWrapUnwrap()
+{
+ 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);
+
+ rsaWrapUnwrap(CKM_RSA_PKCS,hSessionRO,hPublicKey,hPrivateKey);
+ rsaWrapUnwrap(CKM_RSA_PKCS_OAEP,hSessionRO,hPublicKey,hPrivateKey);
+}
diff --git a/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h
new file mode 100644
index 0000000..97f6940
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/AsymWrapUnwrapTests.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Red Hat
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ AsymWrapUnwrapTests.h
+
+ Contains test cases for C_WrapKey and C_UnwrapKey
+ using asymmetrical algorithms (RSA)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_ASYMWRAPUNWRAPTESTS_H
+#define _SOFTHSM_V2_ASYMWRAPUNWRAPTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class AsymWrapUnwrapTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(AsymWrapUnwrapTests);
+ CPPUNIT_TEST(testRsaWrapUnwrap);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaWrapUnwrap();
+
+protected:
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void rsaWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey);
+};
+
+#endif // !_SOFTHSM_V2_ASYMWRAPUNWRAPTESTS_H
diff --git a/SoftHSMv2/src/lib/test/DeriveTests.cpp b/SoftHSMv2/src/lib/test/DeriveTests.cpp
new file mode 100644
index 0000000..588d0b9
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DeriveTests.cpp
@@ -0,0 +1,737 @@
+/*
+ * Copyright (c) 2014 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DeriveTests.cpp
+
+ Contains test cases for:
+ C_DeriveKey
+
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "DeriveTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DeriveTests);
+
+CK_RV DeriveTests::generateDhKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BYTE bn1024[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
+ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
+ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
+ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22,
+ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
+ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b,
+ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
+ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
+ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
+ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b,
+ 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
+ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5,
+ 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6,
+ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe6, 0x53, 0x81,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+ CK_BYTE bn2[] = { 2 };
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_PRIME, &bn1024, sizeof(bn1024) },
+ { CKA_BASE, &bn2, sizeof(bn2) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+#ifdef WITH_ECC
+CK_RV DeriveTests::generateEcKeyPair(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_KEY_TYPE keyType = CKK_EC;
+ CK_BYTE oidP256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
+ CK_BYTE oidP384[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 };
+ CK_BYTE oidP521[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 };
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ /* Select the curve */
+ if (strcmp(curve, "P-256") == 0)
+ {
+ pukAttribs[0].pValue = oidP256;
+ pukAttribs[0].ulValueLen = sizeof(oidP256);
+ }
+ else if (strcmp(curve, "P-384") == 0)
+ {
+ pukAttribs[0].pValue = oidP384;
+ pukAttribs[0].ulValueLen = sizeof(oidP384);
+ }
+ else if (strcmp(curve, "P-521") == 0)
+ {
+ pukAttribs[0].pValue = oidP521;
+ pukAttribs[0].ulValueLen = sizeof(oidP521);
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+#endif
+
+CK_RV DeriveTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+#ifndef WITH_FIPS
+CK_RV DeriveTests::generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+#endif
+
+CK_RV DeriveTests::generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES2_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV DeriveTests::generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DERIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+void DeriveTests::dhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey)
+{
+ CK_ATTRIBUTE valAttrib = { CKA_VALUE, NULL_PTR, 0 };
+ CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ valAttrib.pValue = (CK_BYTE_PTR)malloc(valAttrib.ulValueLen);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_MECHANISM mechanism = { CKM_DH_PKCS_DERIVE, NULL_PTR, 0 };
+ mechanism.pParameter = valAttrib.pValue;
+ mechanism.ulParameterLen = valAttrib.ulValueLen;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ULONG secLen = 32;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &secLen, sizeof(secLen) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hPrivateKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ free(valAttrib.pValue);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+#ifdef WITH_ECC
+void DeriveTests::ecdhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey, bool useRaw)
+{
+ CK_ATTRIBUTE valAttrib = { CKA_EC_POINT, NULL_PTR, 0 };
+ CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ valAttrib.pValue = (CK_BYTE_PTR)malloc(valAttrib.ulValueLen);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPublicKey, &valAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ECDH1_DERIVE_PARAMS parms = { CKD_NULL, 0, NULL_PTR, 0, NULL_PTR };
+ // Use RAW or DER format
+ if (useRaw)
+ {
+ size_t offset = 0;
+ unsigned char* buf = (unsigned char*)valAttrib.pValue;
+ if (valAttrib.ulValueLen > 2 && buf[0] == 0x04)
+ {
+ if (buf[1] < 0x80)
+ {
+ offset = 2;
+ }
+ else
+ {
+ if (valAttrib.ulValueLen > ((buf[1] & 0x7F) + (unsigned int)2))
+ {
+ offset = 2 + (buf[1] & 0x7F);
+ }
+ }
+ }
+ parms.pPublicData = buf + offset;
+ parms.ulPublicDataLen = valAttrib.ulValueLen - offset;
+ }
+ else
+ {
+ parms.pPublicData = (unsigned char*)valAttrib.pValue;
+ parms.ulPublicDataLen = valAttrib.ulValueLen;
+ }
+
+ CK_MECHANISM mechanism = { CKM_ECDH1_DERIVE, NULL, 0 };
+ mechanism.pParameter = &parms;
+ mechanism.ulParameterLen = sizeof(parms);
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ULONG secLen = 32;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &secLen, sizeof(secLen) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hPrivateKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ free(valAttrib.pValue);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+#endif
+
+bool DeriveTests::compareSecret(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey1, CK_OBJECT_HANDLE hKey2)
+{
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_VALUE, NULL_PTR, 0 },
+ { CKA_CHECK_VALUE, NULL_PTR, 0 }
+ };
+ CK_BYTE val1[128];
+ CK_BYTE check1[3];
+ keyAttribs[0].pValue = val1;
+ keyAttribs[0].ulValueLen = sizeof(val1);
+ keyAttribs[1].pValue = check1;
+ keyAttribs[1].ulValueLen = sizeof(check1);
+ CK_RV rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey1, keyAttribs, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(keyAttribs[0].ulValueLen == 32);
+ CPPUNIT_ASSERT(keyAttribs[1].ulValueLen == 3);
+ CK_BYTE val2[128];
+ CK_BYTE check2[3];
+ keyAttribs[0].pValue = val2;
+ keyAttribs[0].ulValueLen = sizeof(val2);
+ keyAttribs[1].pValue = check2;
+ keyAttribs[1].ulValueLen = sizeof(check2);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey2, keyAttribs, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(keyAttribs[0].ulValueLen == 32);
+ CPPUNIT_ASSERT(keyAttribs[1].ulValueLen == 3);
+ return memcmp(val1, val2, 32) == 0 &&
+ memcmp(check1, check2, 3) == 0;
+}
+
+void DeriveTests::testDhDerive()
+{
+ 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);
+
+ // Public Session keys
+ CK_OBJECT_HANDLE hPuk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPuk2 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk2 = CK_INVALID_HANDLE;
+
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hKey1 = CK_INVALID_HANDLE;
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ CK_OBJECT_HANDLE hKey2 = CK_INVALID_HANDLE;
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Session Keys
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Public Token Keys
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Token Keys
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDhKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ dhDerive(hSessionRW,hPuk1,hPrk2,hKey1);
+ dhDerive(hSessionRW,hPuk2,hPrk1,hKey2);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+}
+
+#ifdef WITH_ECC
+void DeriveTests::testEcdhDerive()
+{
+ 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);
+
+ // Public Session keys
+ CK_OBJECT_HANDLE hPuk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk1 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPuk2 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk2 = CK_INVALID_HANDLE;
+
+ rv = generateEcKeyPair("P-256",hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-256",hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hKey1 = CK_INVALID_HANDLE;
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ CK_OBJECT_HANDLE hKey2 = CK_INVALID_HANDLE;
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Session Keys
+ rv = generateEcKeyPair("P-384",hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-384",hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Public Token Keys
+ rv = generateEcKeyPair("P-521",hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-521",hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+
+ // Private Token Keys
+ rv = generateEcKeyPair("P-256",hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk1,hPrk1);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateEcKeyPair("P-256",hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk2,hPrk2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ ecdhDerive(hSessionRW,hPuk1,hPrk2,hKey1,true);
+ ecdhDerive(hSessionRW,hPuk2,hPrk1,hKey2,false);
+ CPPUNIT_ASSERT(compareSecret(hSessionRW,hKey1,hKey2));
+}
+#endif
+
+void DeriveTests::symDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE &hDerive, CK_MECHANISM_TYPE mechType, CK_KEY_TYPE keyType)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechType, NULL_PTR, 0 };
+ CK_MECHANISM mechEncrypt = { CKM_VENDOR_DEFINED, NULL_PTR, 0 };
+ CK_KEY_DERIVATION_STRING_DATA param1;
+ CK_DES_CBC_ENCRYPT_DATA_PARAMS param2;
+ CK_AES_CBC_ENCRYPT_DATA_PARAMS param3;
+
+ CK_BYTE data[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32
+ };
+ CK_ULONG secLen = 0;
+
+ switch (mechType)
+ {
+ case CKM_DES_ECB_ENCRYPT_DATA:
+ case CKM_DES3_ECB_ENCRYPT_DATA:
+ case CKM_AES_ECB_ENCRYPT_DATA:
+ param1.pData = &data[0];
+ param1.ulLen = sizeof(data);
+ mechanism.pParameter = &param1;
+ mechanism.ulParameterLen = sizeof(param1);
+ break;
+ case CKM_DES_CBC_ENCRYPT_DATA:
+ case CKM_DES3_CBC_ENCRYPT_DATA:
+ memcpy(param2.iv, "12345678", 8);
+ param2.pData = &data[0];
+ param2.length = sizeof(data);
+ mechanism.pParameter = &param2;
+ mechanism.ulParameterLen = sizeof(param2);
+ break;
+ case CKM_AES_CBC_ENCRYPT_DATA:
+ memcpy(param3.iv, "1234567890ABCDEF", 16);
+ param3.pData = &data[0];
+ param3.length = sizeof(data);
+ mechanism.pParameter = &param3;
+ mechanism.ulParameterLen = sizeof(param3);
+ break;
+ default:
+ CPPUNIT_FAIL("Invalid mechanism");
+ }
+
+ switch (keyType)
+ {
+ case CKK_GENERIC_SECRET:
+ secLen = 32;
+ break;
+ case CKK_DES:
+ mechEncrypt.mechanism = CKM_DES_ECB;
+ break;
+ case CKK_DES2:
+ case CKK_DES3:
+ mechEncrypt.mechanism = CKM_DES3_ECB;
+ break;
+ case CKK_AES:
+ mechEncrypt.mechanism = CKM_AES_ECB;
+ secLen = 32;
+ break;
+ default:
+ CPPUNIT_FAIL("Invalid key type");
+ }
+
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &secLen, sizeof(secLen) }
+ };
+
+ hDerive = CK_INVALID_HANDLE;
+ if (secLen > 0)
+ {
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hDerive) );
+ }
+ else
+ {
+ rv = CRYPTOKI_F_PTR( C_DeriveKey(hSession, &mechanism, hKey,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE) - 1,
+ &hDerive) );
+ }
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check that KCV has been set
+ CK_ATTRIBUTE checkAttribs[] = {
+ { CKA_CHECK_VALUE, NULL_PTR, 0 }
+ };
+ CK_BYTE check[3];
+ checkAttribs[0].pValue = check;
+ checkAttribs[0].ulValueLen = sizeof(check);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hDerive, checkAttribs, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(checkAttribs[0].ulValueLen == 3);
+
+ if (keyType == CKK_GENERIC_SECRET) return;
+
+ CK_BYTE cipherText[300];
+ CK_ULONG ulCipherTextLen;
+ CK_BYTE recoveredText[300];
+ CK_ULONG ulRecoveredTextLen;
+
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechEncrypt,hDerive) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulCipherTextLen = sizeof(cipherText);
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,data,sizeof(data),cipherText,&ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechEncrypt,hDerive) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulRecoveredTextLen = sizeof(recoveredText);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(ulRecoveredTextLen==sizeof(data));
+
+ CPPUNIT_ASSERT(memcmp(data, recoveredText, sizeof(data)) == 0);
+}
+
+void DeriveTests::testSymDerive()
+{
+ 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 private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Generate base key
+#ifndef WITH_FIPS
+ CK_OBJECT_HANDLE hKeyDes = CK_INVALID_HANDLE;
+#endif
+ CK_OBJECT_HANDLE hKeyDes2 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hKeyDes3 = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hKeyAes = CK_INVALID_HANDLE;
+#ifndef WITH_FIPS
+ rv = generateDesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyDes);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+#endif
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyDes2);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyDes3);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKeyAes);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Derive keys
+ CK_OBJECT_HANDLE hDerive = CK_INVALID_HANDLE;
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_DES);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_ECB_ENCRYPT_DATA,CKK_AES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_ECB_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_ECB_ENCRYPT_DATA,CKK_AES);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_DES);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes,hDerive,CKM_DES_CBC_ENCRYPT_DATA,CKK_AES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes2,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyDes3,hDerive,CKM_DES3_CBC_ENCRYPT_DATA,CKK_AES);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_GENERIC_SECRET);
+#ifndef WITH_FIPS
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_DES);
+#endif
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_DES2);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_DES3);
+ symDerive(hSessionRW,hKeyAes,hDerive,CKM_AES_CBC_ENCRYPT_DATA,CKK_AES);
+}
+
diff --git a/SoftHSMv2/src/lib/test/DeriveTests.h b/SoftHSMv2/src/lib/test/DeriveTests.h
new file mode 100644
index 0000000..5b2aef5
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DeriveTests.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DeriveTests.h
+
+ Contains test cases to C_DeriveKey
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DERIVETESTS_H
+#define _SOFTHSM_V2_DERIVETESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class DeriveTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(DeriveTests);
+ CPPUNIT_TEST(testDhDerive);
+#ifdef WITH_ECC
+ CPPUNIT_TEST(testEcdhDerive);
+#endif
+ CPPUNIT_TEST(testSymDerive);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDhDerive();
+#ifdef WITH_ECC
+ void testEcdhDerive();
+#endif
+ void testSymDerive();
+
+protected:
+ CK_RV generateDhKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#ifndef WITH_FIPS
+ CK_RV generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#endif
+ CK_RV generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ void dhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey);
+#ifdef WITH_ECC
+ CK_RV generateEcKeyPair(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+ void ecdhDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_OBJECT_HANDLE &hKey, bool useRaw);
+#endif
+ bool compareSecret(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey1, CK_OBJECT_HANDLE hKey2);
+ void symDerive(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE &hDerive, CK_MECHANISM_TYPE mechType, CK_KEY_TYPE keyType);
+};
+
+#endif // !_SOFTHSM_V2_DERIVETESTS_H
diff --git a/SoftHSMv2/src/lib/test/DigestTests.cpp b/SoftHSMv2/src/lib/test/DigestTests.cpp
new file mode 100644
index 0000000..b5e7e7e
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DigestTests.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DigestTests.cpp
+
+ Contains test cases to C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "DigestTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DigestTests);
+
+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);
+}
+
+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 DigestTests::testDigestUpdate()
+{
+ 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_DigestUpdate(hSession, data, sizeof(data)-1) );
+ 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_DigestUpdate(CK_INVALID_HANDLE, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) );
+ 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_DigestUpdate(hSession, NULL_PTR, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+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 DigestTests::testDigestFinal()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mechanism = {
+ CKM_SHA512, NULL_PTR, 0
+ };
+ CK_BYTE data[] = {"Text to digest"};
+ CK_ULONG digestLen;
+ CK_BYTE_PTR digest;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, 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_DigestFinal(CK_INVALID_HANDLE, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, 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_DigestUpdate(hSession, data, sizeof(data)-1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ digest = (CK_BYTE_PTR)malloc(digestLen);
+ digestLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, digest, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(digest);
+
+ rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+}
+
+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);
+ }
+}
diff --git a/SoftHSMv2/src/lib/test/DigestTests.h b/SoftHSMv2/src/lib/test/DigestTests.h
new file mode 100644
index 0000000..e724a39
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/DigestTests.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DigestTests.h
+
+ Contains test cases to C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DIGESTTESTS_H
+#define _SOFTHSM_V2_DIGESTTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class DigestTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(DigestTests);
+ CPPUNIT_TEST(testDigestInit);
+ CPPUNIT_TEST(testDigest);
+ CPPUNIT_TEST(testDigestUpdate);
+ CPPUNIT_TEST(testDigestKey);
+ CPPUNIT_TEST(testDigestFinal);
+ CPPUNIT_TEST(testDigestAll);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testDigestInit();
+ void testDigest();
+ void testDigestUpdate();
+ void testDigestKey();
+ void testDigestFinal();
+ void testDigestAll();
+};
+
+#endif // !_SOFTHSM_V2_DIGESTTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/InfoTests.cpp b/SoftHSMv2/src/lib/test/InfoTests.cpp
new file mode 100644
index 0000000..958d96e
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InfoTests.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InfoTests.cpp
+
+ Contains test cases to C_GetInfo, C_GetFunctionList, C_GetSlotList,
+ C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, and C_GetMechanismInfo
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "InfoTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InfoTests);
+
+void InfoTests::testGetInfo()
+{
+ CK_RV rv;
+ CK_INFO ckInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetInfo(&ckInfo) );
+ 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_GetInfo(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetInfo(&ckInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetFunctionList()
+{
+ CK_RV rv;
+ CK_FUNCTION_LIST_PTR ckFuncList;
+
+ rv = CRYPTOKI_F_PTR( C_GetFunctionList(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetFunctionList(&ckFuncList) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+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
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount) );
+ 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_GetSlotList(CK_FALSE, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Get the size of the buffer
+ rv = CRYPTOKI_F_PTR( 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 = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the slot list
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pSlotList);
+
+ // Get the number of slots with tokens
+ rv = CRYPTOKI_F_PTR( 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 = CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the slot list
+ rv = CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, pSlotList, &ulSlotCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pSlotList);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetSlotInfo()
+{
+ CK_RV rv;
+ CK_SLOT_INFO slotInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ 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_GetSlotInfo(m_notInitializedTokenSlotID, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_invalidSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT ) == CKF_TOKEN_PRESENT);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_REMOVABLE_DEVICE ) == 0);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InfoTests::testGetSlotInfoAlt()
+{
+ CK_RV rv;
+ CK_SLOT_INFO slotInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2-alt.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2-alt.conf", 1);
+#endif
+
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // (Re)initialize the token
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ 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_GetSlotInfo(m_notInitializedTokenSlotID, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_invalidSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSlotInfo(m_notInitializedTokenSlotID, &slotInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_TOKEN_PRESENT ) == CKF_TOKEN_PRESENT);
+ CPPUNIT_ASSERT((slotInfo.flags & CKF_REMOVABLE_DEVICE ) == CKF_REMOVABLE_DEVICE);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2.conf", 1);
+#endif
+}
+
+
+void InfoTests::testGetTokenInfo()
+{
+ CK_RV rv;
+ CK_TOKEN_INFO tokenInfo;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_notInitializedTokenSlotID, &tokenInfo) );
+ 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_GetTokenInfo(m_notInitializedTokenSlotID, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_invalidSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_notInitializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0);
+
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_initializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+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
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, NULL_PTR, &ulMechCount) );
+ 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_GetMechanismList(m_initializedTokenSlotID, NULL_PTR, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_invalidSlotID, NULL_PTR, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ // Get the size of the buffer
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, 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 = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, pMechanismList, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ // Get the mechanism list
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, pMechanismList, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ free(pMechanismList);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+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
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, CKM_RSA_PKCS, &info) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get the mechanism list
+ rv = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, 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 = CRYPTOKI_F_PTR( C_GetMechanismList(m_initializedTokenSlotID, pMechanismList, &ulMechCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, pMechanismList[0], NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_invalidSlotID, pMechanismList[0], &info) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, CKM_VENDOR_DEFINED, &info) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ for (unsigned int i = 0; i < ulMechCount; i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_GetMechanismInfo(m_initializedTokenSlotID, pMechanismList[i], &info) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ }
+
+ free(pMechanismList);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
diff --git a/SoftHSMv2/src/lib/test/InfoTests.h b/SoftHSMv2/src/lib/test/InfoTests.h
new file mode 100644
index 0000000..4acf770
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InfoTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InfoTests.h
+
+ Contains test cases to C_GetInfo, C_GetFunctionList, C_GetSlotList,
+ C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, and C_GetMechanismInfo
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_INFOTESTS_H
+#define _SOFTHSM_V2_INFOTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class InfoTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(InfoTests);
+ CPPUNIT_TEST(testGetInfo);
+ CPPUNIT_TEST(testGetFunctionList);
+ CPPUNIT_TEST(testGetSlotList);
+ CPPUNIT_TEST(testGetSlotInfo);
+ CPPUNIT_TEST(testGetTokenInfo);
+ CPPUNIT_TEST(testGetMechanismList);
+ CPPUNIT_TEST(testGetMechanismInfo);
+ CPPUNIT_TEST(testGetSlotInfoAlt);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testGetInfo();
+ void testGetFunctionList();
+ void testGetSlotList();
+ void testGetSlotInfo();
+ void testGetTokenInfo();
+ void testGetMechanismList();
+ void testGetMechanismInfo();
+ void testGetSlotInfoAlt();
+};
+
+#endif // !_SOFTHSM_V2_INFOTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/InitTests.cpp b/SoftHSMv2/src/lib/test/InitTests.cpp
new file mode 100644
index 0000000..71611f8
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InitTests.cpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InitTests.cpp
+
+ Contains test cases to C_Initialize and C_Finalize
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include "InitTests.h"
+#include "cryptoki.h"
+#include "osmutex.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InitTests);
+
+void InitTests::setUp()
+{
+// printf("\nInitTests\n");
+
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2.conf", 1);
+#endif
+}
+
+void InitTests::tearDown()
+{
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
+
+void InitTests::testInit1()
+{
+ CK_RV rv;
+
+ // Just make sure that we finalize any previous failed 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_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit2()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+#ifdef CreateMutex
+#undef CreateMutex
+#endif
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = (CK_VOID_PTR)1;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.pReserved = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit3()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = (CK_UNLOCKMUTEX)1;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit4()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = NULL_PTR;
+ InitArgs.DestroyMutex = NULL_PTR;
+ InitArgs.LockMutex = NULL_PTR;
+ InitArgs.UnlockMutex = (CK_UNLOCKMUTEX)1;
+ InitArgs.flags = CKF_OS_LOCKING_OK;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit5()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = OSCreateMutex;
+ InitArgs.DestroyMutex = OSDestroyMutex;
+ InitArgs.LockMutex = OSLockMutex;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = 0;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = OSUnlockMutex;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testInit6()
+{
+ CK_C_INITIALIZE_ARGS InitArgs;
+ CK_RV rv;
+
+ InitArgs.CreateMutex = OSCreateMutex;
+ InitArgs.DestroyMutex = OSDestroyMutex;
+ InitArgs.LockMutex = OSLockMutex;
+ InitArgs.UnlockMutex = NULL_PTR;
+ InitArgs.flags = CKF_OS_LOCKING_OK;
+ InitArgs.pReserved = NULL_PTR;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ InitArgs.UnlockMutex = OSUnlockMutex;
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ // If rv == CKR_CANT_LOCK then we cannot use multiple threads
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize((CK_VOID_PTR)&InitArgs) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void InitTests::testFinal()
+{
+ CK_RV rv;
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // pReserved is reserved for future versions
+ rv = CRYPTOKI_F_PTR( C_Finalize((CK_VOID_PTR)1) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/test/InitTests.h b/SoftHSMv2/src/lib/test/InitTests.h
new file mode 100644
index 0000000..ba22ec0
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/InitTests.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ InitTests.h
+
+ Contains test cases to C_Initialize and C_Finalize
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_INITTESTS_H
+#define _SOFTHSM_V2_INITTESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "TestsNoPINInitBase.h"
+
+class InitTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(InitTests);
+ CPPUNIT_TEST(testInit1);
+ CPPUNIT_TEST(testInit2);
+ CPPUNIT_TEST(testInit3);
+ CPPUNIT_TEST(testInit4);
+ CPPUNIT_TEST(testInit5);
+ CPPUNIT_TEST(testInit6);
+ CPPUNIT_TEST(testFinal);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInit1();
+ void testInit2();
+ void testInit3();
+ void testInit4();
+ void testInit5();
+ void testInit6();
+ void testFinal();
+
+ virtual void setUp();
+ virtual void tearDown();
+};
+
+#endif // !_SOFTHSM_V2_INITTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/Makefile.am b/SoftHSMv2/src/lib/test/Makefile.am
new file mode 100644
index 0000000..4345878
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/Makefile.am
@@ -0,0 +1,40 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/.. \
+ -I$(srcdir)/../common \
+ -I$(srcdir)/../pkcs11 \
+ @CPPUNIT_CFLAGS@
+
+check_PROGRAMS = p11test
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+p11test_SOURCES = p11test.cpp \
+ SymmetricAlgorithmTests.cpp \
+ DigestTests.cpp \
+ InitTests.cpp \
+ InfoTests.cpp \
+ RandomTests.cpp \
+ SessionTests.cpp \
+ TokenTests.cpp \
+ UserTests.cpp \
+ ObjectTests.cpp \
+ DeriveTests.cpp \
+ SignVerifyTests.cpp \
+ AsymEncryptDecryptTests.cpp \
+ AsymWrapUnwrapTests.cpp \
+ TestsBase.cpp \
+ TestsNoPINInitBase.cpp \
+ ../common/log.cpp \
+ ../common/osmutex.cpp
+
+p11test_LDADD = ../libsofthsm2.la
+
+p11test_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install -pthread -static
+
+TESTS = p11test
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/softhsm2-alt.conf.win32 \
+ $(srcdir)/softhsm2.conf.win32 \
+ $(srcdir)/tokens/dummy.in
diff --git a/SoftHSMv2/src/lib/test/ObjectTests.cpp b/SoftHSMv2/src/lib/test/ObjectTests.cpp
new file mode 100644
index 0000000..cd6c676
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/ObjectTests.cpp
@@ -0,0 +1,2393 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectTests.cpp
+
+ Contains test cases for:
+ C_CreateObject
+ C_CopyObject
+ C_DestroyObject
+ C_GetAttributeValue
+ C_SetAttributeValue
+ C_FindObjectsInit
+ C_FindObjects
+ C_FindObjectsFinal
+ C_GenererateKeyPair
+
+ Below is a list of tests we need to add in order to verify that the PKCS#11 library
+ is working as expected.
+
+ We want to be sure that order of attributes does not impact the tests, therefore
+ every function involving attributes should have the order of the attributes
+ in the template randomized.
+
+ We want to be sure that only attributes that are specified as being part of an
+ object class can be used when creating an object.
+ Using other attributes should return an error on creation of the object.
+
+ We want to be sure that attributes that are required but missing will result
+ in a template incomplete return value.
+
+ We want to be sure that we get an error when trying to modify an attribute that
+ may not be modified
+
+ We want to be sure that attributes that may be changed to one value but not
+ back to the previous value are handled correctly.
+
+ We want to verify that an error is returned when we are trying to modify
+ read-only attributes.
+
+ We want to verify that sensitive attributes cannot be read.
+
+ Because the teardown also removes token objects it is not really
+ required to destroy objects created during the test in the CreateObject tests.
+
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ObjectTests.h"
+
+// Common object attributes
+const CK_BBOOL CKA_TOKEN_DEFAULT = CK_FALSE;
+//const CK_BBOOL CKA_PRIVATE_DEFAULT = <token/object attribute dependent>
+const CK_BBOOL CKA_MODIFIABLE_DEFAULT = CK_TRUE;
+const CK_UTF8CHAR_PTR CKA_LABEL_DEFAULT = NULL;
+const CK_BBOOL CKA_COPYABLE_DEFAULT = CK_TRUE;
+const CK_BBOOL CKA_DESTROYABLE_DEFAULT = CK_TRUE;
+
+// Data Object Attributes
+const CK_UTF8CHAR_PTR CKA_APPLICATION_DEFAULT = NULL;
+const CK_BYTE_PTR CKA_OBJECT_ID_DEFAULT = NULL;
+const CK_BYTE_PTR CKA_VALUE_DEFAULT = NULL;
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ObjectTests);
+
+void ObjectTests::checkCommonObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_OBJECT_CLASS objClass)
+{
+ CK_RV rv;
+
+ CK_OBJECT_CLASS obj_class = CKO_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &obj_class, sizeof(obj_class) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(obj_class == objClass);
+}
+
+void ObjectTests::checkCommonStorageObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BBOOL bToken, CK_BBOOL /*bPrivate*/, CK_BBOOL bModifiable, CK_UTF8CHAR_PTR pLabel, CK_ULONG ulLabelLen, CK_BBOOL bCopyable, CK_BBOOL bDestroyable)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_token = CK_FALSE;
+ CK_BBOOL obj_private = CK_FALSE;
+ CK_BBOOL obj_modifiable = CK_FALSE;
+ CK_BBOOL obj_copyable = CK_FALSE;
+ CK_BBOOL obj_destroyable = CK_FALSE;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, NULL_PTR, 0 },
+ { CKA_TOKEN, &obj_token, sizeof(obj_token) },
+ { CKA_PRIVATE, &obj_private, sizeof(obj_private) },
+ { CKA_MODIFIABLE, &obj_modifiable, sizeof(obj_modifiable) },
+ { CKA_COPYABLE, &obj_copyable, sizeof(obj_copyable) },
+ { CKA_DESTROYABLE, &obj_destroyable, sizeof(obj_destroyable) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 6) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulLabelLen);
+ CPPUNIT_ASSERT(obj_token == bToken);
+ /* Default is token-specifict
+ CPPUNIT_ASSERT(obj_private == bPrivate); */
+ CPPUNIT_ASSERT(obj_modifiable == bModifiable);
+ CPPUNIT_ASSERT(obj_copyable == bCopyable);
+ CPPUNIT_ASSERT(obj_destroyable == bDestroyable);
+ if (ulLabelLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pLabel, ulLabelLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkDataObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_UTF8CHAR_PTR pApplication, CK_ULONG ulApplicationLen, CK_BYTE_PTR pObjectID, CK_ULONG ulObjectIdLen, CK_BYTE_PTR pValue, CK_ULONG ulValueLen)
+{
+ CK_RV rv;
+
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_APPLICATION, NULL_PTR, 0 },
+ { CKA_OBJECT_ID, NULL_PTR, 0 },
+ { CKA_VALUE, NULL_PTR, 0 }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+ attribs[2].pValue = (CK_VOID_PTR)malloc(attribs[2].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulApplicationLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulObjectIdLen);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulValueLen);
+ if (ulApplicationLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pApplication, ulApplicationLen) == 0);
+ if (ulObjectIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pObjectID, ulObjectIdLen) == 0);
+ if (ulValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, pValue, ulValueLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+ free(attribs[2].pValue);
+}
+
+void ObjectTests::checkCommonCertificateObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_CERTIFICATE_TYPE certType, CK_BBOOL bTrusted, CK_ULONG ulCertificateCategory, CK_BYTE_PTR pCheckValue, CK_ULONG ulCheckValueLen, CK_DATE startDate, CK_ULONG ulStartDateLen, CK_DATE endDate, CK_ULONG ulEndDateLen)
+{
+ CK_RV rv;
+
+ CK_CERTIFICATE_TYPE obj_type = CKC_X_509;
+ CK_BBOOL obj_trusted = CK_FALSE;
+ CK_ULONG obj_category = 0;
+ CK_DATE obj_start;
+ CK_DATE obj_end;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CHECK_VALUE, NULL_PTR, 0 },
+ { CKA_CERTIFICATE_TYPE, &obj_type, sizeof(obj_type) },
+ { CKA_TRUSTED, &obj_trusted, sizeof(obj_trusted) },
+ { CKA_CERTIFICATE_CATEGORY, &obj_category, sizeof(obj_category) },
+ { CKA_START_DATE, &obj_start, sizeof(obj_start) },
+ { CKA_END_DATE, &obj_end, sizeof(obj_end) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 6) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulCheckValueLen);
+ CPPUNIT_ASSERT(obj_type == certType);
+ CPPUNIT_ASSERT(obj_trusted == bTrusted);
+ CPPUNIT_ASSERT(obj_category == ulCertificateCategory);
+ CPPUNIT_ASSERT(attribs[4].ulValueLen == ulStartDateLen);
+ CPPUNIT_ASSERT(attribs[5].ulValueLen == ulEndDateLen);
+ if (ulCheckValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pCheckValue, ulCheckValueLen) == 0);
+ if (ulStartDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, &startDate, ulStartDateLen) == 0);
+ if (ulEndDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[5].pValue, &endDate, ulEndDateLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkX509CertificateObjectAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BYTE_PTR pId, CK_ULONG ulIdLen, CK_BYTE_PTR pIssuer, CK_ULONG ulIssuerLen, CK_BYTE_PTR pSerialNumber, CK_ULONG ulSerialNumberLen, CK_BYTE_PTR pValue, CK_ULONG ulValueLen, CK_BYTE_PTR pUrl, CK_ULONG ulUrlLen, CK_BYTE_PTR pHashOfSubjectPublicKey, CK_ULONG ulHashOfSubjectPublicKeyLen, CK_BYTE_PTR pHashOfIssuerPublicKey, CK_ULONG ulHashOfIssuerPublicKeyLen, CK_ULONG ulJavaMidpSecurityDomain, CK_MECHANISM_TYPE nameHashAlgorithm)
+{
+ CK_RV rv;
+
+ CK_ULONG obj_java = 0;
+ CK_MECHANISM_TYPE obj_mech = CKM_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_ID, NULL_PTR, 0 },
+ { CKA_ISSUER, NULL_PTR, 0 },
+ { CKA_SERIAL_NUMBER, NULL_PTR, 0 },
+ { CKA_VALUE, NULL_PTR, 0 },
+ { CKA_URL, NULL_PTR, 0 },
+ { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, NULL_PTR, 0 },
+ { CKA_HASH_OF_ISSUER_PUBLIC_KEY, NULL_PTR, 0 },
+ { CKA_JAVA_MIDP_SECURITY_DOMAIN, &obj_java, sizeof(obj_java) },
+ { CKA_NAME_HASH_ALGORITHM, &obj_mech, sizeof(obj_mech) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 8) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+ attribs[2].pValue = (CK_VOID_PTR)malloc(attribs[2].ulValueLen);
+ attribs[3].pValue = (CK_VOID_PTR)malloc(attribs[3].ulValueLen);
+ attribs[4].pValue = (CK_VOID_PTR)malloc(attribs[4].ulValueLen);
+ attribs[5].pValue = (CK_VOID_PTR)malloc(attribs[5].ulValueLen);
+ attribs[6].pValue = (CK_VOID_PTR)malloc(attribs[6].ulValueLen);
+ attribs[7].pValue = (CK_VOID_PTR)malloc(attribs[7].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 10) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulIdLen);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulIssuerLen);
+ CPPUNIT_ASSERT(attribs[3].ulValueLen == ulSerialNumberLen);
+ CPPUNIT_ASSERT(attribs[4].ulValueLen == ulValueLen);
+ CPPUNIT_ASSERT(attribs[5].ulValueLen == ulUrlLen);
+ CPPUNIT_ASSERT(attribs[6].ulValueLen == ulHashOfSubjectPublicKeyLen);
+ CPPUNIT_ASSERT(attribs[7].ulValueLen == ulHashOfIssuerPublicKeyLen);
+ CPPUNIT_ASSERT(obj_java == ulJavaMidpSecurityDomain);
+ CPPUNIT_ASSERT(obj_mech == nameHashAlgorithm);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+ if (ulIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pId, ulIdLen) == 0);
+ if (ulIssuerLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, pIssuer, ulIssuerLen) == 0);
+ if (ulSerialNumberLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[3].pValue, pSerialNumber, ulSerialNumberLen) == 0);
+ if (ulValueLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[4].pValue, pValue, ulValueLen) == 0);
+ if (ulUrlLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[5].pValue, pUrl, ulUrlLen) == 0);
+ if (ulHashOfSubjectPublicKeyLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[6].pValue, pHashOfSubjectPublicKey, ulHashOfSubjectPublicKeyLen) == 0);
+ if (ulHashOfIssuerPublicKeyLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[7].pValue, pHashOfIssuerPublicKey, ulHashOfIssuerPublicKeyLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+ free(attribs[2].pValue);
+ free(attribs[3].pValue);
+ free(attribs[4].pValue);
+ free(attribs[5].pValue);
+ free(attribs[6].pValue);
+ free(attribs[7].pValue);
+}
+
+void ObjectTests::checkCommonKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_KEY_TYPE keyType, CK_BYTE_PTR pId, CK_ULONG ulIdLen, CK_DATE startDate, CK_ULONG ulStartDateLen, CK_DATE endDate, CK_ULONG ulEndDateLen, CK_BBOOL bDerive, CK_BBOOL bLocal, CK_MECHANISM_TYPE keyMechanismType, CK_MECHANISM_TYPE_PTR pAllowedMechanisms, CK_ULONG ulAllowedMechanismsLen)
+{
+ CK_RV rv;
+
+ CK_KEY_TYPE obj_type = CKK_VENDOR_DEFINED;
+ CK_DATE obj_start;
+ CK_DATE obj_end;
+ CK_BBOOL obj_derive = CK_FALSE;
+ CK_BBOOL obj_local = CK_FALSE;
+ CK_MECHANISM_TYPE obj_mech = CKM_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_ID, NULL_PTR, 0 },
+ { CKA_KEY_TYPE, &obj_type, sizeof(obj_type) },
+ { CKA_START_DATE, &obj_start, sizeof(obj_start) },
+ { CKA_END_DATE, &obj_end, sizeof(obj_end) },
+ { CKA_DERIVE, &obj_derive, sizeof(obj_derive) },
+ { CKA_LOCAL, &obj_local, sizeof(obj_local) },
+ { CKA_KEY_GEN_MECHANISM, &obj_mech, sizeof(obj_mech) },
+ { CKA_ALLOWED_MECHANISMS, NULL_PTR, 0 }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 8) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulIdLen);
+ CPPUNIT_ASSERT(obj_type == keyType);
+ CPPUNIT_ASSERT(attribs[2].ulValueLen == ulStartDateLen);
+ CPPUNIT_ASSERT(attribs[3].ulValueLen == ulEndDateLen);
+ CPPUNIT_ASSERT(obj_derive == bDerive);
+ CPPUNIT_ASSERT(obj_local == bLocal);
+ CPPUNIT_ASSERT(obj_mech == keyMechanismType);
+ CPPUNIT_ASSERT(attribs[7].ulValueLen == ulAllowedMechanismsLen);
+
+ if (ulIdLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pId, ulIdLen) == 0);
+ if (ulStartDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[2].pValue, &startDate, ulStartDateLen) == 0);
+ if (ulEndDateLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[3].pValue, &endDate, ulEndDateLen) == 0);
+ if (ulAllowedMechanismsLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[7].pValue, pAllowedMechanisms, ulAllowedMechanismsLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonPublicKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BBOOL /*bEncrypt*/, CK_BBOOL /*bVerify*/, CK_BBOOL /*bVerifyRecover*/, CK_BBOOL /*bWrap*/, CK_BBOOL bTrusted, CK_ATTRIBUTE_PTR pWrapTemplate, CK_ULONG ulWrapTemplateLen)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_encrypt = CK_FALSE;
+ CK_BBOOL obj_verify = CK_FALSE;
+ CK_BBOOL obj_verify_recover = CK_FALSE;
+ CK_BBOOL obj_wrap = CK_FALSE;
+ CK_BBOOL obj_trusted = CK_FALSE;
+ CK_LONG len_wrap_template = ulWrapTemplateLen;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_ENCRYPT, &obj_encrypt, sizeof(obj_encrypt) },
+ { CKA_VERIFY, &obj_verify, sizeof(obj_verify) },
+ { CKA_VERIFY_RECOVER, &obj_verify_recover, sizeof(obj_verify_recover) },
+ { CKA_WRAP, &obj_wrap, sizeof(obj_wrap) },
+ { CKA_TRUSTED, &obj_trusted, sizeof(obj_trusted) },
+ { CKA_WRAP_TEMPLATE, pWrapTemplate, ulWrapTemplateLen }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 7) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ /* Default is token-specifict
+ CPPUNIT_ASSERT(obj_encrypt == bEncrypt);
+ CPPUNIT_ASSERT(obj_verify == bVerify);
+ CPPUNIT_ASSERT(obj_verify_recover == bVerifyRecover);
+ CPPUNIT_ASSERT(obj_wrap == bWrap); */
+ CPPUNIT_ASSERT(obj_trusted == bTrusted);
+ len_wrap_template = attribs[6].ulValueLen;
+ CPPUNIT_ASSERT(len_wrap_template == 0);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonPrivateKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen, CK_BBOOL bSensitive, CK_BBOOL bDecrypt, CK_BBOOL bSign, CK_BBOOL bSignRecover, CK_BBOOL bUnwrap, CK_BBOOL bExtractable, CK_BBOOL bAlwaysSensitive, CK_BBOOL bNeverExtractable, CK_BBOOL bWrapWithTrusted, CK_ATTRIBUTE_PTR pUnwrapTemplate, CK_ULONG ulUnwrapTemplateLen, CK_BBOOL bAlwaysAuthenticate)
+{
+ CK_RV rv;
+
+ CK_BBOOL obj_sensitive = CK_FALSE;
+ CK_BBOOL obj_decrypt = CK_FALSE;
+ CK_BBOOL obj_sign = CK_FALSE;
+ CK_BBOOL obj_sign_recover = CK_FALSE;
+ CK_BBOOL obj_unwrap = CK_FALSE;
+ CK_BBOOL obj_extractable = CK_FALSE;
+ CK_BBOOL obj_always_sensitive = CK_FALSE;
+ CK_BBOOL obj_never_extractable = CK_FALSE;
+ CK_BBOOL obj_wrap_with_trusted = CK_FALSE;
+ CK_BBOOL obj_always_authenticate = CK_FALSE;
+ CK_LONG len_unwrap_template = ulUnwrapTemplateLen;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_SUBJECT, NULL_PTR, 0 },
+ { CKA_SENSITIVE, &obj_sensitive, sizeof(obj_sensitive) },
+ { CKA_DECRYPT, &obj_decrypt, sizeof(obj_decrypt) },
+ { CKA_SIGN, &obj_sign, sizeof(obj_sign) },
+ { CKA_SIGN_RECOVER, &obj_sign_recover, sizeof(obj_sign_recover) },
+ { CKA_UNWRAP, &obj_unwrap, sizeof(obj_unwrap) },
+ { CKA_EXTRACTABLE, &obj_extractable, sizeof(obj_extractable) },
+ { CKA_ALWAYS_SENSITIVE, &obj_always_sensitive, sizeof(obj_always_sensitive) },
+ { CKA_NEVER_EXTRACTABLE, &obj_never_extractable, sizeof(obj_never_extractable) },
+ { CKA_WRAP_WITH_TRUSTED, &obj_wrap_with_trusted, sizeof(obj_wrap_with_trusted) },
+ { CKA_UNWRAP_TEMPLATE, pUnwrapTemplate, ulUnwrapTemplateLen },
+ { CKA_ALWAYS_AUTHENTICATE, &obj_always_authenticate, sizeof(obj_always_authenticate) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 12) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulSubjectLen);
+ CPPUNIT_ASSERT(obj_sensitive == bSensitive);
+ CPPUNIT_ASSERT(obj_decrypt == bDecrypt);
+ CPPUNIT_ASSERT(obj_sign == bSign);
+ CPPUNIT_ASSERT(obj_sign_recover == bSignRecover);
+ CPPUNIT_ASSERT(obj_unwrap == bUnwrap);
+ CPPUNIT_ASSERT(obj_extractable == bExtractable);
+ CPPUNIT_ASSERT(obj_always_sensitive == bAlwaysSensitive);
+ CPPUNIT_ASSERT(obj_never_extractable == bNeverExtractable);
+ CPPUNIT_ASSERT(obj_wrap_with_trusted == bWrapWithTrusted);
+ CPPUNIT_ASSERT(obj_always_authenticate == bAlwaysAuthenticate);
+ len_unwrap_template = attribs[10].ulValueLen;
+ CPPUNIT_ASSERT(len_unwrap_template == 0);
+ if (ulSubjectLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pSubject, ulSubjectLen) == 0);
+
+ free(attribs[0].pValue);
+}
+
+void ObjectTests::checkCommonRSAPublicKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen, CK_ULONG ulModulusBits, CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen)
+{
+ CK_RV rv;
+
+ CK_ULONG obj_bits = 0;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_MODULUS, NULL_PTR, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 },
+ { CKA_MODULUS_BITS, &obj_bits, sizeof(obj_bits) }
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulModulusLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulPublicExponentLen);
+ CPPUNIT_ASSERT(obj_bits == ulModulusBits);
+ if (ulModulusLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pModulus, ulModulusLen) == 0);
+ if (ulPublicExponentLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pPublicExponent, ulPublicExponentLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+}
+
+void ObjectTests::checkCommonRSAPrivateKeyAttributes(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen, CK_BYTE_PTR /*pPublicExponent*/, CK_ULONG /*ulPublicExponentLen*/, CK_BYTE_PTR pPrivateExponent, CK_ULONG ulPrivateExponentLen, CK_BYTE_PTR /*pPrime1*/, CK_ULONG /*ulPrime1Len*/, CK_BYTE_PTR /*pPrime2*/, CK_ULONG /*ulPrime2Len*/, CK_BYTE_PTR /*pExponent1*/, CK_ULONG /*ulExponent1Len*/, CK_BYTE_PTR /*pExponent2*/, CK_ULONG /*ulExponent2Len*/, CK_BYTE_PTR /*pCoefficient*/, CK_ULONG /*ulCoefficientLen*/)
+{
+ CK_RV rv;
+
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_MODULUS, NULL_PTR, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL_PTR, 0 }
+ /* Some tokens may only store modulus and private exponent
+ { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 },
+ { CKA_PRIME_1, NULL_PTR, 0 },
+ { CKA_PRIME_2, NULL_PTR, 0 },
+ { CKA_EXPONENT_1, NULL_PTR, 0 },
+ { CKA_EXPONENT_2, NULL_PTR, 0 },
+ { CKA_COEFFICIENT, NULL_PTR, 0 }, */
+ };
+
+ // Get length
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ attribs[0].pValue = (CK_VOID_PTR)malloc(attribs[0].ulValueLen);
+ attribs[1].pValue = (CK_VOID_PTR)malloc(attribs[1].ulValueLen);
+
+ // Check values
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &attribs[0], 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == ulModulusLen);
+ CPPUNIT_ASSERT(attribs[1].ulValueLen == ulPrivateExponentLen);
+ if (ulModulusLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[0].pValue, pModulus, ulModulusLen) == 0);
+ if (ulPrivateExponentLen > 0)
+ CPPUNIT_ASSERT(memcmp(attribs[1].pValue, pPrivateExponent, ulPrivateExponentLen) == 0);
+
+ free(attribs[0].pValue);
+ free(attribs[1].pValue);
+}
+
+CK_RV ObjectTests::createDataObjectMinimal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ //CKA_MODIFIABLE
+ { CKA_LABEL, label, sizeof(label)-1 },
+ //CKA_COPYABLE
+ //CKA_DESTROYABLE
+
+ // Data
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createDataObjectMCD(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_BBOOL bModifiable, CK_BBOOL bCopyable, CK_BBOOL bDestroyable, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_MODIFIABLE, &bModifiable, sizeof(bModifiable) },
+ { CKA_LABEL, label, sizeof(label)-1 },
+ { CKA_COPYABLE, &bCopyable, sizeof(bCopyable) },
+ { CKA_DESTROYABLE, &bDestroyable, sizeof(bDestroyable) }
+
+ // Data
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createDataObjectNormal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_UTF8CHAR label[] = "A data object";
+
+ CK_UTF8CHAR application[] = "An application";
+ CK_BYTE objectID[] = "invalid object id";
+ CK_BYTE data[] = "Sample data";
+
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ //CKA_MODIFIABLE
+ { CKA_LABEL, label, sizeof(label)-1 },
+ //CKA_COPYABLE
+ //CKA_DESTROYABLE
+
+ // Data
+ { CKA_APPLICATION, application, sizeof(application)-1 },
+ { CKA_OBJECT_ID, objectID, sizeof(objectID) },
+ { CKA_VALUE, data, sizeof(data) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createCertificateObjectIncomplete(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_CERTIFICATE;
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::createCertificateObjectX509(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject)
+{
+ CK_OBJECT_CLASS cClass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE cType = CKC_X_509;
+ const char *pSubject = "invalid subject der";
+ const char *pValue = "invalid certificate der";
+
+ CK_ATTRIBUTE objTemplate[] = {
+ // Common
+ { CKA_CLASS, &cClass, sizeof(cClass) },
+ // Storage
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ // Common Certificate Object Attributes
+ { CKA_CERTIFICATE_TYPE, &cType, sizeof(cType) },
+ // X.509 Certificate Object Attributes
+ { CKA_SUBJECT, (CK_VOID_PTR)pSubject, strlen(pSubject) },
+ { CKA_VALUE, (CK_VOID_PTR)pValue, strlen(pValue) }
+ };
+
+ hObject = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE),&hObject) );
+}
+
+CK_RV ObjectTests::generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+void ObjectTests::testCreateObject()
+{
+// printf("\ntestCreateObject\n");
+
+ // [PKCS#11 v2.40, C_CreateObject]
+ // a. Only session objects can be created during read-only session.
+ // b. Only public objects can be created unless the normal user is logged in.
+ // c. Key object will have CKA_LOCAL == CK_FALSE.
+ // d. If key object is secret or a private key then both CKA_ALWAYS_SENSITIVE == CK_FALSE and CKA_NEVER_EXTRACTABLE == CKA_FALSE.
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+
+ 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_BYTE keyPtr[128];
+ CK_ULONG keyLen = 128;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE, keyPtr, keyLen }
+ };
+
+ CK_BBOOL local;
+ CK_BBOOL always;
+ CK_BBOOL never;
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_LOCAL, &local, sizeof(local) },
+ { CKA_ALWAYS_SENSITIVE, &always, sizeof(always) },
+ { CKA_NEVER_EXTRACTABLE, &never, sizeof(never) }
+ };
+
+ // 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);
+
+ /////////////////////////////////
+ // READ-ONLY & PUBLIC
+ /////////////////////////////////
+
+ // Open read-only session and don't login
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should not be allowed to create token objects because the session is read-only
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ /////////////////////////////////
+ // READ-ONLY & USER
+ /////////////////////////////////
+
+ // Login USER into the read-only session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create private session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be allowed to create token objects.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & PUBLIC
+ /////////////////////////////////
+
+ // Open as read-write session but don't login.
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be able to create private token objects because we are not logged in now
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & USER
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should always be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be able allowed to create private session objects because we are logged in.
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should be able to create private token objects because we are logged in now
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & SO
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_SO,m_soPin1,m_soPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should always be allowed to create public session objects
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in.
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // We should be allowed to create public token objects even when not logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Only public objects can be created unless the normal user is logged in.
+ rv = createDataObjectMinimal(hSession, ON_TOKEN, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ /////////////////////////////////
+ // READ-WRITE & USER
+ /////////////////////////////////
+
+ // Open as read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login to the read-write session
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Create a secret object
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, keyPtr, keyLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, getTemplate, 3) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(local == CK_FALSE);
+ CPPUNIT_ASSERT(always == CK_FALSE);
+ CPPUNIT_ASSERT(never == CK_FALSE);
+
+ // Destroy the secret object
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testCopyObject()
+{
+// printf("\ntestCopyObject\n");
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+ CK_OBJECT_HANDLE hObjectCopy;
+ CK_OBJECT_HANDLE hObject1;
+
+ // 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);
+
+ // Open read-only session and don't login
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get a public session object
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMCD(hSession, IN_SESSION, IS_PUBLIC, CK_TRUE, CK_FALSE, CK_TRUE, hObjectCopy);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Allowed to copy it
+ const char *pLabel = "Label modified via C_CopyObject";
+ CK_BBOOL bToken = CK_FALSE;
+ CK_BBOOL bPrivate = CK_FALSE;
+ CK_OBJECT_CLASS cClass = CKO_DATA;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) },
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_CLASS, &cClass, sizeof(cClass) }
+ };
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 1, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Not allowed to copy.
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObjectCopy, &attribs[0], 1, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_ACTION_PROHIBITED);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObjectCopy) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Still allowed when still session and public
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Not allowed to overwrite an !ck8 attribute
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 4, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Not allowed to go on token
+ bToken = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ bToken = CK_FALSE;
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Not allowed to go to private
+ bPrivate = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ bPrivate = CK_FALSE;
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create a read-write session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, 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 object
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get a public session object
+ rv = createDataObjectNormal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Allowed to go on token
+ bToken = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Allowed to go to private
+ bPrivate = CK_TRUE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Not allowed to change a !ck8 parameter
+ CK_BYTE id[] = "Another object ID";
+ attribs[3].type = CKA_OBJECT_ID;
+ attribs[3].pValue = id;
+ attribs[3].ulValueLen = sizeof(id);
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 4, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Not allowed to downgrade privacy
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectNormal(hSession, IN_SESSION, IS_PRIVATE, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ bToken = CK_FALSE;
+ bPrivate = CK_FALSE;
+ rv = CRYPTOKI_F_PTR( C_CopyObject(hSession, hObject, &attribs[0], 3, &hObject1) );
+ CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCONSISTENT);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testDestroyObject()
+{
+// printf("\ntestDestroyObject\n");
+
+ // [PKCS#11 v2.40, C_Logout] When logout is successful...
+ // a. Any of the application's handles to private objects become invalid.
+ // b. Even if a user is later logged back into the token those handles remain invalid.
+ // c. All private session objects from sessions belonging to the application area destroyed.
+
+ // [PKCS#11 v2.40, C_CreateObject]
+ // Only session objects can be created during read-only session.
+ // Only public objects can be created unless the normal user is logged in.
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+ CK_OBJECT_HANDLE hObjectDestroy;
+
+ // 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);
+
+ // Try to destroy an invalid object using an invalid session
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ // Create a read-only session.
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Trying to destroy an invalid object in a read-only session
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Create a 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);
+
+ // Trying to destroy an invalid object in a read-write session
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // 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);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMCD(hSessionRW, IN_SESSION, IS_PUBLIC, CK_TRUE, CK_TRUE, CK_FALSE, hObjectDestroy);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // We should not be able to destroy a non-destroyable object.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectDestroy) );
+ CPPUNIT_ASSERT(rv == CKR_ACTION_PROHIBITED);
+
+ // On a read-only session we should not be able to destroy the public token object
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectTokenPublic) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // On a read-only session we should not be able to destroy the private token object
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectTokenPrivate) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ // Logout with a different session than the one used for login should be fine.
+ rv = CRYPTOKI_F_PTR( C_Logout(hSessionRW) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Login USER into the sessions so we can destroy private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRO,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // We should be able to destroy the public session object from a read-only session.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRO,hObjectSessionPublic) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // All private session objects should have been destroyed when logging out.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRW,hObjectSessionPrivate) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // We should be able to destroy the public token object now.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRW,hObjectTokenPublic) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // All handles to private token objects should have been invalidated when logging out.
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSessionRW,hObjectTokenPrivate) );
+ CPPUNIT_ASSERT(rv == CKR_OBJECT_HANDLE_INVALID);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testGetObjectSize()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject;
+
+ // 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, &hSession) );
+ 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 a session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get an object
+ rv = createDataObjectMinimal(hSession, IN_SESSION, IS_PUBLIC, hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get the object size
+ CK_ULONG objectSize;
+ rv = CRYPTOKI_F_PTR( C_GetObjectSize(hSession, hObject, &objectSize) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(objectSize == CK_UNAVAILABLE_INFORMATION);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testGetAttributeValue()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+
+ // 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
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Try to destroy an invalid object using an invalid session
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSessionRO,CK_INVALID_HANDLE,NULL,1) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_OBJECT_CLASS cClass = CKO_VENDOR_DEFINED;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CLASS, &cClass, sizeof(cClass) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1) );//sizeof(attribs)/sizeof(CK_ATTRIBUTE));
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testSetAttributeValue()
+{
+ // [PKCS#11 v2.40, 4.1.1 Creating objects]
+ // 1. If the supplied template specifies a value for an invalid attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_TYPE_INVALID. An attribute
+ // is valid if it is either one of the attributes described in the Cryptoki specification or an
+ // additional vendor-specific attribute supported by the library and token.
+ //
+ // 2. If the supplied template specifies an invalid value for a valid attribute, then the
+ // attempt should fail with the error code CKR_ATTRIBUTE_VALUE_INVALID.
+ // The valid values for Cryptoki attributes are described in the Cryptoki specification.
+ //
+ // 3. If the supplied template specifies a value for a read-only attribute, then the attempt
+ // should fail with the error code CKR_ATTRIBUTE_READ_ONLY. Whether or not a
+ // given Cryptoki attribute is read-only is explicitly stated in the Cryptoki specification;
+ // however, a particular library and token may be even more restrictive than Cryptoki
+ // specifies. In other words, an attribute which Cryptoki says is not read-only may
+ // nonetheless be read-only under certain circumstances (i.e., in conjunction with some
+ // combinations of other attributes) for a particular library and token. Whether or not a
+ // given non-Cryptoki attribute is read-only is obviously outside the scope of Cryptoki.
+ //
+ // 4. N/A (Does not apply to C_SetAttributeValue)
+ //
+ // 5. If the attribute values in the supplied template, together with any default attribute
+ // values and any attribute values contributed to the object by the object-creation
+ // function itself, are inconsistent, then the attempt should fail with the error code
+ // CKR_TEMPLATE_INCONSISTENT. A set of attribute values is inconsistent if not
+ // all of its members can be satisfied simultaneously by the token, although each value
+ // individually is valid in Cryptoki. One example of an inconsistent template would be
+ // using a template which specifies two different values for the same attribute. Another
+ // example would be trying to create a secret key object with an attribute which is
+ // appropriate for various types of public keys or private keys, but not for secret keys.
+ // A final example would be a template with an attribute that violates some token
+ // specific requirement. Note that this final example of an inconsistent template is
+ // token-dependent—on a different token, such a template might not be inconsistent.
+ //
+ // 6. If the supplied template specifies the same value for a particular attribute more than
+ // once (or the template specifies the same value for a particular attribute that the object-
+ // creation function itself contributes to the object), then the behavior of Cryptoki is not
+ // completely specified. The attempt to create an object can either succeed—thereby
+ // creating the same object that would have been created if the multiply-specified
+ // attribute had only appeared once—or it can fail with error code
+ // CKR_TEMPLATE_INCONSISTENT. Library developers are encouraged to make
+ // their libraries behave as though the attribute had only appeared once in the template;
+ // application developers are strongly encouraged never to put a particular attribute into
+ // a particular template more than once.
+
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+ CK_OBJECT_HANDLE hObjectSet;
+
+ // 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);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMCD(hSessionRO, IN_SESSION, IS_PUBLIC, CK_FALSE, CK_TRUE, CK_TRUE, hObjectSet);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check that label can be modified on all combintations of session/token and public/private objects
+ const char *pLabel = "Label modified via C_SetAttributeValue";
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectTokenPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectTokenPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSet,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_ACTION_PROHIBITED);
+
+ attribs[0].pValue = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == strlen(pLabel));
+
+ char pStoredLabel[64];
+ attribs[0].pValue = &pStoredLabel[0];
+ attribs[0].ulValueLen = 64;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribs[0].ulValueLen == strlen(pLabel));
+ CPPUNIT_ASSERT(memcmp(pLabel,pStoredLabel,strlen(pLabel)) == 0);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Close session
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRW) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testFindObjects()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_OBJECT_HANDLE hObjectSessionPublic;
+ CK_OBJECT_HANDLE hObjectSessionPrivate;
+ CK_OBJECT_HANDLE hObjectTokenPublic;
+ CK_OBJECT_HANDLE hObjectTokenPrivate;
+
+ // 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);
+
+ // Create all permutations of session/token, public/private objects
+ rv = createDataObjectMinimal(hSessionRO, IN_SESSION, IS_PUBLIC, hObjectSessionPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, IN_SESSION, IS_PRIVATE, hObjectSessionPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PUBLIC, hObjectTokenPublic);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = createDataObjectMinimal(hSessionRW, ON_TOKEN, IS_PRIVATE, hObjectTokenPrivate);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Set labels for the objects
+ const char *pLabel = "Label modified via C_SetAttributeValue";
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_LABEL, (CK_UTF8CHAR_PTR)pLabel, strlen(pLabel) }
+ };
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRO,hObjectSessionPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPublic,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue (hSessionRW,hObjectTokenPrivate,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find the objects while logged in should find them all.
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRO,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_OBJECT_HANDLE hObjects[16];
+ CK_ULONG ulObjectCount = 0;
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRO,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(4 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRO) );
+
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find the objects while no longer logged in should find only 2
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRO,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRO,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(2 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRO) );
+
+ // Close the session used to create the session objects, should also destroy the session objects.
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSessionRO) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Now find just the public token object as public session object should be gone now.
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRW,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRW,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(1 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRW) );
+
+ // Login USER into the sessions so we can gain access to private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSessionRW,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Now find just the public token object as public session object should be gone now.
+ rv = CRYPTOKI_F_PTR( C_FindObjectsInit(hSessionRW,&attribs[0],1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_FindObjects(hSessionRW,&hObjects[0],16,&ulObjectCount) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(2 == ulObjectCount);
+ rv = CRYPTOKI_F_PTR( C_FindObjectsFinal(hSessionRW) );
+}
+
+
+void ObjectTests::testGenerateKeys()
+{
+ 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 hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token public/private key pairs.
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PUBLIC,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,IN_SESSION,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = generateRsaKeyPair(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testCreateCertificates()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ rv = createCertificateObjectIncomplete(hSession,IN_SESSION,IS_PUBLIC,hObject);
+ CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCOMPLETE);
+ rv = createCertificateObjectX509(hSession,IN_SESSION,IS_PUBLIC,hObject);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_BYTE pCheckValue[] = { 0x2b, 0x84, 0xf6 };
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_CHECK_VALUE, pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue(hSession, hObject, attribs, 1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+}
+
+void ObjectTests::testDefaultDataAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal data object
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal data object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in data object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_TRUE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ checkDataObjectAttributes(hSession, hObject, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0);
+}
+
+void ObjectTests::testDefaultX509CertAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal X509 certificate object
+ CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE certificateType = CKC_X_509;
+ CK_BYTE pSubject[] = "Test1";
+ CK_BYTE pValue[] = "Test2";
+ CK_BYTE pCheckValue[] = { 0x2b, 0x84, 0xf6 };
+ CK_DATE emptyDate;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_CERTIFICATE_TYPE, &certificateType, sizeof(certificateType) },
+ { CKA_SUBJECT, pSubject, sizeof(pSubject)-1 },
+ { CKA_VALUE, pValue, sizeof(pValue)-1 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal X509 certificate
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in X509 certificate object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ memset(&emptyDate, 0, sizeof(emptyDate));
+ checkCommonCertificateObjectAttributes(hSession, hObject, CKC_X_509, CK_FALSE, 0, pCheckValue, sizeof(pCheckValue), emptyDate, 0, emptyDate, 0);
+ checkX509CertificateObjectAttributes(hSession, hObject, pSubject, sizeof(pSubject)-1, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, pValue, sizeof(pValue)-1, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, 0, CKM_SHA_1);
+}
+
+void ObjectTests::testDefaultRSAPubAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal RSA public key object
+ CK_OBJECT_CLASS objClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_BYTE pE[] = { 0x01, 0x00, 0x01 };
+ CK_DATE emptyDate;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in RSA public key object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_FALSE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ memset(&emptyDate, 0, sizeof(emptyDate));
+ checkCommonKeyAttributes(hSession, hObject, objType, NULL_PTR, 0, emptyDate, 0, emptyDate, 0, CK_FALSE, CK_FALSE, CK_UNAVAILABLE_INFORMATION, NULL_PTR, 0);
+ checkCommonPublicKeyAttributes(hSession, hObject, NULL_PTR, 0, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_FALSE, NULL_PTR, 0);
+ checkCommonRSAPublicKeyAttributes(hSession, hObject, pN, sizeof(pN), 512, pE, sizeof(pE));
+}
+
+void ObjectTests::testDefaultRSAPrivAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal RSA private key object
+ CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_BYTE pD[] = { 0x6D, 0x94, 0x6B, 0xEB, 0xFF, 0xDC, 0x03, 0x80, 0x7B, 0x0A,
+ 0x4F, 0x0A, 0x98, 0x6C, 0xA3, 0x2A, 0x8A, 0xE4, 0xAA, 0x18,
+ 0x44, 0xA4, 0xA5, 0x39, 0x37, 0x0A, 0x2C, 0xFC, 0x5F, 0xD1,
+ 0x44, 0x6E, 0xCE, 0x25, 0x9B, 0xE5, 0xD1, 0x51, 0xAF, 0xA8,
+ 0x30, 0xD1, 0x4D, 0x3C, 0x60, 0x33, 0xB5, 0xED, 0x4C, 0x39,
+ 0xDA, 0x68, 0x78, 0xF9, 0x6B, 0x4F, 0x47, 0x55, 0xB2, 0x02,
+ 0x00, 0x7E, 0x9C, 0x05 };
+ CK_DATE emptyDate;
+ // Make the key non-sensitive and extractable so that we can test it.
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PRIVATE_EXPONENT, pD, sizeof(pD) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check attributes in RSA public key object
+ checkCommonObjectAttributes(hSession, hObject, objClass);
+ checkCommonStorageObjectAttributes(hSession, hObject, CK_FALSE, CK_TRUE, CK_TRUE, NULL_PTR, 0, CK_TRUE, CK_TRUE);
+ memset(&emptyDate, 0, sizeof(emptyDate));
+ checkCommonKeyAttributes(hSession, hObject, objType, NULL_PTR, 0, emptyDate, 0, emptyDate, 0, CK_FALSE, CK_FALSE, CK_UNAVAILABLE_INFORMATION, NULL_PTR, 0);
+ checkCommonPrivateKeyAttributes(hSession, hObject, NULL_PTR, 0, CK_FALSE, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_TRUE, CK_FALSE, CK_FALSE, CK_FALSE, NULL_PTR, 0, CK_FALSE);
+ checkCommonRSAPrivateKeyAttributes(hSession, hObject, pN, sizeof(pN), NULL_PTR, 0, pD, sizeof(pD), NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0, NULL_PTR, 0);
+}
+
+void ObjectTests::testAlwaysNeverAttribute()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BBOOL always;
+ CK_BBOOL never;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_ALWAYS_SENSITIVE, &always, sizeof(always) },
+ { CKA_NEVER_EXTRACTABLE, &never, sizeof(never) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, getTemplate, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(always == CK_TRUE);
+ CPPUNIT_ASSERT(never == CK_TRUE);
+
+ // Set value
+ rv = CRYPTOKI_F_PTR( C_SetAttributeValue(hSession, hPrk, prkAttribs, 2) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_READ_ONLY);
+
+ // Create object
+ prkAttribs[0].pValue = &bFalse;
+ prkAttribs[1].pValue = &bTrue;
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, getTemplate, 2) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(always == CK_FALSE);
+ CPPUNIT_ASSERT(never == CK_FALSE);
+}
+
+void ObjectTests::testSensitiveAttributes()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BBOOL bSensitive = CK_TRUE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ // Sensitive attributes cannot be revealed in plaintext even if wrapping is allowed
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_SENSITIVE, &bSensitive, sizeof(bSensitive) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_PRIVATE_EXPONENT, NULL_PTR, 0 },
+ { CKA_PRIME_1, NULL_PTR, 0 },
+ { CKA_PRIME_2, NULL_PTR, 0 },
+ { CKA_EXPONENT_1, NULL_PTR, 0 },
+ { CKA_EXPONENT_2, NULL_PTR, 0 },
+ { CKA_COEFFICIENT, NULL_PTR, 0 }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ for (int i = 0; i < 6; i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, &getTemplate[i], 1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_SENSITIVE);
+ }
+
+ // Retry with non-sensitive object
+ bSensitive = CK_FALSE;
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 2, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ for (int i = 0; i < 6; i++)
+ {
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hPrk, &getTemplate[i], 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ }
+}
+
+void ObjectTests::testGetInvalidAttribute()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+
+ // Minimal data object
+ CK_OBJECT_CLASS objClass = CKO_DATA;
+ CK_BBOOL bSign;
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) }
+ };
+ CK_ATTRIBUTE getTemplate[] = {
+ { CKA_SIGN, &bSign, sizeof(bSign) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal data object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, 1, &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Check value
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, getTemplate, 1) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_TYPE_INVALID);
+}
+
+void ObjectTests::testReAuthentication()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1024;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_ALWAYS_AUTHENTICATE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_MECHANISM signMech = { CKM_SHA256_RSA_PKCS, NULL_PTR, 0 };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+ CK_BYTE signature256[256];
+ CK_ULONG signature256Len = sizeof(signature256);
+
+ CK_MECHANISM encMech = { CKM_RSA_PKCS, NULL_PTR, 0 };
+ CK_BYTE cipherText[256];
+ CK_ULONG ulCipherTextLen = sizeof(cipherText);
+ CK_BYTE recoveredText[256];
+ CK_ULONG ulRecoveredTextLen = sizeof(recoveredText);
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create object
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism, pukAttribs, 1, prkAttribs, 4, &hPuk, &hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_Sign with re-authentication with invalid and valid PIN
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length-1) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_Sign without re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ // Test C_SignUpdate with re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignUpdate(hSession, data, sizeof(data)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_SignUpdate without re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignUpdate(hSession, data, sizeof(data)) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_SignUpdate(hSession, data, sizeof(data)) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ // Test C_SignFinal with re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Test C_SignFinal without re-authentication
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &signMech, hPrk) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_SignFinal(hSession, signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+
+ // Encrypt some data
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&encMech,hPuk) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,data,sizeof(data),cipherText,&ulCipherTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // Test C_Decrypt with re-authentication
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&encMech,hPrk) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_CONTEXT_SPECIFIC,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ CPPUNIT_ASSERT(memcmp(data, &recoveredText[ulRecoveredTextLen-sizeof(data)], sizeof(data)) == 0);
+
+ // Test C_Decrypt without re-authentication
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&encMech,hPrk) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,cipherText,ulCipherTextLen,recoveredText,&ulRecoveredTextLen) );
+ CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED);
+}
+
+void ObjectTests::testAllowedMechanisms()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_BYTE key[65] = { "0000000000000000000000000000000000000000000000000000000000000000" };
+ CK_MECHANISM_TYPE allowedMechs[] = { CKM_SHA256_HMAC, CKM_SHA512_HMAC };
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_VALUE, &key, sizeof(key)-1 },
+ { CKA_ALLOWED_MECHANISMS, &allowedMechs, sizeof(allowedMechs) }
+ };
+
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+
+ // SHA_1_HMAC is not an allowed mechanism
+ CK_MECHANISM mechanism = { CKM_SHA_1_HMAC, NULL_PTR, 0 };
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ // SHA256_HMAC is an allowed mechanism
+ mechanism.mechanism = CKM_SHA256_HMAC;
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_BYTE signature256[256];
+ CK_ULONG signature256Len = sizeof(signature256);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature256, &signature256Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // SHA384_HMAC is not an allowed mechanism
+ mechanism.mechanism = CKM_SHA384_HMAC;
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_MECHANISM_INVALID);
+
+ // SHA512_HMAC is an allowed mechanism
+ mechanism.mechanism = CKM_SHA512_HMAC;
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession, &mechanism, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CK_BYTE signature512[512];
+ CK_ULONG signature512Len = sizeof(signature512);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession, data, sizeof(data), signature512, &signature512Len) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void ObjectTests::testTemplateAttribute()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_BYTE pE[] = { 0x01, 0x00, 0x01 };
+ CK_MECHANISM_TYPE allowedMechs[] = { CKM_SHA256_HMAC, CKM_SHA512_HMAC };
+
+ // Wrap template
+ CK_KEY_TYPE wrapType = CKK_SHA256_HMAC;;
+ CK_ATTRIBUTE wrapTemplate[] = {
+ { CKA_KEY_TYPE, &wrapType, sizeof(wrapType) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) },
+ { CKA_ALLOWED_MECHANISMS, &allowedMechs, sizeof(allowedMechs) }
+ };
+
+ // Minimal public key object
+ CK_OBJECT_CLASS objClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE objType = CKK_RSA;
+ CK_BYTE pN[] = { 0xC6, 0x47, 0xDD, 0x74, 0x3B, 0xCB, 0xDC, 0x6F, 0xCE, 0xA7,
+ 0xF0, 0x5F, 0x29, 0x4B, 0x27, 0x00, 0xCC, 0x92, 0xE9, 0x20,
+ 0x8A, 0x2C, 0x87, 0x36, 0x47, 0x24, 0xB0, 0xD5, 0x7D, 0xB0,
+ 0x92, 0x01, 0xA0, 0xA3, 0x55, 0x2E, 0x3F, 0xFE, 0xA7, 0x4C,
+ 0x4B, 0x3F, 0x9D, 0x4E, 0xCB, 0x78, 0x12, 0xA9, 0x42, 0xAD,
+ 0x51, 0x1F, 0x3B, 0xBD, 0x3D, 0x6A, 0xE5, 0x38, 0xB7, 0x45,
+ 0x65, 0x50, 0x30, 0x35 };
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &objClass, sizeof(objClass) },
+ { CKA_KEY_TYPE, &objType, sizeof(objType) },
+ { CKA_MODULUS, pN, sizeof(pN) },
+ { CKA_PUBLIC_EXPONENT, pE, sizeof(pE) },
+ { CKA_WRAP_TEMPLATE, wrapTemplate, sizeof(wrapTemplate) }
+ };
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Create minimal RSA public key object
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, objTemplate, sizeof(objTemplate)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ATTRIBUTE wrapAttribs[] = {
+ { 0, NULL_PTR, 0 },
+ { 0, NULL_PTR, 0 },
+ { 0, NULL_PTR, 0 }
+ };
+ CK_ATTRIBUTE wrapAttrib = { CKA_WRAP_TEMPLATE, NULL_PTR, 0 };
+
+ // Get number of elements
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &wrapAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrapAttrib.ulValueLen == 3 * sizeof(CK_ATTRIBUTE));
+
+ // Get element types and sizes
+ wrapAttrib.pValue = wrapAttribs;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &wrapAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrapAttrib.ulValueLen == 3 * sizeof(CK_ATTRIBUTE));
+ for (size_t i = 0; i < 3; i++)
+ {
+ switch (wrapAttribs[i].type)
+ {
+ case CKA_KEY_TYPE:
+ CPPUNIT_ASSERT(wrapAttribs[i].ulValueLen == sizeof(CK_KEY_TYPE));
+ break;
+ case CKA_PUBLIC_EXPONENT:
+ CPPUNIT_ASSERT(wrapAttribs[i].ulValueLen == sizeof(pE));
+ break;
+ case CKA_ALLOWED_MECHANISMS:
+ CPPUNIT_ASSERT(wrapAttribs[i].ulValueLen == sizeof(allowedMechs));
+ break;
+ default:
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ // Get values
+ wrapAttribs[0].pValue = (CK_VOID_PTR)malloc(wrapAttribs[0].ulValueLen);
+ wrapAttribs[1].pValue = (CK_VOID_PTR)malloc(wrapAttribs[1].ulValueLen);
+ wrapAttribs[2].pValue = (CK_VOID_PTR)malloc(wrapAttribs[2].ulValueLen);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, &wrapAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ for (size_t i = 0; i < 3; i++)
+ {
+ switch (wrapAttribs[i].type)
+ {
+ case CKA_KEY_TYPE:
+ CPPUNIT_ASSERT(*(CK_KEY_TYPE*) wrapAttribs[i].pValue == CKK_SHA256_HMAC);
+ break;
+ case CKA_PUBLIC_EXPONENT:
+ CPPUNIT_ASSERT(memcmp(wrapAttribs[i].pValue, pE, sizeof(pE)) == 0);
+ break;
+ case CKA_ALLOWED_MECHANISMS:
+ CPPUNIT_ASSERT(memcmp(wrapAttribs[i].pValue, allowedMechs, sizeof(allowedMechs)) == 0);
+ break;
+ default:
+ CPPUNIT_ASSERT(false);
+ }
+ }
+
+ free(wrapAttribs[0].pValue);
+ free(wrapAttribs[1].pValue);
+ free(wrapAttribs[2].pValue);
+}
+
+void ObjectTests::testCreateSecretKey()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_BYTE genericKey[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
+ };
+ CK_BYTE aesKey[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
+ };
+ CK_BYTE desKey[] = {
+ 0x81, 0xdc, 0x9b, 0xdb, 0x52, 0xd0, 0x4d, 0xc2
+ };
+ CK_BYTE des2Key[] = {
+ 0x81, 0xdc, 0x9b, 0xdb, 0x52, 0xd0, 0x4d, 0xc2, 0x00, 0x36,
+ 0xdb, 0xd8, 0x31, 0x3e, 0xd0, 0x55
+ };
+ CK_BYTE des3Key[] = {
+ 0x81, 0xdc, 0x9b, 0xdb, 0x52, 0xd0, 0x4d, 0xc2, 0x00, 0x36,
+ 0xdb, 0xd8, 0x31, 0x3e, 0xd0, 0x55, 0xcc, 0x57, 0x76, 0xd1,
+ 0x6a, 0x1f, 0xb6, 0xe4
+ };
+ CK_BYTE genericKCV[] = { 0x5c, 0x3b, 0x7c };
+ CK_BYTE aesKCV[] = { 0x08, 0xbd, 0x28 };
+ CK_BYTE desKCV[] = { 0x08, 0xa1, 0x50 };
+ CK_BYTE des2KCV[] = { 0xa9, 0x67, 0xae };
+ CK_BYTE des3KCV[] = { 0x5c, 0x5e, 0xec };
+
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_VALUE, genericKey, sizeof(genericKey) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_BYTE pCheckValue[3];
+ CK_ATTRIBUTE attribKCV[] = {
+ { CKA_CHECK_VALUE, pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, genericKCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_AES;
+ attribs[0].pValue = aesKey;
+ attribs[0].ulValueLen = sizeof(aesKey);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, aesKCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_DES;
+ attribs[0].pValue = desKey;
+ attribs[0].ulValueLen = sizeof(desKey);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, desKCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_DES2;
+ attribs[0].pValue = des2Key;
+ attribs[0].ulValueLen = sizeof(des2Key);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, des2KCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ keyType = CKK_DES3;
+ attribs[0].pValue = des3Key;
+ attribs[0].ulValueLen = sizeof(des3Key);
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hObject, attribKCV, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(attribKCV[0].ulValueLen == 3);
+ CPPUNIT_ASSERT(memcmp(pCheckValue, des3KCV, 3) == 0);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession,hObject) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
diff --git a/SoftHSMv2/src/lib/test/ObjectTests.h b/SoftHSMv2/src/lib/test/ObjectTests.h
new file mode 100644
index 0000000..b15ae48
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/ObjectTests.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ ObjectTests.h
+
+ Contains test cases to C_CreateObject, C_CopyObject, C_DestroyObject,
+ C_GetAttributeValue, C_SetAttributeValue, C_FindObjectsInit,
+ C_FindObjects, C_FindObjectsFinal, C_GenerateKeyPair
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OBJECTTESTS_H
+#define _SOFTHSM_V2_OBJECTTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class ObjectTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(ObjectTests);
+ CPPUNIT_TEST(testCreateObject);
+ CPPUNIT_TEST(testCopyObject);
+ CPPUNIT_TEST(testDestroyObject);
+ CPPUNIT_TEST(testGetObjectSize);
+ CPPUNIT_TEST(testGetAttributeValue);
+ CPPUNIT_TEST(testSetAttributeValue);
+ CPPUNIT_TEST(testFindObjects);
+ CPPUNIT_TEST(testGenerateKeys);
+ CPPUNIT_TEST(testCreateCertificates);
+ CPPUNIT_TEST(testDefaultDataAttributes);
+ CPPUNIT_TEST(testDefaultX509CertAttributes);
+ CPPUNIT_TEST(testDefaultRSAPubAttributes);
+ CPPUNIT_TEST(testDefaultRSAPrivAttributes);
+ CPPUNIT_TEST(testAlwaysNeverAttribute);
+ CPPUNIT_TEST(testSensitiveAttributes);
+ CPPUNIT_TEST(testGetInvalidAttribute);
+ CPPUNIT_TEST(testAllowedMechanisms);
+ CPPUNIT_TEST(testReAuthentication);
+ CPPUNIT_TEST(testTemplateAttribute);
+ CPPUNIT_TEST(testCreateSecretKey);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testCreateObject();
+ void testCopyObject();
+ void testDestroyObject();
+ void testGetObjectSize();
+ void testGetAttributeValue();
+ void testSetAttributeValue();
+ void testFindObjects();
+ void testGenerateKeys();
+ void testCreateCertificates();
+ void testDefaultDataAttributes();
+ void testDefaultX509CertAttributes();
+ void testDefaultRSAPubAttributes();
+ void testDefaultRSAPrivAttributes();
+ void testAlwaysNeverAttribute();
+ void testSensitiveAttributes();
+ void testGetInvalidAttribute();
+ void testReAuthentication();
+ void testAllowedMechanisms();
+ void testTemplateAttribute();
+ void testCreateSecretKey();
+
+protected:
+ void checkCommonObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_OBJECT_CLASS objectClass
+ );
+ void checkCommonStorageObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BBOOL bToken,
+ CK_BBOOL bPrivate,
+ CK_BBOOL bModifiable,
+ CK_UTF8CHAR_PTR pLabel, CK_ULONG ulLabelLen,
+ CK_BBOOL bCopyable,
+ CK_BBOOL bDestroyable
+ );
+ void checkDataObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_UTF8CHAR_PTR pApplication, CK_ULONG ulApplicationLen,
+ CK_BYTE_PTR pObjectID, CK_ULONG ulObjectIdLen,
+ CK_BYTE_PTR pValue, CK_ULONG ulValueLen
+ );
+ void checkCommonCertificateObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_CERTIFICATE_TYPE certType,
+ CK_BBOOL bTrusted,
+ CK_ULONG ulCertificateCategory,
+ CK_BYTE_PTR pCheckValue, CK_ULONG ulCheckValueLen,
+ CK_DATE startDate, CK_ULONG ulStartDateLen,
+ CK_DATE endDate, CK_ULONG ulEndDateLen
+ );
+ void checkX509CertificateObjectAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BYTE_PTR pId, CK_ULONG ulIdLen,
+ CK_BYTE_PTR pIssuer, CK_ULONG ulIssuerLen,
+ CK_BYTE_PTR pSerialNumber, CK_ULONG ulSerialNumberLen,
+ CK_BYTE_PTR pValue, CK_ULONG ulValueLen,
+ CK_BYTE_PTR pUrl, CK_ULONG ulUrlLen,
+ CK_BYTE_PTR pHashOfSubjectPublicKey, CK_ULONG ulHashOfSubjectPublicKeyLen,
+ CK_BYTE_PTR pHashOfIssuerPublicKey, CK_ULONG ulHashOfIssuerPublicKeyLen,
+ CK_ULONG ulJavaMidpSecurityDomain,
+ CK_MECHANISM_TYPE nameHashAlgorithm
+ );
+ void checkCommonKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_KEY_TYPE keyType,
+ CK_BYTE_PTR pId, CK_ULONG ulIdLen,
+ CK_DATE startDate, CK_ULONG ulStartDateLen,
+ CK_DATE endDate, CK_ULONG ulEndDateLen,
+ CK_BBOOL bDerive,
+ CK_BBOOL bLocal,
+ CK_MECHANISM_TYPE keyMechanismType,
+ CK_MECHANISM_TYPE_PTR pAllowedMechanisms, CK_ULONG ulAllowedMechanismsLen /* len = count * sizeof(CK_MECHANISM_TYPE) */
+ );
+ void checkCommonPublicKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BBOOL bEncrypt,
+ CK_BBOOL bVerify,
+ CK_BBOOL bVerifyRecover,
+ CK_BBOOL bWrap,
+ CK_BBOOL bTrusted,
+ CK_ATTRIBUTE_PTR pWrapTemplate, CK_ULONG ulWrapTemplateLen /* len = count * sizeof(CK_ATTRIBUTE) */
+ );
+ void checkCommonPrivateKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pSubject, CK_ULONG ulSubjectLen,
+ CK_BBOOL bSensitive,
+ CK_BBOOL bDecrypt,
+ CK_BBOOL bSign,
+ CK_BBOOL bSignRecover,
+ CK_BBOOL bUnwrap,
+ CK_BBOOL bExtractable,
+ CK_BBOOL bAlwaysSensitive,
+ CK_BBOOL bNeverExtractable,
+ CK_BBOOL bWrapWithTrusted,
+ CK_ATTRIBUTE_PTR pUnwrapTemplate, CK_ULONG ulUnwrapTemplateLen, /* len = count * sizeof(CK_ATTRIBUTE) */
+ CK_BBOOL bAlwaysAuthenticate
+ );
+ void checkCommonRSAPublicKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen,
+ CK_ULONG ulModulusBits,
+ CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen
+ );
+ void checkCommonRSAPrivateKeyAttributes
+ ( CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_BYTE_PTR pModulus, CK_ULONG ulModulusLen,
+ CK_BYTE_PTR pPublicExponent, CK_ULONG ulPublicExponentLen,
+ CK_BYTE_PTR pPrivateExponent, CK_ULONG ulPrivateExponentLen,
+ CK_BYTE_PTR pPrime1, CK_ULONG ulPrime1Len,
+ CK_BYTE_PTR pPrime2, CK_ULONG ulPrime2Len,
+ CK_BYTE_PTR pExponent1, CK_ULONG ulExponent1Len,
+ CK_BYTE_PTR pExponent2, CK_ULONG ulExponent2Len,
+ CK_BYTE_PTR pCoefficient, CK_ULONG ulCoefficientLen
+ );
+
+ CK_RV createDataObjectMinimal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+ CK_RV createDataObjectMCD(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_BBOOL bModifiable, CK_BBOOL bCopyable, CK_BBOOL bDestroyable, CK_OBJECT_HANDLE &hObject);
+ CK_RV createDataObjectNormal(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+
+ CK_RV createCertificateObjectIncomplete(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+ CK_RV createCertificateObjectX509(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hObject);
+
+ CK_RV generateRsaKeyPair(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+};
+
+#endif // !_SOFTHSM_V2_OBJECTTESTS_H
diff --git a/SoftHSMv2/src/lib/test/README b/SoftHSMv2/src/lib/test/README
new file mode 100644
index 0000000..d9e6cce
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/README
@@ -0,0 +1,17 @@
+To build for test of SoftHSM with static linking:
+make p11test
+
+To build for testing another p11 module provided as shared library:
+make p11test_DEPENDENCIES= p11test_LDADD= CPPFLAGS=-DP11M=\\\"./p11m.so\\\" p11test
+Substitute ./p11m.so with the path to your shared library.
+Note that nothing else of SoftHSMv2 has to be built in order to build the test of an external p11.
+
+To run the test with first a test summary and then specific output of each failure:
+./p11test
+
+To get output of each test after it is executed:
+./p11test direct
+
+To run a specific test:
+./p11test ObjectTests::testArrayAttribute
+Substitute 'ObjectTests::testArrayAttribute' with the test you want to run.
diff --git a/SoftHSMv2/src/lib/test/RandomTests.cpp b/SoftHSMv2/src/lib/test/RandomTests.cpp
new file mode 100644
index 0000000..8fe25bc
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/RandomTests.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RandomTests.cpp
+
+ Contains test cases to C_SeedRandom and C_GenerateRandom
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "RandomTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RandomTests);
+
+void RandomTests::testSeedRandom()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE seed[] = {"Some random data"};
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(CK_INVALID_HANDLE, seed, sizeof(seed)) );
+ 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_SeedRandom(hSession, NULL_PTR, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(hSession, seed, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SeedRandom(hSession, seed, sizeof(seed)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void RandomTests::testGenerateRandom()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_BYTE randomData[40];
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(CK_INVALID_HANDLE, randomData, 40) );
+ 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_GenerateRandom(hSession, NULL_PTR, 40) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, randomData, 40) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, randomData, 40) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/test/RandomTests.h b/SoftHSMv2/src/lib/test/RandomTests.h
new file mode 100644
index 0000000..4b7b062
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/RandomTests.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ RandomTests.h
+
+ Contains test cases to C_SeedRandom and C_GenerateRandom
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_RANDOMTESTS_H
+#define _SOFTHSM_V2_RANDOMTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class RandomTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(RandomTests);
+ CPPUNIT_TEST(testSeedRandom);
+ CPPUNIT_TEST(testGenerateRandom);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testSeedRandom();
+ void testGenerateRandom();
+};
+
+#endif // !_SOFTHSM_V2_RANDOMTESTS_H
diff --git a/SoftHSMv2/src/lib/test/SessionTests.cpp b/SoftHSMv2/src/lib/test/SessionTests.cpp
new file mode 100644
index 0000000..756106a
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SessionTests.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionTests.cpp
+
+ Contains test cases to C_OpenSession, C_CloseSession, C_CloseAllSessions, and
+ C_GetSessionInfo
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SessionTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SessionTests);
+
+void SessionTests::testOpenSession()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ 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, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_invalidSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_notInitializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_TOKEN_NOT_RECOGNIZED);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, 0, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_PARALLEL_NOT_SUPPORTED);
+
+ 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_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SessionTests::testCloseSession()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ 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_CloseSession(CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession + 1) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
+
+void SessionTests::testCloseAllSessions()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_SESSION_INFO info;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_initializedTokenSlotID) );
+ 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_CloseAllSessions(m_invalidSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_notInitializedTokenSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseAllSessions(m_initializedTokenSlotID) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
+
+void SessionTests::testGetSessionInfo()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_SESSION_INFO info;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ 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_GetSessionInfo(CK_INVALID_HANDLE, &info) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession + 1, &info) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(info.state == CKS_RO_PUBLIC_SESSION);
+ CPPUNIT_ASSERT(info.flags == CKF_SERIAL_SESSION);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GetSessionInfo(hSession, &info) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+}
diff --git a/SoftHSMv2/src/lib/test/SessionTests.h b/SoftHSMv2/src/lib/test/SessionTests.h
new file mode 100644
index 0000000..c940ab0
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SessionTests.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SessionTests.h
+
+ Contains test cases to C_OpenSession, C_CloseSession, C_CloseAllSessions, and
+ C_GetSessionInfo
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SESSIONTESTS_H
+#define _SOFTHSM_V2_SESSIONTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class SessionTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(SessionTests);
+ CPPUNIT_TEST(testOpenSession);
+ CPPUNIT_TEST(testCloseSession);
+ CPPUNIT_TEST(testCloseAllSessions);
+ CPPUNIT_TEST(testGetSessionInfo);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testOpenSession();
+ void testCloseSession();
+ void testCloseAllSessions();
+ void testGetSessionInfo();
+};
+
+#endif // !_SOFTHSM_V2_SESSIONTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/SignVerifyTests.cpp b/SoftHSMv2/src/lib/test/SignVerifyTests.cpp
new file mode 100644
index 0000000..06dbf95
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SignVerifyTests.cpp
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SignVerifyTests.cpp
+
+ Contains test cases for:
+ C_SignInit
+ C_Sign
+ C_SignUpdate
+ C_SignFinal
+ C_VerifyInit
+ C_Verify
+ C_VerifyUpdate
+ C_VerifyFinal
+
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SignVerifyTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SignVerifyTests);
+
+CK_RV SignVerifyTests::generateRSA(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE label[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+
+#ifdef WITH_ECC
+CK_RV SignVerifyTests::generateEC(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk)
+{
+ CK_MECHANISM mechanism = { CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_KEY_TYPE keyType = CKK_EC;
+ CK_BYTE oidP256[] = { 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 };
+ CK_BYTE oidP384[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 };
+ CK_BYTE oidP521[] = { 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 };
+ CK_BYTE label[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+
+ CK_ATTRIBUTE pukAttribs[] = {
+ { CKA_EC_PARAMS, NULL, 0 },
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_TOKEN, &bTokenPuk, sizeof(bTokenPuk) },
+ { CKA_PRIVATE, &bPrivatePuk, sizeof(bPrivatePuk) }
+ };
+ CK_ATTRIBUTE prkAttribs[] = {
+ { CKA_LABEL, &label[0], sizeof(label) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_TOKEN, &bTokenPrk, sizeof(bTokenPrk) },
+ { CKA_PRIVATE, &bPrivatePrk, sizeof(bPrivatePrk) },
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }
+ };
+
+ /* Select the curve */
+ if (strcmp(curve, "P-256") == 0)
+ {
+ pukAttribs[0].pValue = oidP256;
+ pukAttribs[0].ulValueLen = sizeof(oidP256);
+ }
+ else if (strcmp(curve, "P-384") == 0)
+ {
+ pukAttribs[0].pValue = oidP384;
+ pukAttribs[0].ulValueLen = sizeof(oidP384);
+ }
+ else if (strcmp(curve, "P-521") == 0)
+ {
+ pukAttribs[0].pValue = oidP521;
+ pukAttribs[0].ulValueLen = sizeof(oidP521);
+ }
+ else
+ {
+ return CKR_GENERAL_ERROR;
+ }
+
+ hPuk = CK_INVALID_HANDLE;
+ hPrk = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pukAttribs, sizeof(pukAttribs)/sizeof(CK_ATTRIBUTE),
+ prkAttribs, sizeof(prkAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPuk, &hPrk) );
+}
+#endif
+
+void SignVerifyTests::signVerifySingle(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param /* = NULL_PTR */, CK_ULONG paramLen /* = 0 */)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, param, paramLen };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession,data,sizeof(data),signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,sizeof(data),signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,sizeof(data),signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+void SignVerifyTests::signVerifySingleData(size_t dataSize, CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param /* = NULL_PTR */, CK_ULONG paramLen /* = 0 */)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, param, paramLen };
+ CK_BYTE *data = (CK_BYTE*)malloc(dataSize);
+ CK_BYTE signature[1024];
+ CK_ULONG ulSignatureLen = 0;
+ unsigned i;
+
+ CPPUNIT_ASSERT(data != NULL);
+
+ for (i=0;i<dataSize;i++)
+ data[i] = i;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv = CRYPTOKI_F_PTR( C_Sign(hSession,data,dataSize,signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,dataSize,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_Verify(hSession,data,dataSize,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+
+ free(data);
+}
+
+void SignVerifyTests::signVerifyMulti(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param /* = NULL_PTR */, CK_ULONG paramLen /* = 0 */)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, param, paramLen };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hPrivateKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv =CRYPTOKI_F_PTR( C_SignUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv =CRYPTOKI_F_PTR( C_SignFinal(hSession,signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hPublicKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+void SignVerifyTests::testRsaSignVerify()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSessionRO;
+ CK_SESSION_HANDLE hSessionRW;
+ CK_RSA_PKCS_PSS_PARAMS params[] = {
+ { CKM_SHA_1, CKG_MGF1_SHA1, 0 },
+ { CKM_SHA224, CKG_MGF1_SHA224, 28 },
+ { CKM_SHA256, CKG_MGF1_SHA256, 32 },
+ { CKM_SHA384, CKG_MGF1_SHA384, 0 },
+ { CKM_SHA512, CKG_MGF1_SHA512, 0 }
+ };
+
+ // 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 hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Public Session keys
+ rv = generateRSA(hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRO, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRO, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRO, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRO, hPuk,hPrk);
+
+#ifdef WITH_RAW_PSS
+ signVerifySingleData(20, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifySingleData(28, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifySingleData(32, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifySingleData(48, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifySingleData(64, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[4], sizeof(params[4]));
+#endif
+
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, &params[4], sizeof(params[4]));
+
+ // Private Session Keys
+ rv = generateRSA(hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[4], sizeof(params[4]));
+
+ // Public Token Keys
+ rv = generateRSA(hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[4], sizeof(params[4]));
+
+ // Private Token Keys
+ rv = generateRSA(hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ signVerifySingle(CKM_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifySingle(CKM_RSA_X_509, hSessionRW, hPuk,hPrk);
+#ifndef WITH_FIPS
+ signVerifyMulti(CKM_MD5_RSA_PKCS, hSessionRW, hPuk,hPrk);
+#endif
+ signVerifyMulti(CKM_SHA1_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA224_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA256_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA384_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA512_RSA_PKCS, hSessionRW, hPuk,hPrk);
+ signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[0], sizeof(params[0]));
+ signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[1], sizeof(params[1]));
+ signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[2], sizeof(params[2]));
+ signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[3], sizeof(params[3]));
+ signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, &params[4], sizeof(params[4]));
+}
+
+#ifdef WITH_ECC
+void SignVerifyTests::testEcSignVerify()
+{
+ 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 hPuk = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE hPrk = CK_INVALID_HANDLE;
+
+ // Public Session keys
+ rv = generateEC("P-256", hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,IN_SESSION,IS_PUBLIC,IN_SESSION,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+
+ // Private Session Keys
+ rv = generateEC("P-256", hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,IN_SESSION,IS_PRIVATE,IN_SESSION,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+
+ // Public Token Keys
+ rv = generateEC("P-256", hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,ON_TOKEN,IS_PUBLIC,ON_TOKEN,IS_PUBLIC,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+
+ // Private Token Keys
+ rv = generateEC("P-256", hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-384", hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+ rv = generateEC("P-521", hSessionRW,ON_TOKEN,IS_PRIVATE,ON_TOKEN,IS_PRIVATE,hPuk,hPrk);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ signVerifySingle(CKM_ECDSA, hSessionRO, hPuk,hPrk);
+}
+#endif
+
+CK_RV SignVerifyTests::generateKey(CK_SESSION_HANDLE hSession, CK_KEY_TYPE keyType, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+#ifndef WITH_BOTAN
+#define GEN_KEY_LEN 75
+#else
+#define GEN_KEY_LEN 64
+#endif
+ CK_RV rv;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_BYTE val[GEN_KEY_LEN];
+ //CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_BYTE oid[] = { 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x1F, 0x00 };
+ CK_ATTRIBUTE kAttribs[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE, val, sizeof(val) },
+ { CKA_GOST28147_PARAMS, oid, sizeof(oid) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, val, GEN_KEY_LEN) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ hKey = CK_INVALID_HANDLE;
+ if (keyType == CKK_GOST28147)
+ {
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, kAttribs, 9, &hKey) );
+ }
+ else
+ {
+ return CRYPTOKI_F_PTR( C_CreateObject(hSession, kAttribs, 8, &hKey) );
+ }
+}
+
+CK_RV SignVerifyTests::generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES2_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV SignVerifyTests::generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV SignVerifyTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) }
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+void SignVerifyTests::macSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+ CK_RV rv;
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,0x0C, 0x0D, 0x0F };
+ CK_BYTE signature[256];
+ CK_ULONG ulSignatureLen = 0;
+
+ rv = CRYPTOKI_F_PTR( C_SignInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv =CRYPTOKI_F_PTR( C_SignUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ ulSignatureLen = sizeof(signature);
+ rv =CRYPTOKI_F_PTR( C_SignFinal(hSession,signature,&ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ // verify again, but now change the input that is being signed.
+ rv = CRYPTOKI_F_PTR( C_VerifyInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ data[0] = 0xff;
+ rv = CRYPTOKI_F_PTR( C_VerifyUpdate(hSession,data,sizeof(data)) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_VerifyFinal(hSession,signature,ulSignatureLen) );
+ CPPUNIT_ASSERT(rv==CKR_SIGNATURE_INVALID);
+}
+
+void SignVerifyTests::testMacSignVerify()
+{
+ 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);
+
+ // Public Session keys
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRO, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRO, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRO, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRO, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+
+ // Private Session Keys
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRW, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+
+ // Public Token Keys
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRW, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,ON_TOKEN,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+
+ // Private Token Keys
+#ifndef WITH_FIPS
+ rv = generateKey(hSessionRW,CKK_MD5_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_MD5_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateKey(hSessionRW,CKK_SHA_1_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA_1_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA224_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA224_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA256_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA256_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA384_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA384_HMAC, hSessionRW, hKey);
+
+ rv = generateKey(hSessionRW,CKK_SHA512_HMAC,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_SHA512_HMAC, hSessionRW, hKey);
+
+#ifdef WITH_GOST
+ rv = generateKey(hSessionRW,CKK_GOST28147,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_GOSTR3411_HMAC, hSessionRW, hKey);
+#endif
+
+ rv = generateDes2Key(hSessionRW,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateDes3Key(hSessionRW,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_DES3_CMAC, hSessionRO, hKey);
+
+ rv = generateAesKey(hSessionRW,ON_TOKEN,IS_PRIVATE,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ macSignVerify(CKM_AES_CMAC, hSessionRO, hKey);
+}
+
diff --git a/SoftHSMv2/src/lib/test/SignVerifyTests.h b/SoftHSMv2/src/lib/test/SignVerifyTests.h
new file mode 100644
index 0000000..a251218
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SignVerifyTests.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SignVerifyTests.h
+
+ Contains test cases to C_SignInit,C_Sign,C_SignUpdate,C_SignFinal,
+ C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SIGNVERIFYTESTS_H
+#define _SOFTHSM_V2_SIGNVERIFYTESTS_H
+
+#include "config.h"
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class SignVerifyTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(SignVerifyTests);
+ CPPUNIT_TEST(testRsaSignVerify);
+#ifdef WITH_ECC
+ CPPUNIT_TEST(testEcSignVerify);
+#endif
+ CPPUNIT_TEST(testMacSignVerify);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testRsaSignVerify();
+#ifdef WITH_ECC
+ void testEcSignVerify();
+#endif
+ void testMacSignVerify();
+
+protected:
+ CK_RV generateRSA(CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+#ifdef WITH_ECC
+ CK_RV generateEC(const char* curve, CK_SESSION_HANDLE hSession, CK_BBOOL bTokenPuk, CK_BBOOL bPrivatePuk, CK_BBOOL bTokenPrk, CK_BBOOL bPrivatePrk, CK_OBJECT_HANDLE &hPuk, CK_OBJECT_HANDLE &hPrk);
+#endif
+ void signVerifySingle(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param = NULL_PTR, CK_ULONG paramLen = 0);
+ void signVerifySingleData(size_t dataSize, CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param = NULL_PTR, CK_ULONG paramLen = 0);
+ void signVerifyMulti(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey, CK_VOID_PTR param = NULL_PTR, CK_ULONG paramLen = 0);
+ CK_RV generateKey(CK_SESSION_HANDLE hSession, CK_KEY_TYPE keyType, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ void macSignVerify(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
+};
+
+#endif // !_SOFTHSM_V2_SIGNVERIFYTESTS_H
diff --git a/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp
new file mode 100644
index 0000000..f301c73
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.cpp
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithmTests.cpp
+
+ Contains test cases for symmetrical algorithms (i.e., AES and DES)
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <climits>
+//#include <iomanip>
+#include "SymmetricAlgorithmTests.h"
+
+// CKA_TOKEN
+const CK_BBOOL ON_TOKEN = CK_TRUE;
+const CK_BBOOL IN_SESSION = CK_FALSE;
+
+// CKA_PRIVATE
+const CK_BBOOL IS_PRIVATE = CK_TRUE;
+const CK_BBOOL IS_PUBLIC = CK_FALSE;
+
+#define NR_OF_BLOCKS_IN_TEST 0x10001
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SymmetricAlgorithmTests);
+
+CK_RV SymmetricAlgorithmTests::generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_ULONG bytes = 16;
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+#ifndef WITH_FIPS
+CK_RV SymmetricAlgorithmTests::generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+CK_RV SymmetricAlgorithmTests::generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES2_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+#endif
+
+CK_RV SymmetricAlgorithmTests::generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_DES3_KEY_GEN, NULL_PTR, 0 };
+ // CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ };
+
+ hKey = CK_INVALID_HANDLE;
+ return CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+}
+
+void SymmetricAlgorithmTests::encryptDecrypt(
+ const CK_MECHANISM_TYPE mechanismType,
+ const size_t blockSize,
+ const CK_SESSION_HANDLE hSession,
+ const CK_OBJECT_HANDLE hKey,
+ const size_t messageSize,
+ const bool isSizeOK)
+{
+ class PartSize {// class to get random size for part
+ private: // we want to know for sure that no part length is causing any problem.
+ const int blockSize;
+ const unsigned* pRandom;// point to memory with random data. We are using the data to be encrypted.
+ const unsigned* pBack;// point to memory where random data ends.
+ int current;// the current size.
+ public:
+ PartSize(
+ const int _blockSize,
+ const std::vector<CK_BYTE>* pvData) :
+ blockSize(_blockSize),
+ pRandom((const unsigned*)&pvData->front()),
+ pBack((const unsigned*)&pvData->back()),
+ current(blockSize*4){};
+ int getCurrent() {// current part size
+ return current;
+ }
+ int getNext() {// get next part size.
+ // Check if we do not have more random data
+ if ((pRandom+sizeof(unsigned)-1) > pBack) {
+ current = blockSize*4;
+ return current;
+ }
+ const unsigned random(*(pRandom++));
+ // Bit shift to handle 32- and 64-bit systems.
+ // Just want a simple random part length,
+ // not a perfect random number (bit shifting will
+ // give some loss of precision).
+ current = ((unsigned long)random >> 20)*blockSize*0x100/(UINT_MAX >> 20) + 1;
+ //std::cout << "New random " << std::hex << random << " current " << std::hex << std::setfill('0') << std::setw(4) << current << " block size " << std::hex << blockSize << std::endl;
+ return current;
+ }
+ };
+
+ const std::vector<CK_BYTE> vData(messageSize);
+ std::vector<CK_BYTE> vEncryptedData;
+ std::vector<CK_BYTE> vEncryptedDataParted;
+ PartSize partSize(blockSize, &vData);
+
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_GenerateRandom(hSession, (CK_BYTE_PTR)&vData.front(), messageSize) ) );
+
+ const CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ CK_MECHANISM_PTR pMechanism((CK_MECHANISM_PTR)&mechanism);
+ CK_AES_CTR_PARAMS ctrParams =
+ {
+ 32,
+ {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+ }
+ };
+ CK_BYTE gcmIV[] = {
+ 0xCA, 0xFE, 0xBA, 0xBE, 0xFA, 0xCE,
+ 0xDB, 0xAD, 0xDE, 0xCA, 0xF8, 0x88
+ };
+ CK_BYTE gcmAAD[] = {
+ 0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF,
+ 0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF,
+ 0xAB, 0xAD, 0xDA, 0xD2
+ };
+ CK_GCM_PARAMS gcmParams =
+ {
+ &gcmIV[0],
+ sizeof(gcmIV),
+ sizeof(gcmIV)*8,
+ &gcmAAD[0],
+ sizeof(gcmAAD),
+ 16*8
+ };
+
+ switch (mechanismType)
+ {
+ case CKM_DES_CBC:
+ case CKM_DES_CBC_PAD:
+ case CKM_DES3_CBC:
+ case CKM_DES3_CBC_PAD:
+ case CKM_AES_CBC:
+ case CKM_AES_CBC_PAD:
+ pMechanism->pParameter = (CK_VOID_PTR)&vData.front();
+ pMechanism->ulParameterLen = blockSize;
+ break;
+ case CKM_AES_CTR:
+ pMechanism->pParameter = &ctrParams;
+ pMechanism->ulParameterLen = sizeof(ctrParams);
+ break;
+ case CKM_AES_GCM:
+ pMechanism->pParameter = &gcmParams;
+ pMechanism->ulParameterLen = sizeof(gcmParams);
+ break;
+ default:
+ break;
+ }
+
+ // Single-part encryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptInit(hSession,pMechanism,hKey) ) );
+ {
+ CK_ULONG ulEncryptedDataLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_Encrypt(hSession,(CK_BYTE_PTR)&vData.front(),messageSize,NULL_PTR,&ulEncryptedDataLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedData.resize(ulEncryptedDataLen);
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Encrypt(hSession,(CK_BYTE_PTR)&vData.front(),messageSize,&vEncryptedData.front(),&ulEncryptedDataLen) ) );
+ vEncryptedData.resize(ulEncryptedDataLen);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("C_Encrypt should fail with C_CKR_DATA_LEN_RANGE", (CK_RV)CKR_DATA_LEN_RANGE, rv);
+ vEncryptedData = vData;
+ }
+ }
+
+ // Multi-part encryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptInit(hSession,pMechanism,hKey) ) );
+
+ for ( std::vector<CK_BYTE>::const_iterator i(vData.begin()); i<vData.end(); i+=partSize.getCurrent() ) {
+ const CK_ULONG lPartLen( i+partSize.getNext()<vData.end() ? partSize.getCurrent() : vData.end()-i );
+ CK_ULONG ulEncryptedPartLen;
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,(CK_BYTE_PTR)&(*i),lPartLen,NULL_PTR,&ulEncryptedPartLen) ) );
+ const size_t oldSize( vEncryptedDataParted.size() );
+ vEncryptedDataParted.resize(oldSize+ulEncryptedPartLen);
+ CK_BYTE dummy;
+ const CK_BYTE_PTR pEncryptedPart( ulEncryptedPartLen>0 ? &vEncryptedDataParted.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,(CK_BYTE_PTR)&(*i),lPartLen,pEncryptedPart,&ulEncryptedPartLen) ) );
+ vEncryptedDataParted.resize(oldSize+ulEncryptedPartLen);
+ }
+ {
+ CK_ULONG ulLastEncryptedPartLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_EncryptFinal(hSession,NULL_PTR,&ulLastEncryptedPartLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ const size_t oldSize( vEncryptedDataParted.size() );
+ CK_BYTE dummy;
+ vEncryptedDataParted.resize(oldSize+ulLastEncryptedPartLen);
+ const CK_BYTE_PTR pLastEncryptedPart( ulLastEncryptedPartLen>0 ? &vEncryptedDataParted.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_EncryptFinal(hSession,pLastEncryptedPart,&ulLastEncryptedPartLen) ) );
+ vEncryptedDataParted.resize(oldSize+ulLastEncryptedPartLen);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("C_EncryptFinal should fail with C_CKR_DATA_LEN_RANGE", (CK_RV)CKR_DATA_LEN_RANGE, rv);
+ vEncryptedDataParted = vData;
+ }
+ }
+
+ // Single-part decryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptInit(hSession,pMechanism,hKey) ) );
+
+ {
+ CK_ULONG ulDataLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),NULL_PTR,&ulDataLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ std::vector<CK_BYTE> vDecryptedData(ulDataLen);
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedData.front(),&ulDataLen) ) );
+ vDecryptedData.resize(ulDataLen);
+ CPPUNIT_ASSERT_MESSAGE("C_Encrypt C_Decrypt does not give the original", vData==vDecryptedData);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "C_Decrypt should fail with CKR_ENCRYPTED_DATA_LEN_RANGE", (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+ }
+ }
+
+ // Multi-part decryption
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptInit(hSession,pMechanism,hKey) ) );
+ {
+ std::vector<CK_BYTE> vDecryptedData;
+ CK_BYTE dummy;
+ for ( std::vector<CK_BYTE>::iterator i(vEncryptedDataParted.begin()); i<vEncryptedDataParted.end(); i+=partSize.getCurrent()) {
+ const CK_ULONG ulPartLen( i+partSize.getNext()<vEncryptedDataParted.end() ? partSize.getCurrent() : vEncryptedDataParted.end()-i );
+ CK_ULONG ulDecryptedPartLen;
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&(*i),ulPartLen,NULL_PTR,&ulDecryptedPartLen) ) );
+ const size_t oldSize( vDecryptedData.size() );
+ vDecryptedData.resize(oldSize+ulDecryptedPartLen);
+ const CK_BYTE_PTR pDecryptedPart( ulDecryptedPartLen>0 ? &vDecryptedData.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&(*i),ulPartLen,pDecryptedPart,&ulDecryptedPartLen) ) );
+ vDecryptedData.resize(oldSize+ulDecryptedPartLen);
+ }
+ {
+ CK_ULONG ulLastPartLen;
+ const CK_RV rv( CRYPTOKI_F_PTR( C_DecryptFinal(hSession,NULL_PTR,&ulLastPartLen) ) );
+ if ( isSizeOK ) {
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ const size_t oldSize( vDecryptedData.size() );
+ vDecryptedData.resize(oldSize+ulLastPartLen);
+ const CK_BYTE_PTR pLastPart( ulLastPartLen>0 ? &vDecryptedData.at(oldSize) : &dummy );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_DecryptFinal(hSession,pLastPart,&ulLastPartLen) ) );
+ vDecryptedData.resize(oldSize+ulLastPartLen);
+ CPPUNIT_ASSERT_MESSAGE("C_EncryptUpdate/C_EncryptFinal C_DecryptUpdate/C_DecryptFinal does not give the original", vData==vDecryptedData);
+ } else {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE( "C_EncryptFinal should fail with CKR_ENCRYPTED_DATA_LEN_RANGE", (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+ }
+ }
+ }
+}
+
+CK_RV SymmetricAlgorithmTests::generateRsaPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey)
+{
+ CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0 };
+ CK_ULONG bits = 1536;
+ CK_BYTE pubExp[] = {0x01, 0x00, 0x01};
+ CK_BYTE subject[] = { 0x12, 0x34 }; // dummy
+ CK_BYTE id[] = { 123 } ; // dummy
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE pubAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bFalse, sizeof(bFalse) },
+ { CKA_MODULUS_BITS, &bits, sizeof(bits) },
+ { CKA_PUBLIC_EXPONENT, &pubExp[0], sizeof(pubExp) }
+ };
+ CK_ATTRIBUTE privAttribs[] = {
+ { CKA_TOKEN, &bToken, sizeof(bToken) },
+ { CKA_PRIVATE, &bPrivate, sizeof(bPrivate) },
+ { CKA_SUBJECT, &subject[0], sizeof(subject) },
+ { CKA_ID, &id[0], sizeof(id) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_SIGN, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bFalse, sizeof(bFalse) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ CK_OBJECT_HANDLE hPub = CK_INVALID_HANDLE;
+ hKey = CK_INVALID_HANDLE;
+ CK_RV rv;
+ rv = CRYPTOKI_F_PTR( C_GenerateKeyPair(hSession, &mechanism,
+ pubAttribs, sizeof(pubAttribs)/sizeof(CK_ATTRIBUTE),
+ privAttribs, sizeof(privAttribs)/sizeof(CK_ATTRIBUTE),
+ &hPub, &hKey) );
+ if (hPub != CK_INVALID_HANDLE)
+ {
+ CRYPTOKI_F_PTR( C_DestroyObject(hSession, hPub) );
+ }
+ return rv;
+}
+
+void SymmetricAlgorithmTests::aesWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
+{
+ CK_MECHANISM mechanism = { mechanismType, NULL_PTR, 0 };
+ 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_BYTE keyPtr[128];
+ CK_ULONG keyLen =
+ mechanismType == CKM_AES_KEY_WRAP_PAD ? 125UL : 128UL;
+ CK_ATTRIBUTE attribs[] = {
+ { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) },
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bTrue, sizeof(bTrue) }, // Wrapping is allowed even on sensitive objects
+ { CKA_VALUE, keyPtr, keyLen }
+ };
+ CK_OBJECT_HANDLE hSecret;
+ CK_RV rv;
+
+ rv = CRYPTOKI_F_PTR( C_GenerateRandom(hSession, keyPtr, keyLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ hSecret = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hSecret != CK_INVALID_HANDLE);
+
+ CK_BYTE_PTR wrappedPtr = NULL_PTR;
+ CK_ULONG wrappedLen = 0UL;
+ CK_ULONG zero = 0UL;
+ CK_ULONG rndKeyLen = keyLen;
+ if (mechanismType == CKM_AES_KEY_WRAP_PAD)
+ rndKeyLen = (keyLen + 7) & ~7;
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_KEY_UNEXTRACTABLE);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ attribs[0].pValue = &bTrue;
+
+ hSecret = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_CreateObject(hSession, attribs, sizeof(attribs)/sizeof(CK_ATTRIBUTE), &hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hSecret != CK_INVALID_HANDLE);
+
+ // Estimate wrapped length
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrappedLen == rndKeyLen + 8);
+
+ wrappedPtr = (CK_BYTE_PTR) malloc(wrappedLen);
+ CPPUNIT_ASSERT(wrappedPtr != NULL_PTR);
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(wrappedLen == rndKeyLen + 8);
+
+ // This should always fail because wrapped data have to be longer than 0 bytes
+ zero = 0;
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hSecret, wrappedPtr, &zero) );
+ CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL);
+
+ CK_ATTRIBUTE nattribs[] = {
+ { CKA_CLASS, &secretClass, sizeof(secretClass) },
+ { CKA_KEY_TYPE, &genKeyType, sizeof(genKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bFalse, sizeof(bFalse) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bFalse,sizeof(bFalse) },
+ { CKA_VERIFY, &bTrue, sizeof(bTrue) }
+ };
+ CK_OBJECT_HANDLE hNew;
+
+ hNew = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hKey, wrappedPtr, wrappedLen, nattribs, sizeof(nattribs)/sizeof(CK_ATTRIBUTE), &hNew) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hNew != CK_INVALID_HANDLE);
+
+ free(wrappedPtr);
+ wrappedPtr = NULL_PTR;
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hSecret) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_OBJECT_HANDLE hRsa;
+ hRsa = CK_INVALID_HANDLE;
+ rv = generateRsaPrivateKey(hSession, CK_TRUE, CK_TRUE, hRsa);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hRsa != CK_INVALID_HANDLE);
+
+ CK_OBJECT_CLASS privateClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE rsaKeyType = CKK_RSA;
+ CK_BYTE_PTR p2Ptr = NULL_PTR;
+ CK_ULONG p2Len = 0UL;
+ CK_ATTRIBUTE rsaAttribs[] = {
+ { CKA_CLASS, &privateClass, sizeof(privateClass) },
+ { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) },
+ { CKA_PRIME_2, NULL_PTR, 0UL }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hRsa, rsaAttribs, sizeof(rsaAttribs)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(rsaAttribs[0].ulValueLen == sizeof(CK_OBJECT_CLASS));
+ CPPUNIT_ASSERT(*(CK_OBJECT_CLASS*)rsaAttribs[0].pValue == CKO_PRIVATE_KEY);
+ CPPUNIT_ASSERT(rsaAttribs[1].ulValueLen == sizeof(CK_KEY_TYPE));
+ CPPUNIT_ASSERT(*(CK_KEY_TYPE*)rsaAttribs[1].pValue == CKK_RSA);
+
+ p2Len = rsaAttribs[2].ulValueLen;
+ p2Ptr = (CK_BYTE_PTR) malloc(2 * p2Len);
+ CPPUNIT_ASSERT(p2Ptr != NULL_PTR);
+ rsaAttribs[2].pValue = p2Ptr;
+ rsaAttribs[2].ulValueLen = p2Len;
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hRsa, rsaAttribs, sizeof(rsaAttribs)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(rsaAttribs[2].ulValueLen == p2Len);
+
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hRsa, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ wrappedPtr = (CK_BYTE_PTR) malloc(wrappedLen);
+ CPPUNIT_ASSERT(wrappedPtr != NULL_PTR);
+ rv = CRYPTOKI_F_PTR( C_WrapKey(hSession, &mechanism, hKey, hRsa, wrappedPtr, &wrappedLen) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hRsa) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ATTRIBUTE nRsaAttribs[] = {
+ { CKA_CLASS, &privateClass, sizeof(privateClass) },
+ { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) },
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_SIGN, &bFalse,sizeof(bFalse) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ { CKA_SENSITIVE, &bFalse, sizeof(bFalse) },
+ { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue) }
+ };
+
+ hRsa = CK_INVALID_HANDLE;
+ rv = CRYPTOKI_F_PTR( C_UnwrapKey(hSession, &mechanism, hKey, wrappedPtr, wrappedLen, nRsaAttribs, sizeof(nRsaAttribs)/sizeof(CK_ATTRIBUTE), &hRsa) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(hRsa != CK_INVALID_HANDLE);
+
+ rsaAttribs[2].pValue = p2Ptr + p2Len;
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hRsa, rsaAttribs, sizeof(rsaAttribs)/sizeof(CK_ATTRIBUTE)) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CPPUNIT_ASSERT(rsaAttribs[0].ulValueLen == sizeof(CK_OBJECT_CLASS));
+ CPPUNIT_ASSERT(*(CK_OBJECT_CLASS*)rsaAttribs[0].pValue == CKO_PRIVATE_KEY);
+ CPPUNIT_ASSERT(rsaAttribs[1].ulValueLen == sizeof(CK_KEY_TYPE));
+ CPPUNIT_ASSERT(*(CK_KEY_TYPE*)rsaAttribs[1].pValue == CKK_RSA);
+ CPPUNIT_ASSERT(rsaAttribs[2].ulValueLen == p2Len);
+ CPPUNIT_ASSERT(memcmp(p2Ptr, p2Ptr + p2Len, p2Len) == 0);
+
+ free(wrappedPtr);
+ free(p2Ptr);
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hRsa) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SymmetricAlgorithmTests::testAesEncryptDecrypt()
+{
+ CK_RV rv;
+ // 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
+ 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 hKey = CK_INVALID_HANDLE;
+
+ // Generate all combinations of session/token keys.
+ rv = generateAesKey(hSessionRW,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // AES allways have the block size of 128 bits (0x80 bits 0x10 bytes).
+ // with padding all message sizes could be encrypted-decrypted.
+ // without padding the message size must be a multiple of the block size.
+ const int blockSize(0x10);
+ encryptDecrypt(CKM_AES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_AES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_AES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_AES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_AES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_AES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_AES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_AES_CTR,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_AES_CTR,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_AES_CTR,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+#ifdef WITH_AES_GCM
+ encryptDecrypt(CKM_AES_GCM,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_AES_GCM,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_AES_GCM,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+#endif
+}
+
+void SymmetricAlgorithmTests::testAesWrapUnwrap()
+{
+ CK_RV rv;
+ // 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
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Open session
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, 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 = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ 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::testDesEncryptDecrypt()
+{
+ CK_RV rv;
+ // 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
+ 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);
+
+ // 3DES and DES always have the block size of 64 bits (0x40 bits 0x8 bytes).
+ // with padding all message sizes could be encrypted-decrypted.
+ // without padding the message size must be a multiple of the block size.
+ const int blockSize(0x8);
+
+#ifndef WITH_FIPS
+ 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);
+
+ encryptDecrypt(CKM_DES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_DES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_DES_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_DES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+
+ 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);
+
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+#endif
+
+ 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);
+
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST-1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1);
+ encryptDecrypt(CKM_DES3_CBC_PAD,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_CBC,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST);
+ encryptDecrypt(CKM_DES3_ECB,blockSize,hSessionRO,hKey,blockSize*NR_OF_BLOCKS_IN_TEST+1, false);
+}
+
+void SymmetricAlgorithmTests::testNullTemplate()
+{
+ CK_RV rv;
+ 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
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism1, NULL_PTR, 0, &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism2, NULL_PTR, 0, &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_TEMPLATE_INCOMPLETE);
+}
+
+void SymmetricAlgorithmTests::testNonModifiableDesKeyGeneration()
+{
+ CK_RV rv;
+ 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
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, sizeof(keyAttribs)/sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( 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 = CRYPTOKI_F_PTR( 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 = CRYPTOKI_F_PTR( 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 = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs1, sizeof(keyAttribs1) / sizeof(CK_ATTRIBUTE),
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SymmetricAlgorithmTests::testCheckValue()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mechanism = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the sessions so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_ULONG bytes = 16;
+ CK_BYTE pCheckValue[] = { 0x2b, 0x84, 0xf6 };
+ CK_BBOOL bFalse = CK_FALSE;
+ CK_BBOOL bTrue = CK_TRUE;
+ CK_ATTRIBUTE keyAttribs[] = {
+ { CKA_TOKEN, &bFalse, sizeof(bFalse) },
+ { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
+ { CKA_ENCRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_DECRYPT, &bTrue, sizeof(bTrue) },
+ { CKA_WRAP, &bTrue, sizeof(bTrue) },
+ { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
+ { CKA_VALUE_LEN, &bytes, sizeof(bytes) },
+ { CKA_CHECK_VALUE, &pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, 8,
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_ATTRIBUTE_VALUE_INVALID);
+
+ keyAttribs[7].ulValueLen = 0;
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, 8,
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_ATTRIBUTE checkAttrib[] = {
+ { CKA_CHECK_VALUE, &pCheckValue, sizeof(pCheckValue) }
+ };
+
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey, checkAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(checkAttrib[0].ulValueLen == 0);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_GenerateKey(hSession, &mechanism,
+ keyAttribs, 7,
+ &hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ checkAttrib[0].ulValueLen = sizeof(pCheckValue);
+ rv = CRYPTOKI_F_PTR( C_GetAttributeValue(hSession, hKey, checkAttrib, 1) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(checkAttrib[0].ulValueLen == 3);
+
+ rv = CRYPTOKI_F_PTR( C_DestroyObject(hSession, hKey) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void SymmetricAlgorithmTests::testAesCtrOverflow()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Initialize the library and start the test.
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ 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, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Login USER into the session so we can create a private objects
+ rv = CRYPTOKI_F_PTR( C_Login(hSession,CKU_USER,m_userPin1,m_userPin1Length) );
+ CPPUNIT_ASSERT(rv==CKR_OK);
+
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+
+ // Generate a session keys.
+ rv = generateAesKey(hSession,IN_SESSION,IS_PUBLIC,hKey);
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ CK_MECHANISM mechanism = { CKM_AES_CTR, NULL_PTR, 0 };
+ CK_AES_CTR_PARAMS ctrParams =
+ {
+ 2,
+ {
+ 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+ }
+ };
+ mechanism.pParameter = &ctrParams;
+ mechanism.ulParameterLen = sizeof(ctrParams);
+
+ CK_BYTE plainText[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x00 };
+ std::vector<CK_BYTE> vEncryptedData;
+ std::vector<CK_BYTE> vEncryptedDataParted;
+ std::vector<CK_BYTE> vDecryptedData;
+ std::vector<CK_BYTE> vDecryptedDataParted;
+ CK_ULONG ulEncryptedDataLen;
+ CK_ULONG ulEncryptedPartLen;
+ CK_ULONG ulDataLen;
+ CK_ULONG ulDataPartLen;
+
+ // Single-part encryption
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText),NULL_PTR,&ulEncryptedDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_DATA_LEN_RANGE, rv );
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText)-1,NULL_PTR,&ulEncryptedDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedData.resize(ulEncryptedDataLen);
+ rv = CRYPTOKI_F_PTR( C_Encrypt(hSession,plainText,sizeof(plainText)-1,&vEncryptedData.front(),&ulEncryptedDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedData.resize(ulEncryptedDataLen);
+
+ // Multi-part encryption
+ rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,plainText,sizeof(plainText)-1,NULL_PTR,&ulEncryptedPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedDataParted.resize(ulEncryptedPartLen);
+ rv = CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,plainText,sizeof(plainText)-1,&vEncryptedDataParted.front(),&ulEncryptedPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vEncryptedDataParted.resize(ulEncryptedPartLen);
+ rv = CRYPTOKI_F_PTR( C_EncryptUpdate(hSession,plainText,1,NULL_PTR,&ulEncryptedPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_DATA_LEN_RANGE, rv );
+
+ // Single-part decryption
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size()+1,NULL_PTR,&ulDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),NULL_PTR,&ulDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedData.resize(ulDataLen);
+ rv = CRYPTOKI_F_PTR( C_Decrypt(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedData.front(),&ulDataLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedData.resize(ulDataLen);
+
+ // Multi-part decryption
+ rv = CRYPTOKI_F_PTR( C_DecryptInit(hSession,&mechanism,hKey) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ rv = CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&vEncryptedData.front(),vEncryptedData.size(),NULL_PTR,&ulDataPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedDataParted.resize(ulDataPartLen);
+ rv = CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&vEncryptedData.front(),vEncryptedData.size(),&vDecryptedDataParted.front(),&ulDataPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, rv );
+ vDecryptedDataParted.resize(ulDataPartLen);
+ rv = CRYPTOKI_F_PTR( C_DecryptUpdate(hSession,&vEncryptedData.front(),1,NULL_PTR,&ulDataPartLen) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_ENCRYPTED_DATA_LEN_RANGE, rv );
+}
diff --git a/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h
new file mode 100644
index 0000000..9b96ae1
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/SymmetricAlgorithmTests.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 SURFnet
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ SymmetricAlgorithmTests.h
+
+ Contains test cases for symmetrical algorithms (i.e., AES and DES)
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
+#define _SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class SymmetricAlgorithmTests : public TestsBase
+{
+ CPPUNIT_TEST_SUITE(SymmetricAlgorithmTests);
+ CPPUNIT_TEST(testAesEncryptDecrypt);
+ CPPUNIT_TEST(testDesEncryptDecrypt);
+#ifdef HAVE_AES_KEY_WRAP
+ CPPUNIT_TEST(testAesWrapUnwrap);
+#endif
+ CPPUNIT_TEST(testNullTemplate);
+ CPPUNIT_TEST(testNonModifiableDesKeyGeneration);
+ CPPUNIT_TEST(testCheckValue);
+ CPPUNIT_TEST(testAesCtrOverflow);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testAesEncryptDecrypt();
+ void testDesEncryptDecrypt();
+ void testAesWrapUnwrap();
+ void testNullTemplate();
+ void testNonModifiableDesKeyGeneration();
+ void testCheckValue();
+ void testAesCtrOverflow();
+
+protected:
+ CK_RV generateAesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#ifndef WITH_FIPS
+ CK_RV generateDesKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ CK_RV generateDes2Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+#endif
+ CK_RV generateDes3Key(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+ void encryptDecrypt(
+ CK_MECHANISM_TYPE mechanismType,
+ size_t sizeOfIV,
+ CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hKey,
+ size_t messageSize,
+ bool isSizeOK=true);
+ void aesWrapUnwrap(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey);
+ CK_RV generateRsaPrivateKey(CK_SESSION_HANDLE hSession, CK_BBOOL bToken, CK_BBOOL bPrivate, CK_OBJECT_HANDLE &hKey);
+};
+
+#endif // !_SOFTHSM_V2_SYMENCRYPTDECRYPTTESTS_H
diff --git a/SoftHSMv2/src/lib/test/TestsBase.cpp b/SoftHSMv2/src/lib/test/TestsBase.cpp
new file mode 100644
index 0000000..1c8467c
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsBase.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsBase.cpp
+
+ Base class for test classes.
+ *****************************************************************************/
+
+#include "TestsBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+void TestsBase::setUp() {
+ TestsNoPINInitBase::setUp();
+
+ CK_SESSION_HANDLE hSession;
+
+ // Open session
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION|CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession)==CKR_OK ) );
+
+ // Login SO
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_Login(hSession,CKU_SO, m_soPin1, m_soPin1Length)==CKR_OK ) );
+
+ // Initialize the user pin
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length)==CKR_OK ) );
+}
diff --git a/SoftHSMv2/src/lib/test/TestsBase.h b/SoftHSMv2/src/lib/test/TestsBase.h
new file mode 100644
index 0000000..6bcf894
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsBase.h
+
+ Base class for test classes.
+ *****************************************************************************/
+
+#ifndef SRC_LIB_TEST_TESTSBASE_H_
+#define SRC_LIB_TEST_TESTSBASE_H_
+
+#include <TestsNoPINInitBase.h>
+
+class TestsBase : public TestsNoPINInitBase {
+public:
+ virtual void setUp();
+};
+
+
+#endif /* SRC_LIB_TEST_TESTSBASE_H_ */
diff --git a/SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp
new file mode 100644
index 0000000..f5bb066
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsNoPINInitBase.cpp
+
+ Base class for test classes. Used when there is no need for user login.
+ *****************************************************************************/
+
+#include "TestsNoPINInitBase.h"
+#include <cstring>
+#include <cppunit/extensions/HelperMacros.h>
+#include <vector>
+#include <sstream>
+
+#ifdef P11M
+#ifdef _WIN32
+CK_FUNCTION_LIST_PTR FunctionList::getFunctionListPtr(const char*const libName, HINSTANCE__* p11Library, const char*getFunctionList) {
+#else
+#include <dlfcn.h>
+
+static CK_FUNCTION_LIST_PTR getFunctionListPtr(const char*const libName, void *const p11Library, const char*getFunctionList) {
+#endif //_WIN32
+ CPPUNIT_ASSERT_MESSAGE(libName, p11Library);
+#ifdef _WIN32
+ const CK_C_GetFunctionList pGFL( (CK_C_GetFunctionList)GetProcAddress(
+ p11Library,
+ getFunctionList.c_str()
+ ) );
+#else
+ const CK_C_GetFunctionList pGFL( (CK_C_GetFunctionList)dlsym(
+ p11Library,
+ getFunctionList
+ ) );
+#endif //_WIN32
+ CPPUNIT_ASSERT_MESSAGE(libName, pGFL);
+ CK_FUNCTION_LIST_PTR ptr(NULL_PTR);
+ const CK_RV retCode( pGFL(&ptr) );
+ if ( !ptr && (retCode)!=CKR_OK) {
+ std::ostringstream oss;
+ oss << "C_GetFunctionList failed...error no = 0x" << std::hex << retCode << " libName '" << libName << "'.";
+ CPPUNIT_ASSERT_MESSAGE(oss.str(), false);
+ }
+ return ptr;
+}
+#endif //P11M
+void TestsNoPINInitBase::getSlotIDs() {
+ bool hasFoundFree(false);
+ bool hasFoundInitialized(false);
+ CK_ULONG nrOfSlots;
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, NULL_PTR, &nrOfSlots)==CKR_OK ) );
+ std::vector<CK_SLOT_ID> slotIDs(nrOfSlots);
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_GetSlotList(CK_TRUE, &slotIDs.front(), &nrOfSlots)==CKR_OK ) );
+ for ( std::vector<CK_SLOT_ID>::iterator i=slotIDs.begin(); i!=slotIDs.end(); i++ ) {
+ CK_TOKEN_INFO tokenInfo;
+ CPPUNIT_ASSERT( CRYPTOKI_F_PTR( C_GetTokenInfo(*i, &tokenInfo)==CKR_OK ) );
+ if ( tokenInfo.flags&CKF_TOKEN_INITIALIZED ) {
+ if ( !hasFoundInitialized ) {
+ hasFoundInitialized = true;
+ m_initializedTokenSlotID = *i;
+ }
+ } else {
+ if ( !hasFoundFree ) {
+ hasFoundFree = true;
+ m_notInitializedTokenSlotID = *i;
+ }
+ }
+ }
+ if ( !hasFoundInitialized ) {
+ m_initializedTokenSlotID = m_notInitializedTokenSlotID;
+ }
+}
+
+TestsNoPINInitBase::TestsNoPINInitBase() :
+#ifdef P11M
+#ifdef _WIN32
+ p11Library( LoadLibrary(libName.c_str()) ),
+#else
+ p11Library( dlopen(P11M, RTLD_LAZY) ),
+#endif
+ m_ptr(getFunctionListPtr(P11M, p11Library, "C_GetFunctionList")),
+#endif
+ m_invalidSlotID(((CK_SLOT_ID)1<<31)),
+ m_initializedTokenSlotID(m_invalidSlotID),
+ m_notInitializedTokenSlotID(m_invalidSlotID),
+ m_soPin1((CK_UTF8CHAR_PTR)"12345678"),
+ m_soPin1Length(strlen((char*)m_soPin1)),
+ m_userPin1((CK_UTF8CHAR_PTR)"1234"),
+ m_userPin1Length(strlen((char*)m_userPin1)) {};
+
+void TestsNoPINInitBase::setUp() {
+ CK_UTF8CHAR label[32];
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // initialize cryptoki
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) ) );
+ // update slot IDs to initialized and not initialized token.
+ getSlotIDs();
+ // (Re)initialize the token
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) ) );
+ // Reset cryptoki to get new slot IDs.
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) ) );
+ CPPUNIT_ASSERT_EQUAL( (CK_RV)CKR_OK, CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) ) );
+ // slot IDs must be updated since the ID of the initialized token has changed.
+ getSlotIDs();
+}
+
+void TestsNoPINInitBase::tearDown() {
+ const CK_RV result(CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) ) );
+ if ( result==CKR_OK||result==CKR_CRYPTOKI_NOT_INITIALIZED ) {
+ return;
+ }
+ std::ostringstream oss;
+ oss << "C_Finalize failed with CK_RV: " << std::hex << result;
+ CPPUNIT_ASSERT_MESSAGE(oss.str(), false);
+}
+
+#ifdef P11M
+TestsNoPINInitBase::~TestsNoPINInitBase() {
+ if ( !p11Library ) {
+ return;
+ }
+#ifdef _WIN32
+ FreeLibrary(p11Library);
+#else
+ dlclose(p11Library);
+#endif // _WIN32
+}
+
+void softHSMLog(const int, const char*, const char*, const int, const char*, ...)
+{
+
+}
+#else
+TestsNoPINInitBase::~TestsNoPINInitBase() {}
+#endif // P11M
diff --git a/SoftHSMv2/src/lib/test/TestsNoPINInitBase.h b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.h
new file mode 100644
index 0000000..acce9f1
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TestsNoPINInitBase.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TestsNoPINInitBase.h
+
+ Base class for test classes. Used when there is no need for user login.
+ *****************************************************************************/
+
+#ifndef SRC_LIB_TEST_TESTSNOPININITBASE_H_
+#define SRC_LIB_TEST_TESTSNOPININITBASE_H_
+
+#include "cryptoki.h"
+#include <cppunit/TestFixture.h>
+
+
+#ifdef P11M
+#define CRYPTOKI_F_PTR(func) m_ptr->func
+#else
+#define CRYPTOKI_F_PTR(func) func
+#endif
+
+class TestsNoPINInitBase : public CppUnit::TestFixture {
+public:
+ TestsNoPINInitBase();
+ virtual ~TestsNoPINInitBase();
+
+ virtual void setUp();
+ virtual void tearDown();
+private:
+ void getSlotIDs();
+#ifdef P11M
+#ifdef _WIN32
+ HINSTANCE__* p11Library;
+#else
+ void *const p11Library;
+#endif
+protected:
+ const CK_FUNCTION_LIST_PTR m_ptr;
+#else
+protected:
+#endif
+ const CK_SLOT_ID m_invalidSlotID;
+ CK_SLOT_ID m_initializedTokenSlotID;
+ CK_SLOT_ID m_notInitializedTokenSlotID;
+
+ const CK_UTF8CHAR_PTR m_soPin1;
+ const CK_ULONG m_soPin1Length;
+
+ const CK_UTF8CHAR_PTR m_userPin1;
+ const CK_ULONG m_userPin1Length;
+};
+
+
+#endif /* SRC_LIB_TEST_TESTSNOPININITBASE_H_ */
diff --git a/SoftHSMv2/src/lib/test/TokenTests.cpp b/SoftHSMv2/src/lib/test/TokenTests.cpp
new file mode 100644
index 0000000..9fc77ba
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TokenTests.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TokenTests.cpp
+
+ Contains test cases to C_InitToken
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "TokenTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TokenTests);
+
+void TokenTests::testInitToken()
+{
+ CK_RV rv;
+ CK_UTF8CHAR label[32];
+ CK_SESSION_HANDLE hSession;
+ CK_TOKEN_INFO tokenInfo;
+ CK_CHAR serialNumber[16];
+
+ memset(label, ' ', 32);
+ memcpy(label, "token1", strlen("token1"));
+
+ // Just make sure that we finalize any previous failed tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ 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_InitToken(m_initializedTokenSlotID, NULL_PTR, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_invalidSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_SLOT_ID_INVALID);
+
+ // Initialize
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Get token serial
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_initializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ memcpy(serialNumber, tokenInfo.serialNumber, 16);
+
+ // Initialize with wrong password
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length - 1, label) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ 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_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_EXISTS);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Re-initialize
+ rv = CRYPTOKI_F_PTR( C_InitToken(m_initializedTokenSlotID, m_soPin1, m_soPin1Length, label) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ // Compare token serial
+ rv = CRYPTOKI_F_PTR( C_GetTokenInfo(m_initializedTokenSlotID, &tokenInfo) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CPPUNIT_ASSERT(memcmp(serialNumber, tokenInfo.serialNumber, 16) == 0);
+
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+}
diff --git a/SoftHSMv2/src/lib/test/TokenTests.h b/SoftHSMv2/src/lib/test/TokenTests.h
new file mode 100644
index 0000000..cc08b72
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/TokenTests.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ TokenTests.h
+
+ Contains test cases to C_InitToken
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TOKENTESTS_H
+#define _SOFTHSM_V2_TOKENTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class TokenTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(TokenTests);
+ CPPUNIT_TEST(testInitToken);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInitToken();
+};
+
+#endif // !_SOFTHSM_V2_TOKENTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/UserTests.cpp b/SoftHSMv2/src/lib/test/UserTests.cpp
new file mode 100644
index 0000000..d4999e5
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/UserTests.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UserTests.cpp
+
+ Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
+ *****************************************************************************/
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "UserTests.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(UserTests);
+
+void UserTests::testInitPIN()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ 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 | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_NOT_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(CK_INVALID_HANDLE, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, 0) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);
+
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void UserTests::testLogin()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession[2];
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Set up user PIN
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_PIN_NOT_INITIALIZED);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession[0], m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ 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 | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(CK_INVALID_HANDLE, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, NULL_PTR, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, 0) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession[1]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY_EXISTS);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession[1]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession[0]) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length - 1) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession[0], CKU_USER, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ALREADY_LOGGED_IN);
+}
+
+void UserTests::testLogout()
+{
+ CK_RV rv;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ 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 | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(CK_INVALID_HANDLE) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
+
+void UserTests::testSetPIN()
+{
+ CK_RV rv;
+ const CK_UTF8CHAR_PTR pin2((CK_UTF8CHAR_PTR)"12345");
+ const CK_ULONG pin2Length(strlen((char*)pin2));
+ const CK_UTF8CHAR_PTR so2pin((CK_UTF8CHAR_PTR)"123456789");
+ const CK_ULONG so2pinLength(strlen((char*)so2pin));
+ CK_SESSION_HANDLE hSession;
+
+ // Just make sure that we finalize any previous tests
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ // Set up user PIN
+ rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ rv = CRYPTOKI_F_PTR( C_InitPIN(hSession, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+ CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) );
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ 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_SetPIN(CK_INVALID_HANDLE, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_SESSION_READ_ONLY);
+
+ rv = CRYPTOKI_F_PTR( C_CloseSession(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, NULL_PTR, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, NULL_PTR, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, 0) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_LEN_RANGE);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, pin2, pin2Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_USER, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_userPin1, m_userPin1Length, pin2, pin2Length) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, pin2, pin2Length, m_userPin1, m_userPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
+
+ rv = CRYPTOKI_F_PTR( C_Logout(hSession) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_Login(hSession, CKU_SO, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, so2pin, so2pinLength, so2pin, so2pinLength) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_soPin1, m_soPin1Length, so2pin, so2pinLength) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, m_soPin1, m_soPin1Length, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_PIN_INCORRECT);
+
+ rv = CRYPTOKI_F_PTR( C_SetPIN(hSession, so2pin, so2pinLength, m_soPin1, m_soPin1Length) );
+ CPPUNIT_ASSERT(rv == CKR_OK);
+}
diff --git a/SoftHSMv2/src/lib/test/UserTests.h b/SoftHSMv2/src/lib/test/UserTests.h
new file mode 100644
index 0000000..9104208
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/UserTests.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ UserTests.h
+
+ Contains test cases to C_InitPIN, C_SetPIN, C_Login, and C_Logout
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_USERTESTS_H
+#define _SOFTHSM_V2_USERTESTS_H
+
+#include "TestsNoPINInitBase.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+class UserTests : public TestsNoPINInitBase
+{
+ CPPUNIT_TEST_SUITE(UserTests);
+ CPPUNIT_TEST(testInitPIN);
+ CPPUNIT_TEST(testLogin);
+ CPPUNIT_TEST(testLogout);
+ CPPUNIT_TEST(testSetPIN);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testInitPIN();
+ void testLogin();
+ void testLogout();
+ void testSetPIN();
+};
+
+#endif // !_SOFTHSM_V2_USERTESTS_H
+
diff --git a/SoftHSMv2/src/lib/test/p11test.cpp b/SoftHSMv2/src/lib/test/p11test.cpp
new file mode 100644
index 0000000..1198c91
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/p11test.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ p11test.cpp
+
+ The main test executor for tests on the PKCS#11 interface in SoftHSM v2
+ *****************************************************************************/
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestFailure.h>
+#include <cppunit/TestResultCollector.h>
+#include <cppunit/SourceLine.h>
+#include <cppunit/Message.h>
+#include <cppunit/Exception.h>
+#include <cppunit/XmlOutputter.h>
+#include <fstream>
+#include <stdlib.h>
+#include <iostream>
+#ifdef _WIN32
+#include "setenv.h"
+#endif
+
+class MyListener : public CPPUNIT_NS::TestListener {
+ virtual void startTest( CPPUNIT_NS::Test*const pTest ) {
+ std::cout << std::endl << pTest->getName() << ' ' << pTest->countTestCases() << std::endl << std::endl;
+ }
+ virtual void addFailure( const CPPUNIT_NS::TestFailure & failure ) {
+ const CPPUNIT_NS::SourceLine solurceLine( failure.sourceLine() );
+ CPPUNIT_NS::Message message( failure.thrownException()->message() );
+ std::cout << solurceLine.fileName() << ' ' << solurceLine.lineNumber() << ' ' << message.shortDescription() << std::endl;
+ std::cout << message.details() << std::endl << std::endl;
+ }
+};
+int main(int argc, char**const argv)
+{
+#ifndef _WIN32
+ setenv("SOFTHSM2_CONF", "./softhsm2.conf", 1);
+#else
+ setenv("SOFTHSM2_CONF", ".\\softhsm2.conf", 1);
+#endif
+
+ CPPUNIT_NS::TestFactoryRegistry &registry( CPPUNIT_NS::TestFactoryRegistry::getRegistry() );
+
+ CPPUNIT_NS::TextTestRunner runner;
+ runner.addTest(registry.makeTest());
+ if ( argc<2 ) {
+ return runner.run() ? 0 : 1;
+ }
+ if ( std::string("direct").find(*(argv+1))==std::string::npos ) {
+ return runner.run(*(argv+1)) ? 0 : 1;
+ }
+ runner.addTest(registry.makeTest());
+ CPPUNIT_NS::TestResult controller;
+ CPPUNIT_NS::TestResultCollector result;
+ controller.addListener( &result );
+ MyListener progress;
+ controller.addListener( &progress );
+
+ runner.run(controller);
+
+ std::ofstream xmlFileOut("test-results.xml");
+ CppUnit::XmlOutputter xmlOut(&result, xmlFileOut);
+ xmlOut.write();
+
+ return result.wasSuccessful() ? 0 : 1;
+}
diff --git a/SoftHSMv2/src/lib/test/softhsm2-alt.conf.in b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.in
new file mode 100644
index 0000000..5bdcb1f
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.in
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @builddir@/tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = true
diff --git a/SoftHSMv2/src/lib/test/softhsm2-alt.conf.win32 b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.win32
new file mode 100644
index 0000000..68cb2ec
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2-alt.conf.win32
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = .\tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = true
diff --git a/SoftHSMv2/src/lib/test/softhsm2.conf.in b/SoftHSMv2/src/lib/test/softhsm2.conf.in
new file mode 100644
index 0000000..6554669
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2.conf.in
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = @builddir@/tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = false
diff --git a/SoftHSMv2/src/lib/test/softhsm2.conf.win32 b/SoftHSMv2/src/lib/test/softhsm2.conf.win32
new file mode 100644
index 0000000..a877d1f
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/softhsm2.conf.win32
@@ -0,0 +1,6 @@
+# SoftHSM v2 configuration file
+
+directories.tokendir = .\tokens
+objectstore.backend = file
+log.level = INFO
+slots.removable = false
diff --git a/SoftHSMv2/src/lib/test/tokens/dummy.in b/SoftHSMv2/src/lib/test/tokens/dummy.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/SoftHSMv2/src/lib/test/tokens/dummy.in