diff options
Diffstat (limited to 'SoftHSMv2/src/lib/test')
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 = ¶m1; + 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 = ¶m2; + 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 = ¶m3; + 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, ¶ms[0], sizeof(params[0])); + signVerifySingleData(28, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[1], sizeof(params[1])); + signVerifySingleData(32, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[2], sizeof(params[2])); + signVerifySingleData(48, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[3], sizeof(params[3])); + signVerifySingleData(64, CKM_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[4], sizeof(params[4])); +#endif + + signVerifyMulti(CKM_SHA1_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[0], sizeof(params[0])); + signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[1], sizeof(params[1])); + signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[2], sizeof(params[2])); + signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[3], sizeof(params[3])); + signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRO, hPuk,hPrk, ¶ms[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, ¶ms[0], sizeof(params[0])); + signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[1], sizeof(params[1])); + signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[2], sizeof(params[2])); + signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[3], sizeof(params[3])); + signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[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, ¶ms[0], sizeof(params[0])); + signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[1], sizeof(params[1])); + signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[2], sizeof(params[2])); + signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[3], sizeof(params[3])); + signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[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, ¶ms[0], sizeof(params[0])); + signVerifyMulti(CKM_SHA224_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[1], sizeof(params[1])); + signVerifyMulti(CKM_SHA256_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[2], sizeof(params[2])); + signVerifyMulti(CKM_SHA384_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[3], sizeof(params[3])); + signVerifyMulti(CKM_SHA512_RSA_PKCS_PSS, hSessionRW, hPuk,hPrk, ¶ms[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 ®istry( 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 |