public void _03_GetObjectSizeTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) Assert.Fail(rv.ToString()); // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Create object NativeULong objectId = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11Library, session, ref objectId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); // Determine object size NativeULong objectSize = 0; rv = pkcs11Library.C_GetObjectSize(session, objectId, ref objectSize); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); Assert.IsTrue(objectSize > 0); rv = pkcs11Library.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) Assert.Fail(rv.ToString()); } }
public void _02_UsingPkcs11DisposeTest() { Helpers.CheckPlatform(); // Pkcs11Library class can be used in using statement which defines a scope // at the end of which an object will be disposed. using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { // Do something interesting } }
public UriDialog(Pkcs11Library pkcs11Library, Pkcs11Slot pkcs11Slot, Pkcs11ObjectInfo pkcs11ObjectInfo) { InitializeComponent(); this.Icon = Properties.Resources.Pkcs11Admin; _pkcs11Library = pkcs11Library; _pkcs11Slot = pkcs11Slot; _pkcs11ObjectInfo = pkcs11ObjectInfo; RefreshUri(); }
public void _01_BasicMechanismListAndInfoTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Get number of supported mechanisms in first call NativeULong mechanismCount = 0; rv = pkcs11Library.C_GetMechanismList(slotId, null, ref mechanismCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(mechanismCount > 0); // Allocate array for supported mechanisms CKM[] mechanismList = new CKM[mechanismCount]; // Get supported mechanisms in second call rv = pkcs11Library.C_GetMechanismList(slotId, mechanismList, ref mechanismCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Analyze first supported mechanism CK_MECHANISM_INFO mechanismInfo = new CK_MECHANISM_INFO(); rv = pkcs11Library.C_GetMechanismInfo(slotId, mechanismList[0], ref mechanismInfo); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with mechanism info rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicPkcs11DisposeTest() { Helpers.CheckPlatform(); // Unmanaged PKCS#11 library is loaded by the constructor of Pkcs11Library class // and unloaded by Dispose() method. Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath); // Do something interesting pkcs11Library.Dispose(); }
public void _02_SecurityOfficerLoginTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs41); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as SO (security officer) rv = pkcs11Library.C_Login(session, CKU.CKU_SO, Settings.SecurityOfficerPinArray, ConvertUtils.UInt32FromInt32(Settings.SecurityOfficerPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting as security officer rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_BasicSlotListAndInfoTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Get number of slots in first call NativeULong slotCount = 0; rv = pkcs11Library.C_GetSlotList(true, null, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(slotCount > 0); // Allocate array for slot IDs NativeULong[] slotList = new NativeULong[slotCount]; // Get slot IDs in second call rv = pkcs11Library.C_GetSlotList(true, slotList, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Analyze first slot CK_SLOT_INFO slotInfo = new CK_SLOT_INFO(); rv = pkcs11Library.C_GetSlotInfo(slotList[0], ref slotInfo); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with slot info Assert.IsFalse(String.IsNullOrEmpty(ConvertUtils.BytesToUtf8String(slotInfo.ManufacturerId))); rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_GenerateRandomTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RO (read-only) session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, CKF.CKF_SERIAL_SESSION, IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Allocate array for random bytes byte[] randomData = new byte[256]; // Get random or pseudo-random data rv = pkcs11Library.C_GenerateRandom(session, randomData, ConvertUtils.UInt64FromInt32(randomData.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with random data rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_SeedRandomTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RO (read-only) session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, CKF.CKF_SERIAL_SESSION, IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Mix additional seed material into the token's random number generator byte[] seed = ConvertUtils.Utf8StringToBytes("Additional seed material"); rv = pkcs11Library.C_SeedRandom(session, seed, ConvertUtils.UInt64FromInt32(seed.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with random number generator rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _03_SessionInfoTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RO (read-only) session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, CKF.CKF_SERIAL_SESSION, IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } CK_SESSION_INFO sessionInfo = new CK_SESSION_INFO(); rv = pkcs11Library.C_GetSessionInfo(session, ref sessionInfo); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with session info Assert.IsTrue(sessionInfo.SlotId == slotId); rv = pkcs11Library.C_CloseAllSessions(slotId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _06_Pkcs11WithoutGetFunctionListTest() { Helpers.CheckPlatform(); // Before an application can perform any cryptographic operations with Cryptoki library // it has to obtain function pointers for all the Cryptoki API routines present in the library. // This can be done either via C_GetFunctionList() function or via platform specific native // function - GetProcAddress() on Windows and dlsym() on Unix. // The most simple constructor of Pkcs11Library class uses C_GetFunctionList() approach // but Pkcs11Interop also provides an alternative constructor // that can specify which approach should be used. using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath, false)) { // Do something interesting } }
public void _02_CancelFunctionTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs41); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RO (read-only) session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, CKF.CKF_SERIAL_SESSION, IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Legacy functions should always return CKR_FUNCTION_NOT_PARALLEL rv = pkcs11Library.C_CancelFunction(session); if (rv != CKR.CKR_FUNCTION_NOT_PARALLEL) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_SlotListTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Get number of slots in first call NativeULong slotCount = 0; rv = pkcs11Library.C_GetSlotList(true, null, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(slotCount > 0); // Allocate array for slot IDs NativeULong[] slotList = new NativeULong[slotCount]; // Get slot IDs in second call rv = pkcs11Library.C_GetSlotList(true, slotList, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with slots rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_ReadWriteSessionTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RW (read-write) session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting in RW session rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
/// <summary> /// Creates the data object. /// </summary> /// <param name='pkcs11Library'>Initialized PKCS11 wrapper</param> /// <param name='session'>Read-write session with user logged in</param> /// <param name='objectId'>Output parameter for data object handle</param> /// <returns>Return value of C_CreateObject</returns> public static CKR CreateDataObject(Pkcs11Library pkcs11Library, NativeULong session, ref NativeULong objectId) { CKR rv = CKR.CKR_OK; // Prepare attribute template of new data object CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[5]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA); template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); template[2] = CkaUtils.CreateAttribute(CKA.CKA_APPLICATION, Settings.ApplicationName); template[3] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); template[4] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, "Data object content"); // Create object rv = pkcs11Library.C_CreateObject(session, template, ConvertUtils.UInt32FromInt32(template.Length), ref objectId); // In LowLevelAPI caller has to free unmanaged memory taken by attributes for (int i = 0; i < template.Length; i++) { UnmanagedMemory.Free(ref template[i].value); template[i].valueLen = 0; } return(rv); }
public void _02_CopyObjectTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Create object that can be copied NativeULong objectId = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11Library, session, ref objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Copy object NativeULong copiedObjectId = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_CopyObject(session, objectId, null, 0, ref copiedObjectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with new object rv = pkcs11Library.C_DestroyObject(session, copiedObjectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicDeriveKeyTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RW session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key NativeULong baseKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11Library, session, ref baseKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate random data needed for key derivation byte[] data = new byte[24]; rv = pkcs11Library.C_GenerateRandom(session, data, ConvertUtils.UInt64FromInt32(data.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify mechanism parameters // Note that we are allocating unmanaged memory that will have to be freed later CK_KEY_DERIVATION_STRING_DATA mechanismParams = new CK_KEY_DERIVATION_STRING_DATA(); mechanismParams.Data = UnmanagedMemory.Allocate(data.Length); UnmanagedMemory.Write(mechanismParams.Data, data); mechanismParams.Len = ConvertUtils.UInt64FromInt32(data.Length); // Specify derivation mechanism with parameters // Note that CkmUtils.CreateMechanism() automaticaly copies mechanismParams into newly allocated unmanaged memory CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_XOR_BASE_AND_DATA, mechanismParams); // Derive key NativeULong derivedKey = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_DeriveKey(session, ref mechanism, baseKeyId, null, 0, ref derivedKey); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with derived key Assert.IsTrue(derivedKey != CK.CK_INVALID_HANDLE); // In LowLevelAPI we have to free all unmanaged memory we previously allocated UnmanagedMemory.Free(ref mechanismParams.Data); mechanismParams.Len = 0; // In LowLevelAPI we have to free unmanaged memory taken by mechanism parameter UnmanagedMemory.Free(ref mechanism.Parameter); mechanism.ParameterLen = 0; rv = pkcs11Library.C_DestroyObject(session, baseKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_DestroyObject(session, derivedKey); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicInitTokenAndPinTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO(); rv = pkcs11Library.C_GetTokenInfo(slotId, ref tokenInfo); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Check if token needs to be initialized if ((tokenInfo.Flags & CKF.CKF_TOKEN_INITIALIZED) != CKF.CKF_TOKEN_INITIALIZED) { // Token label is 32 bytes long string padded with blank characters byte[] label = new byte[32]; for (int i = 0; i < label.Length; i++) { label[i] = 0x20; } Array.Copy(Settings.ApplicationNameArray, 0, label, 0, Settings.ApplicationNameArray.Length); // Initialize token and SO (security officer) pin rv = pkcs11Library.C_InitToken(slotId, Settings.SecurityOfficerPinArray, ConvertUtils.UInt32FromInt32(Settings.SecurityOfficerPinArray.Length), label); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Open RW session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as SO (security officer) rv = pkcs11Library.C_Login(session, CKU.CKU_SO, Settings.SecurityOfficerPinArray, ConvertUtils.UInt32FromInt32(Settings.SecurityOfficerPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Initialize user pin rv = pkcs11Library.C_InitPIN(session, Settings.NormalUserPinArray, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_CreateDestroyObjectTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare attribute template of new data object CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[5]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA); template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); template[2] = CkaUtils.CreateAttribute(CKA.CKA_APPLICATION, Settings.ApplicationName); template[3] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); template[4] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, "Data object content"); // Create object NativeULong objectId = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_CreateObject(session, template, ConvertUtils.UInt32FromInt32(template.Length), ref objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // In LowLevelAPI we have to free unmanaged memory taken by attributes for (int i = 0; i < template.Length; i++) { UnmanagedMemory.Free(ref template[i].value); template[i].valueLen = 0; } // Do something interesting with new object // Destroy object rv = pkcs11Library.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicSignAndVerifyRecoverTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate asymetric key pair NativeULong pubKeyId = CK.CK_INVALID_HANDLE; NativeULong privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11Library, session, ref pubKeyId, ref privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify signing mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS); // Initialize signing operation rv = pkcs11Library.C_SignRecoverInit(session, ref mechanism, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = ConvertUtils.Utf8StringToBytes("Hello world"); // Get length of signature in first call NativeULong signatureLen = 0; rv = pkcs11Library.C_SignRecover(session, sourceData, ConvertUtils.UInt64FromInt32(sourceData.Length), null, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(signatureLen > 0); // Allocate array for signature byte[] signature = new byte[signatureLen]; // Get signature in second call rv = pkcs11Library.C_SignRecover(session, sourceData, ConvertUtils.UInt64FromInt32(sourceData.Length), signature, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with signature // Initialize verification operation rv = pkcs11Library.C_VerifyRecoverInit(session, ref mechanism, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get length of recovered data in first call NativeULong recoveredDataLen = 0; rv = pkcs11Library.C_VerifyRecover(session, signature, ConvertUtils.UInt64FromInt32(signature.Length), null, ref recoveredDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(recoveredDataLen > 0); // Allocate array for recovered data byte[] recoveredData = new byte[recoveredDataLen]; // Verify signature and get recovered data in second call rv = pkcs11Library.C_VerifyRecover(session, signature, ConvertUtils.UInt64FromInt32(signature.Length), recoveredData, ref recoveredDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with verification result and recovered data Assert.IsTrue(ConvertUtils.BytesToBase64String(sourceData) == ConvertUtils.BytesToBase64String(recoveredData)); rv = pkcs11Library.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicObjectFindingTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Let's create two objects so we can find something NativeULong objectId1 = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11Library, session, ref objectId1); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } NativeULong objectId2 = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11Library, session, ref objectId2); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare attribute template that defines search criteria CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA); template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); // Initialize searching rv = pkcs11Library.C_FindObjectsInit(session, template, ConvertUtils.UInt64FromInt32(template.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get search results NativeULong foundObjectCount = 0; NativeULong[] foundObjectIds = new NativeULong[2]; foundObjectIds[0] = CK.CK_INVALID_HANDLE; foundObjectIds[1] = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_FindObjects(session, foundObjectIds, ConvertUtils.UInt64FromInt32(foundObjectIds.Length), ref foundObjectCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Terminate searching rv = pkcs11Library.C_FindObjectsFinal(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with found objects Assert.IsTrue((foundObjectIds[0] != CK.CK_INVALID_HANDLE) && (foundObjectIds[1] != CK.CK_INVALID_HANDLE)); // In LowLevelAPI we have to free unmanaged memory taken by attributes for (int i = 0; i < template.Length; i++) { UnmanagedMemory.Free(ref template[i].value); template[i].valueLen = 0; } rv = pkcs11Library.C_DestroyObject(session, objectId2); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_DestroyObject(session, objectId1); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
/// <summary> /// Obtains a list of all slots where token that matches PKCS#11 URI is present /// </summary> /// <param name="pkcs11Uri">PKCS#11 URI</param> /// <param name="pkcs11Library">Low level PKCS#11 wrapper</param> /// <param name="tokenPresent">Flag indicating whether the list obtained includes only those slots with a token present (true), or all slots (false)</param> /// <param name="slotList">List of slots matching PKCS#11 URI</param> /// <returns>CKR_OK if successful; any other value otherwise</returns> public static CKR GetMatchingSlotList(Pkcs11Uri pkcs11Uri, Pkcs11Library pkcs11Library, bool tokenPresent, out NativeULong[] slotList) { if (pkcs11Uri == null) { throw new ArgumentNullException("pkcs11Uri"); } if (pkcs11Library == null) { throw new ArgumentNullException("pkcs11Library"); } List <NativeULong> matchingSlots = new List <NativeULong>(); // Get library information CK_INFO libraryInfo = new CK_INFO(); CKR rv = pkcs11Library.C_GetInfo(ref libraryInfo); if (rv != CKR.CKR_OK) { slotList = new NativeULong[0]; return(rv); } // Check whether library matches URI if (!Matches(pkcs11Uri, libraryInfo)) { slotList = new NativeULong[0]; return(CKR.CKR_OK); } // Get number of slots in first call NativeULong slotCount = 0; rv = pkcs11Library.C_GetSlotList(false, null, ref slotCount); if (rv != CKR.CKR_OK) { slotList = new NativeULong[0]; return(rv); } if (slotCount < 1) { slotList = new NativeULong[0]; return(CKR.CKR_OK); } // Allocate array for slot IDs NativeULong[] slots = new NativeULong[slotCount]; // Get slot IDs in second call rv = pkcs11Library.C_GetSlotList(tokenPresent, slots, ref slotCount); if (rv != CKR.CKR_OK) { slotList = new NativeULong[0]; return(rv); } // Shrink array if needed if (slots.Length != ConvertUtils.UInt64ToInt32(slotCount)) { Array.Resize(ref slots, ConvertUtils.UInt64ToInt32(slotCount)); } // Match slots with Pkcs11Uri foreach (NativeULong slot in slots) { CK_SLOT_INFO slotInfo = new CK_SLOT_INFO(); rv = pkcs11Library.C_GetSlotInfo(slot, ref slotInfo); if (rv != CKR.CKR_OK) { slotList = new NativeULong[0]; return(rv); } // Check whether slot matches URI if (Matches(pkcs11Uri, slotInfo, slot)) { if ((slotInfo.Flags & CKF.CKF_TOKEN_PRESENT) == CKF.CKF_TOKEN_PRESENT) { CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO(); rv = pkcs11Library.C_GetTokenInfo(slot, ref tokenInfo); if (rv != CKR.CKR_OK) { slotList = new NativeULong[0]; return(rv); } // Check whether token matches URI if (Matches(pkcs11Uri, tokenInfo)) { matchingSlots.Add(slot); } } else { if (!tokenPresent && Pkcs11UriSharedUtils.Matches(pkcs11Uri, null, null, null, null)) { matchingSlots.Add(slot); } } } } slotList = matchingSlots.ToArray(); return(CKR.CKR_OK); }
public void _01_EncryptAndDecryptSinglePartTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key NativeULong keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11Library, session, ref keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate random initialization vector byte[] iv = new byte[8]; rv = pkcs11Library.C_GenerateRandom(session, iv, ConvertUtils.UInt32FromInt32(iv.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify encryption mechanism with initialization vector as parameter. // Note that CkmUtils.CreateMechanism() automaticaly copies iv into newly allocated unmanaged memory. CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_DES3_CBC, iv); // Initialize encryption operation rv = pkcs11Library.C_EncryptInit(session, ref mechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = ConvertUtils.Utf8StringToBytes("Our new password"); // Get length of encrypted data in first call NativeULong encryptedDataLen = 0; rv = pkcs11Library.C_Encrypt(session, sourceData, ConvertUtils.UInt32FromInt32(sourceData.Length), null, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(encryptedDataLen > 0); // Allocate array for encrypted data byte[] encryptedData = new byte[encryptedDataLen]; // Get encrypted data in second call rv = pkcs11Library.C_Encrypt(session, sourceData, ConvertUtils.UInt32FromInt32(sourceData.Length), encryptedData, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with encrypted data // Initialize decryption operation rv = pkcs11Library.C_DecryptInit(session, ref mechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get length of decrypted data in first call NativeULong decryptedDataLen = 0; rv = pkcs11Library.C_Decrypt(session, encryptedData, ConvertUtils.UInt32FromInt32(encryptedData.Length), null, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(decryptedDataLen > 0); // Allocate array for decrypted data byte[] decryptedData = new byte[decryptedDataLen]; // Get decrypted data in second call rv = pkcs11Library.C_Decrypt(session, encryptedData, ConvertUtils.UInt32FromInt32(encryptedData.Length), decryptedData, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with decrypted data Assert.IsTrue(ConvertUtils.BytesToBase64String(sourceData) == ConvertUtils.BytesToBase64String(decryptedData)); // In LowLevelAPI we have to free unmanaged memory taken by mechanism parameter (iv in this case) UnmanagedMemory.Free(ref mechanism.Parameter); mechanism.ParameterLen = 0; rv = pkcs11Library.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
/// <summary> /// Creates the PKCS#1 v1.5 RSA signature with SHA-1 mechanism /// </summary> /// <param name="data">Data that should be signed</param> /// <param name="uri">PKCS#11 URI identifying PKCS#11 library, token and private key</param> /// <returns>PKCS#1 v1.5 RSA signature</returns> private byte[] SignData(byte[] data, string uri) { // Verify input parameters if (data == null) { throw new ArgumentNullException("data"); } if (string.IsNullOrEmpty(uri)) { throw new ArgumentNullException("uri"); } // Parse PKCS#11 URI Pkcs11Uri pkcs11Uri = new Pkcs11Uri(uri); // Verify that URI contains all information required to perform this operation if (pkcs11Uri.ModulePath == null) { throw new Exception("PKCS#11 URI does not specify PKCS#11 library"); } if (pkcs11Uri.PinValue == null) { throw new Exception("PKCS#11 URI does not specify PIN"); } if (!pkcs11Uri.DefinesObject || pkcs11Uri.Type != CKO.CKO_PRIVATE_KEY) { throw new Exception("PKCS#11 URI does not specify private key"); } // Load and initialize PKCS#11 library specified by URI CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(pkcs11Uri.ModulePath, true)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Obtain a list of all slots with tokens that match URI NativeULong[] slots = null; rv = Pkcs11UriUtils.GetMatchingSlotList(pkcs11Uri, pkcs11Library, true, out slots); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } if ((slots == null) || (slots.Length == 0)) { throw new Exception("None of the slots matches PKCS#11 URI"); } // Open read only session with first token that matches URI NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slots[0], (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user with PIN acquired from URI byte[] pinValue = ConvertUtils.Utf8StringToBytes(pkcs11Uri.PinValue); rv = pkcs11Library.C_Login(session, CKU.CKU_USER, pinValue, ConvertUtils.UInt64FromInt32(pinValue.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get list of object attributes for the private key specified by URI CK_ATTRIBUTE[] attributes = null; Pkcs11UriUtils.GetObjectAttributes(pkcs11Uri, out attributes); // Find private key specified by URI NativeULong foundObjectCount = 0; NativeULong[] foundObjectIds = new NativeULong[] { CK.CK_INVALID_HANDLE }; rv = pkcs11Library.C_FindObjectsInit(session, attributes, ConvertUtils.UInt64FromInt32(attributes.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_FindObjects(session, foundObjectIds, ConvertUtils.UInt64FromInt32(foundObjectIds.Length), ref foundObjectCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_FindObjectsFinal(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } if ((foundObjectCount == 0) || (foundObjectIds[0] == CK.CK_INVALID_HANDLE)) { throw new Exception("None of the private keys match PKCS#11 URI"); } // Create signature with the private key specified by URI CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA1_RSA_PKCS); rv = pkcs11Library.C_SignInit(session, ref mechanism, foundObjectIds[0]); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } NativeULong signatureLen = 0; rv = pkcs11Library.C_Sign(session, data, ConvertUtils.UInt64FromInt32(data.Length), null, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(signatureLen > 0); byte[] signature = new byte[signatureLen]; rv = pkcs11Library.C_Sign(session, data, ConvertUtils.UInt64FromInt32(data.Length), signature, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } if (signature.Length != ConvertUtils.UInt64ToInt32(signatureLen)) { Array.Resize(ref signature, ConvertUtils.UInt64ToInt32(signatureLen)); } // Release PKCS#11 resources rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } return(signature); } }
public void _02_DigestMultiPartTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify digesting mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA_1); byte[] sourceData = ConvertUtils.Utf8StringToBytes("Hello world"); byte[] digest = null; // Multipart digesting functions C_DigestUpdate and C_DigestFinal can be used i.e. for digesting of streamed data using (MemoryStream inputStream = new MemoryStream(sourceData)) { // Initialize digesting operation rv = pkcs11Library.C_DigestInit(session, ref mechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare buffer for source data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] part = new byte[8]; // Read input stream with source data int bytesRead = 0; while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0) { // Digest each individual source data part rv = pkcs11Library.C_DigestUpdate(session, part, ConvertUtils.UInt64FromInt32(bytesRead)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Get length of digest value in first call NativeULong digestLen = 0; rv = pkcs11Library.C_DigestFinal(session, null, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(digestLen > 0); // Allocate array for digest value digest = new byte[digestLen]; // Get digest value in second call rv = pkcs11Library.C_DigestFinal(session, digest, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Do something interesting with digest value rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicWrapAndUnwrapKeyTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate asymetric key pair NativeULong pubKeyId = CK.CK_INVALID_HANDLE; NativeULong privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11Library, session, ref pubKeyId, ref privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key NativeULong keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11Library, session, ref keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify wrapping mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS); // Get length of wrapped key in first call NativeULong wrappedKeyLen = 0; rv = pkcs11Library.C_WrapKey(session, ref mechanism, pubKeyId, keyId, null, ref wrappedKeyLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(wrappedKeyLen > 0); // Allocate array for wrapped key byte[] wrappedKey = new byte[wrappedKeyLen]; // Get wrapped key in second call rv = pkcs11Library.C_WrapKey(session, ref mechanism, pubKeyId, keyId, wrappedKey, ref wrappedKeyLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with wrapped key // Define attributes for unwrapped key CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[6]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY); template[1] = CkaUtils.CreateAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3); template[2] = CkaUtils.CreateAttribute(CKA.CKA_ENCRYPT, true); template[3] = CkaUtils.CreateAttribute(CKA.CKA_DECRYPT, true); template[4] = CkaUtils.CreateAttribute(CKA.CKA_DERIVE, true); template[5] = CkaUtils.CreateAttribute(CKA.CKA_EXTRACTABLE, true); // Unwrap key NativeULong unwrappedKeyId = 0; rv = pkcs11Library.C_UnwrapKey(session, ref mechanism, privKeyId, wrappedKey, wrappedKeyLen, template, ConvertUtils.UInt64FromInt32(template.Length), ref unwrappedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with unwrapped key rv = pkcs11Library.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicOperationStateTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); // Open RO (read-only) session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, CKF.CKF_SERIAL_SESSION, IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get length of state in first call NativeULong stateLen = 0; rv = pkcs11Library.C_GetOperationState(session, null, ref stateLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(stateLen > 0); // Allocate array for state byte[] state = new byte[stateLen]; // Get state in second call rv = pkcs11Library.C_GetOperationState(session, state, ref stateLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Let's set state so the test is complete rv = pkcs11Library.C_SetOperationState(session, state, ConvertUtils.UInt32FromInt32(state.Length), CK.CK_INVALID_HANDLE, CK.CK_INVALID_HANDLE); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _03_DigestKeyTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Login as normal user rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key NativeULong keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11Library, session, ref keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify digesting mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA_1); // Initialize digesting operation rv = pkcs11Library.C_DigestInit(session, ref mechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Digest key rv = pkcs11Library.C_DigestKey(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get length of digest value in first call NativeULong digestLen = 0; rv = pkcs11Library.C_DigestFinal(session, null, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(digestLen > 0); // Allocate array for digest value byte[] digest = new byte[digestLen]; // Get digest value in second call rv = pkcs11Library.C_DigestFinal(session, digest, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with digest value rv = pkcs11Library.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
/// <summary> /// Finds slot containing the token that matches criteria specified in Settings class /// </summary> /// <param name='pkcs11Library'>Initialized PKCS11 wrapper</param> /// <returns>Slot containing the token that matches criteria</returns> public static NativeULong GetUsableSlot(Pkcs11Library pkcs11Library) { CKR rv = CKR.CKR_OK; // Get list of available slots with token present NativeULong slotCount = 0; rv = pkcs11Library.C_GetSlotList(true, null, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(slotCount > 0); NativeULong[] slotList = new NativeULong[slotCount]; rv = pkcs11Library.C_GetSlotList(true, slotList, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Return first slot with token present when both TokenSerial and TokenLabel are null... if (Settings.TokenSerial == null && Settings.TokenLabel == null) { return(slotList[0]); } // First slot with token present is OK... NativeULong?matchingSlot = slotList[0]; // ...unless there are matching criteria specified in Settings class if (Settings.TokenSerial != null || Settings.TokenLabel != null) { matchingSlot = null; foreach (NativeULong slot in slotList) { CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO(); rv = pkcs11Library.C_GetTokenInfo(slot, ref tokenInfo); if (rv != CKR.CKR_OK) { if (rv == CKR.CKR_TOKEN_NOT_RECOGNIZED || rv == CKR.CKR_TOKEN_NOT_PRESENT) { continue; } else { Assert.Fail(rv.ToString()); } } if (!string.IsNullOrEmpty(Settings.TokenSerial)) { if (0 != string.Compare(Settings.TokenSerial, ConvertUtils.BytesToUtf8String(tokenInfo.SerialNumber, true), StringComparison.Ordinal)) { continue; } } if (!string.IsNullOrEmpty(Settings.TokenLabel)) { if (0 != string.Compare(Settings.TokenLabel, ConvertUtils.BytesToUtf8String(tokenInfo.Label, true), StringComparison.Ordinal)) { continue; } } matchingSlot = slot; break; } } Assert.IsTrue(matchingSlot != null, "Token matching criteria specified in Settings class is not present"); return(matchingSlot.Value); }
public void _01_DigestSinglePartTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11Library.C_Initialize(Settings.InitArgs81); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Find first slot with token present NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify digesting mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA_1); // Initialize digesting operation rv = pkcs11Library.C_DigestInit(session, ref mechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = ConvertUtils.Utf8StringToBytes("Hello world"); // Get length of digest value in first call NativeULong digestLen = 0; rv = pkcs11Library.C_Digest(session, sourceData, ConvertUtils.UInt64FromInt32(sourceData.Length), null, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(digestLen > 0); // Allocate array for digest value byte[] digest = new byte[digestLen]; // Get digest value in second call rv = pkcs11Library.C_Digest(session, sourceData, ConvertUtils.UInt64FromInt32(sourceData.Length), digest, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with digest value rv = pkcs11Library.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11Library.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }