/// <summary> /// Initializes new instance of Pkcs11Exception class with serialized data /// </summary> /// <param name="info">SerializationInfo that holds the serialized object data about the exception being thrown</param> /// <param name="context">StreamingContext that contains contextual information about the source or destination</param> protected Pkcs11Exception(SerializationInfo info, StreamingContext context) : base(info, context) { if (info != null) { _method = info.GetString("Method"); _rv = (CKR)info.GetUInt32("RV"); } }
public void _01_DigestSinglePartTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.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 = pkcs11.C_Digest(session, sourceData, ConvertUtils.UInt32FromInt32(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 = pkcs11.C_Digest(session, sourceData, ConvertUtils.UInt32FromInt32(sourceData.Length), digest, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with digest value rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_DigestMultiPartTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.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 = pkcs11.C_DigestUpdate(session, part, ConvertUtils.UInt32FromInt32(bytesRead)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Get length of digest value in first call NativeULong digestLen = 0; rv = pkcs11.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 = pkcs11.C_DigestFinal(session, digest, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Do something interesting with digest value rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_GenerateKeyPairTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, NativeLongUtils.ConvertFromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject byte[] ckaId = new byte[20]; rv = pkcs11.C_GenerateRandom(session, ckaId, NativeLongUtils.ConvertFromInt32(ckaId.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare attribute template of new public key CK_ATTRIBUTE[] pubKeyTemplate = new CK_ATTRIBUTE[10]; pubKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); pubKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, false); pubKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); pubKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_ID, ckaId); pubKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_ENCRYPT, true); pubKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_VERIFY, true); pubKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_VERIFY_RECOVER, true); pubKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_WRAP, true); pubKeyTemplate[8] = CkaUtils.CreateAttribute(CKA.CKA_MODULUS_BITS, 1024); pubKeyTemplate[9] = CkaUtils.CreateAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }); // Prepare attribute template of new private key CK_ATTRIBUTE[] privKeyTemplate = new CK_ATTRIBUTE[9]; privKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true); privKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, true); privKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName); privKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_ID, ckaId); privKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_SENSITIVE, true); privKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_DECRYPT, true); privKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_SIGN, true); privKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_SIGN_RECOVER, true); privKeyTemplate[8] = CkaUtils.CreateAttribute(CKA.CKA_UNWRAP, true); // Specify key generation mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN); // Generate key pair NativeULong pubKeyId = CK.CK_INVALID_HANDLE; NativeULong privKeyId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_GenerateKeyPair(session, ref mechanism, pubKeyTemplate, NativeLongUtils.ConvertFromInt32(pubKeyTemplate.Length), privKeyTemplate, NativeLongUtils.ConvertFromInt32(privKeyTemplate.Length), ref pubKeyId, ref privKeyId); 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 < privKeyTemplate.Length; i++) { UnmanagedMemory.Free(ref privKeyTemplate[i].value); privKeyTemplate[i].valueLen = 0; } for (int i = 0; i < pubKeyTemplate.Length; i++) { UnmanagedMemory.Free(ref pubKeyTemplate[i].value); pubKeyTemplate[i].valueLen = 0; } // Do something interesting with generated key pair // Destroy object rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicWrapAndUnwrapKeyTest() { if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 uint slotId = Helpers.GetUsableSlot(pkcs11); uint session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate asymetric key pair uint pubKeyId = CK.CK_INVALID_HANDLE; uint privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11, session, ref pubKeyId, ref privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key uint keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11, 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 uint wrappedKeyLen = 0; rv = pkcs11.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 = pkcs11.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 uint unwrappedKeyId = 0; rv = pkcs11.C_UnwrapKey(session, ref mechanism, privKeyId, wrappedKey, wrappedKeyLen, template, Convert.ToUInt32(template.Length), ref unwrappedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with unwrapped key rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _LL_25_26_03_KegKexp15KuznechikTwisted_Test() { if (Platform.NativeULongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (var pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath)) { // Инициализация библиотеки rv = pkcs11.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Установление соединения с Рутокен в первом доступном слоте NativeULong slotId = Helpers.GetUsableSlot(pkcs11); // Открытие RW сессии NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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()); } // Выполнение аутентификации пользователя rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Генерация параметра для структуры типа CK_VENDOR_GOST_KEG_PARAMS // для выработки двойственного ключа экспорта byte[] ukm = new byte[Settings.KEG_256_UKM_LENGTH]; rv = pkcs11.C_GenerateRandom(session, ukm, Convert.ToUInt32(ukm.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Генерация значения сессионного ключа byte[] sessionKeyValue = new byte[Settings.GOST_28147_KEY_SIZE]; rv = pkcs11.C_GenerateRandom(session, sessionKeyValue, Convert.ToUInt32(sessionKeyValue.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Генерация ключевой пары ГОСТ Р 34.10-2012(256) отправителя NativeULong senderPubKeyId = CK.CK_INVALID_HANDLE; NativeULong senderPrivKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateGost256KeyPair(pkcs11, session, ref senderPubKeyId, ref senderPrivKeyId, Settings.GostKeyPairId1); // Генерация ключевой пары ГОСТ Р 34.10-2012(256) получателя NativeULong recipientPubKeyId = CK.CK_INVALID_HANDLE; NativeULong recipientPrivKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateGost256KeyPair(pkcs11, session, ref recipientPubKeyId, ref recipientPrivKeyId, Settings.GostKeyPairId2); // Выработка общего ключа на стороне отправителя NativeULong senderDerivedKeyId = CK.CK_INVALID_HANDLE; Helpers.DeriveKuznechikTwin_GostR3410_12_Key(pkcs11, session, recipientPubKeyId, senderPrivKeyId, ukm, ref senderDerivedKeyId); // Шаблон для создания маскируемого ключа CK_ATTRIBUTE[] sessionKeyTemplate = new CK_ATTRIBUTE[9]; sessionKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY); sessionKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.WrappedKuznechikKeyLabel); sessionKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_KEY_TYPE, (CKK)Extended_CKK.CKK_KUZNECHIK); sessionKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, false); sessionKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_MODIFIABLE, true); sessionKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, true); sessionKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, sessionKeyValue); sessionKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_EXTRACTABLE, true); sessionKeyTemplate[8] = CkaUtils.CreateAttribute(CKA.CKA_SENSITIVE, false); // Выработка ключа, который будет замаскирован NativeULong sessionKeyId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_CreateObject(session, sessionKeyTemplate, Convert.ToUInt32(sessionKeyTemplate.Length), ref sessionKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(sessionKeyId != CK.CK_INVALID_HANDLE); // Генерация имитовставки для алгоритма экспорта ключей KExp15 byte[] kexp15Ukm = new byte[Settings.KEXP15_KUZNECHIK_TWIN_UKM_LENGTH]; rv = pkcs11.C_GenerateRandom(session, kexp15Ukm, Convert.ToUInt32(kexp15Ukm.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } CK_MECHANISM wrapMechanism = CkmUtils.CreateMechanism((NativeULong)Extended_CKM.CKM_KUZNECHIK_KEXP_15_WRAP, kexp15Ukm); // Получение длины маскированного ключа NativeULong wrappedKeyLen = 0; rv = pkcs11.C_WrapKey(session, ref wrapMechanism, senderDerivedKeyId, sessionKeyId, null, ref wrappedKeyLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(wrappedKeyLen > 0); byte[] wrappedKey = new byte[wrappedKeyLen]; // Маскирование ключа на общем ключе, выработанном на стороне отправителя rv = pkcs11.C_WrapKey(session, ref wrapMechanism, senderDerivedKeyId, sessionKeyId, wrappedKey, ref wrappedKeyLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Выработка общего ключа на стороне получателя NativeULong recipientDerivedKeyId = CK.CK_INVALID_HANDLE; Helpers.DeriveKuznechikTwin_GostR3410_12_Key(pkcs11, session, senderPubKeyId, recipientPrivKeyId, ukm, ref recipientDerivedKeyId); // Шаблон демаскированного ключа CK_ATTRIBUTE[] unwrappedKeyTemplate = new CK_ATTRIBUTE[8]; unwrappedKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY); unwrappedKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.UnwrappedGost28147_89KeyLabel); unwrappedKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_GOST28147); unwrappedKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, false); unwrappedKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_MODIFIABLE, true); unwrappedKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, false); unwrappedKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_EXTRACTABLE, true); unwrappedKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_SENSITIVE, false); // Демаскирование сессионного ключа с помощью общего выработанного // ключа на стороне получателя NativeULong unwrappedKeyId = 0; rv = pkcs11.C_UnwrapKey(session, ref wrapMechanism, recipientDerivedKeyId, wrappedKey, wrappedKeyLen, unwrappedKeyTemplate, Convert.ToUInt32(unwrappedKeyTemplate.Length), ref unwrappedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } CK_ATTRIBUTE[] valueTemplate = new CK_ATTRIBUTE[1]; valueTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_VALUE); valueTemplate[0].value = UnmanagedMemory.Allocate(Convert.ToInt32(32)); valueTemplate[0].valueLen = 32; rv = pkcs11.C_GetAttributeValue(session, unwrappedKeyId, valueTemplate, Convert.ToUInt32(valueTemplate.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Сравнение ключа byte[] unwrappedKey = UnmanagedMemory.Read(valueTemplate[0].value, Convert.ToInt32(valueTemplate[0].valueLen)); Assert.IsTrue(Convert.ToBase64String(sessionKeyValue) == Convert.ToBase64String(unwrappedKey)); // Освобождение выделенной памяти под аттрибуты for (int i = 0; i < valueTemplate.Length; i++) { UnmanagedMemory.Free(ref valueTemplate[i].value); valueTemplate[i].valueLen = 0; } for (int i = 0; i < sessionKeyTemplate.Length; i++) { UnmanagedMemory.Free(ref sessionKeyTemplate[i].value); sessionKeyTemplate[i].valueLen = 0; } for (int i = 0; i < unwrappedKeyTemplate.Length; i++) { UnmanagedMemory.Free(ref unwrappedKeyTemplate[i].value); unwrappedKeyTemplate[i].valueLen = 0; } // Удаляем созданные пары ключей rv = pkcs11.C_DestroyObject(session, senderPrivKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, senderPubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, recipientPrivKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, recipientPubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Удаляем сессионный ключ rv = pkcs11.C_DestroyObject(session, sessionKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Удаляем наследованные ключи rv = pkcs11.C_DestroyObject(session, senderDerivedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, recipientDerivedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Закрываем сессию rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicObjectFindingTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Let's create two objects so we can find something ulong objectId1 = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, session, ref objectId1); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } ulong objectId2 = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, 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 = pkcs11.C_FindObjectsInit(session, template, Convert.ToUInt64(template.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get search results ulong foundObjectCount = 0; ulong[] foundObjectIds = new ulong[2]; foundObjectIds[0] = CK.CK_INVALID_HANDLE; foundObjectIds[1] = CK.CK_INVALID_HANDLE; rv = pkcs11.C_FindObjects(session, foundObjectIds, Convert.ToUInt64(foundObjectIds.Length), ref foundObjectCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Terminate searching rv = pkcs11.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 = pkcs11.C_DestroyObject(session, objectId2); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, objectId1); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_SignAndVerifyMultiPartTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate asymetric key pair ulong pubKeyId = CK.CK_INVALID_HANDLE; ulong privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11, 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_SHA1_RSA_PKCS); byte[] sourceData = ConvertUtils.Utf8StringToBytes("Hello world"); byte[] signature = null; // Multipart signature functions C_SignUpdate and C_SignFinal can be used i.e. for signing of streamed data using (MemoryStream inputStream = new MemoryStream(sourceData)) { // Initialize signing operation rv = pkcs11.C_SignInit(session, ref mechanism, privKeyId); 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) { // Process each individual source data part rv = pkcs11.C_SignUpdate(session, part, Convert.ToUInt64(bytesRead)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Get the length of signature in first call ulong signatureLen = 0; rv = pkcs11.C_SignFinal(session, null, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(signatureLen > 0); // Allocate array for signature signature = new byte[signatureLen]; // Get signature in second call rv = pkcs11.C_SignFinal(session, signature, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Do something interesting with signature // Multipart verification functions C_VerifyUpdate and C_VerifyFinal can be used i.e. for signature verification of streamed data using (MemoryStream inputStream = new MemoryStream(sourceData)) { // Initialize verification operation rv = pkcs11.C_VerifyInit(session, ref mechanism, pubKeyId); 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) { // Process each individual source data part rv = pkcs11.C_VerifyUpdate(session, part, Convert.ToUInt64(bytesRead)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Verify signature rv = pkcs11.C_VerifyFinal(session, signature, Convert.ToUInt64(signature.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Do something interesting with verification result rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public byte[] ExtendedWrapKey( IMechanism generationMechanism, List <IObjectAttribute> keyAttributes, IMechanism derivationMechanism, IObjectHandle baseKey, IMechanism wrappingMechanism, ref IObjectHandle key) { if (this._disposed) { throw new ObjectDisposedException(this.GetType().FullName); } if (generationMechanism == null) { throw new ArgumentNullException(nameof(generationMechanism)); } if (derivationMechanism == null) { throw new ArgumentNullException(nameof(derivationMechanism)); } if (keyAttributes == null) { throw new ArgumentNullException(nameof(keyAttributes)); } if (baseKey == null) { throw new ArgumentNullException(nameof(baseKey)); } if (wrappingMechanism == null) { throw new ArgumentNullException(nameof(wrappingMechanism)); } var ckGenerationMechanism = new CK_MECHANISM() { Mechanism = (NativeULong)(generationMechanism.Type) }; var ckDerivationMechanism = new CK_MECHANISM() { Mechanism = (NativeULong)(derivationMechanism.Type) }; var ckWrappingMechanism = new CK_MECHANISM() { Mechanism = (NativeULong)(wrappingMechanism.Type) }; // Преобразование ObjectAttributes в CK_ATTRIBUTES CK_ATTRIBUTE[] ckKeyAttributes = null; NativeULong ckKeyAttributesLen = 0; ckKeyAttributes = new CK_ATTRIBUTE[keyAttributes.Count]; for (int i = 0; i < keyAttributes.Count; i++) { ckKeyAttributes[i] = (CK_ATTRIBUTE)keyAttributes[i].ToMarshalableStructure(); } ckKeyAttributesLen = (NativeULong)(keyAttributes.Count); // Получение длины wrapped key NativeULong generatedKey = CK.CK_INVALID_HANDLE; NativeULong wrappedKeyLen = 0; CKR rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_WrapKey(_sessionId, ref ckGenerationMechanism, ckKeyAttributes, ckKeyAttributesLen, ref ckDerivationMechanism, (NativeULong)(baseKey.ObjectId), ref ckWrappingMechanism, null, ref wrappedKeyLen, ref generatedKey); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_WrapKey", rv); } if (wrappedKeyLen <= 0) { throw new InvalidOperationException( "C_EX_WrapKey: invalid wrapped key length"); } // Маскирование ключа byte[] wrappedKey = new byte[wrappedKeyLen]; rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_WrapKey(_sessionId, ref ckGenerationMechanism, ckKeyAttributes, ckKeyAttributesLen, ref ckDerivationMechanism, (NativeULong)(baseKey.ObjectId), ref ckWrappingMechanism, wrappedKey, ref wrappedKeyLen, ref generatedKey); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_WrapKey", rv); } if (generatedKey == CK.CK_INVALID_HANDLE) { throw new InvalidOperationException("C_EX_WrapKey: invalid generated key handle"); } if ((NativeULong)wrappedKey.Length != wrappedKeyLen) { Array.Resize(ref wrappedKey, Convert.ToInt32(wrappedKeyLen)); } key = new Net.Pkcs11Interop.HighLevelAPI41.ObjectHandle(generatedKey); return(wrappedKey); }
public Pkcs7VerificationResult PKCS7Verify(byte[] cms, Stream inputStream, CkVendorX509Store vendorX509Store, VendorCrlMode mode, ulong flags) { if (this._disposed) { throw new ObjectDisposedException(this.GetType().FullName); } if (cms == null) { throw new ArgumentNullException(nameof(cms)); } if (vendorX509Store == null) { throw new ArgumentNullException(nameof(vendorX509Store)); } var storeNative = new LowLevelAPI41.CK_VENDOR_X509_STORE(vendorX509Store); var initialSignerSertificates = IntPtr.Zero; var signerSertificates = IntPtr.Zero; NativeULong signerSertificatesCount = 0; try { CKR rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_PKCS7VerifyInit(_sessionId, cms, ref storeNative, (NativeULong)(mode), (NativeULong)(flags)); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_PKCS7VerifyInit", rv); } byte[] part = new byte[inputStream.Length]; while (inputStream.Read(part, 0, part.Length) > 0) { rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_PKCS7VerifyUpdate(_sessionId, part); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_PKCS7VerifyUpdate", rv); } } rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_PKCS7VerifyFinal(_sessionId, out signerSertificates, out signerSertificatesCount); var result = new Pkcs7VerificationResult(); if (rv == CKR.CKR_OK) { result.Certificates = new List <byte[]>(); var structSize = Marshal.SizeOf(typeof(LowLevelAPI41.CK_VENDOR_BUFFER)); initialSignerSertificates = signerSertificates; for (NativeULong i = 0; i < signerSertificatesCount; i++) { var certificatePtr = (LowLevelAPI41.CK_VENDOR_BUFFER)Marshal.PtrToStructure(signerSertificates, typeof(LowLevelAPI41.CK_VENDOR_BUFFER)); signerSertificates += structSize; var certificateData = new byte[certificatePtr.Size]; Marshal.Copy(certificatePtr.Data, certificateData, 0, (int)certificatePtr.Size); result.Certificates.Add(certificateData); } result.IsValid = true; } else if (rv == CKR.CKR_SIGNATURE_INVALID) { result.IsValid = false; } else { throw new Pkcs11Exception("C_EX_PKCS7VerifyFinal", rv); } return(result); } finally { storeNative.Dispose(); if (initialSignerSertificates != IntPtr.Zero) { var structSize = Marshal.SizeOf(typeof(LowLevelAPI41.CK_VENDOR_BUFFER)); for (NativeULong i = 0; i < signerSertificatesCount; i++) { var certificatePtr = (LowLevelAPI41.CK_VENDOR_BUFFER)Marshal.PtrToStructure(initialSignerSertificates, typeof(LowLevelAPI41.CK_VENDOR_BUFFER)); initialSignerSertificates += structSize; CKR rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_FreeBuffer(certificatePtr.Data); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_FreeBuffer", rv); } } } } }
public byte[] SignInvisible( IMechanism mechanism, IObjectHandle keyHandle, byte[] data) { if (this._disposed) { throw new ObjectDisposedException(this.GetType().FullName); } if (mechanism == null) { throw new ArgumentNullException(nameof(mechanism)); } if (keyHandle == null) { throw new ArgumentNullException(nameof(keyHandle)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } var ckMechanism = new CK_MECHANISM() { Mechanism = (NativeULong)(mechanism.Type) }; CKR rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_SignInvisibleInit(_sessionId, ref ckMechanism, (NativeULong)(keyHandle.ObjectId)); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_SignInvisibleInit", rv); } NativeULong signatureLen = 0; rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_SignInvisible(_sessionId, data, (NativeULong)(data.Length), null, ref signatureLen); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_SignInvisible", rv); } if (signatureLen <= 0) { throw new InvalidOperationException( "C_EX_SignInvisible: invalid signature length"); } byte[] signature = new byte[signatureLen]; rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_SignInvisible(_sessionId, data, (NativeULong)(data.Length), signature, ref signatureLen); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_SignInvisible", rv); } if ((NativeULong)signature.Length != signatureLen) { Array.Resize(ref signature, Convert.ToInt32(signatureLen)); } return(signature); }
public void _LL_30_01_SignJournalTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (RutokenPkcs11Library pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs80); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Установление соединения с Рутокен в первом доступном слоте NativeULong slotId = Helpers.GetUsableSlot(pkcs11); // Открытие RW сессии NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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()); } // Выполнение аутентификации пользователя rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Инициализация хэш-функции CK_MECHANISM digestMechanism = CkmUtils.CreateMechanism((CKM)Extended_CKM.CKM_GOSTR3411_12_512); rv = pkcs11.C_DigestInit(session, ref digestMechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = TestData.Digest_Gost3411_SourceData; // Определение размера хэш-кода NativeULong dataDigestLen = 0; rv = pkcs11.C_Digest(session, sourceData, Convert.ToUInt64(sourceData.Length), null, ref dataDigestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(dataDigestLen > 0); // Вычисление хэш-кода данных byte[] dataDigest = new byte[dataDigestLen]; rv = pkcs11.C_Digest(session, sourceData, Convert.ToUInt64(sourceData.Length), dataDigest, ref dataDigestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Генерация ключевой пары ГОСТ Р 34.10-2012 NativeULong dataPublicKeyId = CK.CK_INVALID_HANDLE; NativeULong dataPrivateKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateGost512KeyPair(pkcs11, session, ref dataPublicKeyId, ref dataPrivateKeyId, Settings.Gost512KeyPairId1); // Инициализация операции подписи данных по алгоритму ГОСТ Р 34.10-2012 CK_MECHANISM signMechanism = CkmUtils.CreateMechanism((CKM)Extended_CKM.CKM_GOSTR3410_512); rv = pkcs11.C_SignInit(session, ref signMechanism, dataPrivateKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Определение размера подписи данных NativeULong signatureLen = 0; rv = pkcs11.C_Sign(session, dataDigest, Convert.ToUInt64(dataDigest.Length), null, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(signatureLen > 0); byte[] signature = new byte[signatureLen]; // Подпись данных rv = pkcs11.C_Sign(session, dataDigest, Convert.ToUInt64(dataDigest.Length), signature, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Инициализация проверки подписи по алгоритму ГОСТ Р 34.10-2012 rv = pkcs11.C_VerifyInit(session, ref signMechanism, dataPublicKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Проверить подпись для данных rv = pkcs11.C_Verify(session, dataDigest, Convert.ToUInt64(dataDigest.Length), signature, Convert.ToUInt64(signature.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Получение длины журнала операций NativeULong journalLen = 0; rv = pkcs11.C_EX_GetJournal(slotId, null, ref journalLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(journalLen > 0); // Получение журнала операций byte[] journal = new byte[journalLen]; rv = pkcs11.C_EX_GetJournal(slotId, journal, ref journalLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Генерация ключевой пары ГОСТ Р 34.10-2012 для подписи журнала NativeULong journalPublicKeyId = CK.CK_INVALID_HANDLE; NativeULong journalPrivateKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateGost512JournalKeyPair( pkcs11, session, ref journalPublicKeyId, ref journalPrivateKeyId); // Инициализация хэш-функции rv = pkcs11.C_DigestInit(session, ref digestMechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Определение размера хэш-кода для журнала NativeULong journalDigestLen = 0; rv = pkcs11.C_Digest(session, journal, Convert.ToUInt64(journal.Length), null, ref journalDigestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(journalDigestLen > 0); // Вычисление хэш-кода журнала byte[] journalDigest = new byte[journalDigestLen]; rv = pkcs11.C_Digest(session, journal, Convert.ToUInt64(journal.Length), journalDigest, ref journalDigestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Инициализация операции подписи данных по алгоритму ГОСТ Р 34.10-2012 rv = pkcs11.C_SignInit(session, ref signMechanism, journalPrivateKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Определение размера подписи журнала NativeULong journalSignatureLen = 0; rv = pkcs11.C_Sign(session, journalDigest, Convert.ToUInt64(journalDigest.Length), null, ref journalSignatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(journalSignatureLen > 0); byte[] journalSignature = new byte[journalSignatureLen]; // Подпись журнала rv = pkcs11.C_Sign(session, journalDigest, Convert.ToUInt64(journalDigest.Length), journalSignature, ref journalSignatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Инициализация проверки подписи по алгоритму ГОСТ Р 34.10-2012 rv = pkcs11.C_VerifyInit(session, ref signMechanism, journalPublicKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Проверить подпись журнала rv = pkcs11.C_Verify(session, journalDigest, Convert.ToUInt64(journalDigest.Length), journalSignature, Convert.ToUInt64(journalSignature.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Уничтожение созданных ключей rv = pkcs11.C_DestroyObject(session, dataPrivateKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, dataPublicKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_BasicDigestEncryptAndDecryptDigestTest() { 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()); } // Generate random initialization vector byte[] iv = new byte[8]; rv = pkcs11Library.C_GenerateRandom(session, iv, ConvertUtils.UInt64FromInt32(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 encryptionMechanism = CkmUtils.CreateMechanism(CKM.CKM_DES3_CBC, iv); // Specify digesting mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM digestingMechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA_1); byte[] sourceData = ConvertUtils.Utf8StringToBytes("Our new password"); byte[] encryptedData = null; byte[] digest1 = null; byte[] decryptedData = null; byte[] digest2 = null; // Multipart digesting and encryption function C_DigestEncryptUpdate can be used i.e. for digesting and encryption of streamed data using (MemoryStream inputStream = new MemoryStream(sourceData), outputStream = new MemoryStream()) { // Initialize digesting operation rv = pkcs11Library.C_DigestInit(session, ref digestingMechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Initialize encryption operation rv = pkcs11Library.C_EncryptInit(session, ref encryptionMechanism, keyId); 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]; // Prepare buffer for encrypted data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] encryptedPart = new byte[8]; NativeULong encryptedPartLen = ConvertUtils.UInt64FromInt32(encryptedPart.Length); // Read input stream with source data int bytesRead = 0; while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0) { // Process each individual source data part encryptedPartLen = ConvertUtils.UInt64FromInt32(encryptedPart.Length); rv = pkcs11Library.C_DigestEncryptUpdate(session, part, ConvertUtils.UInt64FromInt32(bytesRead), encryptedPart, ref encryptedPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append encrypted data part to the output stream outputStream.Write(encryptedPart, 0, ConvertUtils.UInt64ToInt32(encryptedPartLen)); } // 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 digest1 = new byte[digestLen]; // Get digest value in second call rv = pkcs11Library.C_DigestFinal(session, digest1, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get the length of last encrypted data part in first call byte[] lastEncryptedPart = null; NativeULong lastEncryptedPartLen = 0; rv = pkcs11Library.C_EncryptFinal(session, null, ref lastEncryptedPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Allocate array for the last encrypted data part lastEncryptedPart = new byte[lastEncryptedPartLen]; // Get the last encrypted data part in second call rv = pkcs11Library.C_EncryptFinal(session, lastEncryptedPart, ref lastEncryptedPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append the last encrypted data part to the output stream outputStream.Write(lastEncryptedPart, 0, ConvertUtils.UInt64ToInt32(lastEncryptedPartLen)); // Read whole output stream to the byte array so we can compare results more easily encryptedData = outputStream.ToArray(); } // Do something interesting with encrypted data and digest // Multipart decryption and digesting function C_DecryptDigestUpdate can be used i.e. for digesting and decryption of streamed data using (MemoryStream inputStream = new MemoryStream(encryptedData), outputStream = new MemoryStream()) { // Initialize decryption operation rv = pkcs11Library.C_DecryptInit(session, ref encryptionMechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Initialize digesting operation rv = pkcs11Library.C_DigestInit(session, ref digestingMechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare buffer for encrypted data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] encryptedPart = new byte[8]; // Prepare buffer for decrypted data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] part = new byte[8]; NativeULong partLen = ConvertUtils.UInt64FromInt32(part.Length); // Read input stream with encrypted data int bytesRead = 0; while ((bytesRead = inputStream.Read(encryptedPart, 0, encryptedPart.Length)) > 0) { // Process each individual encrypted data part partLen = ConvertUtils.UInt64FromInt32(part.Length); rv = pkcs11Library.C_DecryptDigestUpdate(session, encryptedPart, ConvertUtils.UInt64FromInt32(bytesRead), part, ref partLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append decrypted data part to the output stream outputStream.Write(part, 0, ConvertUtils.UInt64ToInt32(partLen)); } // Get the length of last decrypted data part in first call byte[] lastPart = null; NativeULong lastPartLen = 0; rv = pkcs11Library.C_DecryptFinal(session, null, ref lastPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Allocate array for the last decrypted data part lastPart = new byte[lastPartLen]; // Get the last decrypted data part in second call rv = pkcs11Library.C_DecryptFinal(session, lastPart, ref lastPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append the last decrypted data part to the output stream outputStream.Write(lastPart, 0, ConvertUtils.UInt64ToInt32(lastPartLen)); // Read whole output stream to the byte array so we can compare results more easily decryptedData = outputStream.ToArray(); // 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 digest2 = new byte[digestLen]; // Get digest value in second call rv = pkcs11Library.C_DigestFinal(session, digest2, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } // Do something interesting with decrypted data and digest Assert.IsTrue(ConvertUtils.BytesToBase64String(sourceData) == ConvertUtils.BytesToBase64String(decryptedData)); Assert.IsTrue(ConvertUtils.BytesToBase64String(digest1) == ConvertUtils.BytesToBase64String(digest2)); // In LowLevelAPI we have to free unmanaged memory taken by mechanism parameter (iv in this case) UnmanagedMemory.Free(ref encryptionMechanism.Parameter); encryptionMechanism.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()); } } }
public void _01_BasicInitTokenAndPinTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO(); rv = pkcs11.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 = pkcs11.C_InitToken(slotId, Settings.SecurityOfficerPinArray, NativeLongUtils.ConvertFromInt32(Settings.SecurityOfficerPinArray.Length), label); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Open RW session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_SO, Settings.SecurityOfficerPinArray, NativeLongUtils.ConvertFromInt32(Settings.SecurityOfficerPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Initialize user pin rv = pkcs11.C_InitPIN(session, Settings.NormalUserPinArray, NativeLongUtils.ConvertFromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _LL_20_08_EncryptAndDecrypt_Magma_CTR_ACPKM_Test() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (RutokenPkcs11Library pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs41); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Установление соединения с Рутокен в первом доступном слоте NativeULong slotId = Helpers.GetUsableSlot(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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()); } // Выполнение аутентификации пользователя rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Генерация ключа для симметричного шифрования NativeULong keyId = CK.CK_INVALID_HANDLE; Helpers.GenerateMagmaKey(pkcs11, session, ref keyId); var random = new Random(); byte[] initVector = new byte[Settings.MAGMA_BLOCK_SIZE / 2]; random.NextBytes(initVector); byte[] mechaismParams = new byte[Settings.CTR_ACPKM_PERIOD_SIZE + Settings.MAGMA_BLOCK_SIZE / 2]; mechaismParams[0] = 0x01; mechaismParams[1] = 0x00; mechaismParams[2] = 0x00; mechaismParams[3] = 0x00; Array.Copy(initVector, 0, mechaismParams, Settings.CTR_ACPKM_PERIOD_SIZE, initVector.Length); CK_MECHANISM mechanism = CkmUtils.CreateMechanism((NativeULong)Extended_CKM.CKM_MAGMA_CTR_ACPKM, mechaismParams); // Инициализация операции шифрования rv = pkcs11.C_EncryptInit(session, ref mechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = TestData.Encrypt_Gost28147_89_ECB_SourceData; // Получение длины массива с зашифрованными данными NativeULong encryptedDataLen = 0; rv = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(sourceData.Length), null, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(encryptedDataLen > 0); // Выделение памяти для массива с зашифрованными данными byte[] encryptedData = new byte[encryptedDataLen]; // Получение зашифрованных данных rv = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(sourceData.Length), encryptedData, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Инициализация операции расишфрования rv = pkcs11.C_DecryptInit(session, ref mechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Получение длины массива с расшифрованными данными NativeULong decryptedDataLen = 0; rv = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(encryptedData.Length), null, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(decryptedDataLen > 0); // Выделение памяти для массива с расшифрованными данными byte[] decryptedData = new byte[decryptedDataLen]; // Получение расшифрованных данных rv = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(encryptedData.Length), decryptedData, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(Convert.ToBase64String(sourceData) == Convert.ToBase64String(decryptedData)); rv = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _LL_20_04_EncryptAndDecrypt_RSA_Test() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (RutokenPkcs11Library pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath)) { rv = pkcs11.C_Initialize(Settings.InitArgs41); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Установление соединения с Рутокен в первом доступном слоте NativeULong slotId = Helpers.GetUsableSlot(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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()); } // Выполнение аутентификации пользователя rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Генерация ключей для RSA шифрования NativeULong privateKeyId = CK.CK_INVALID_HANDLE; NativeULong publicKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateRSAKeyPair(pkcs11, session, ref publicKeyId, ref privateKeyId, Settings.RsaKeyPairId); CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS); // Инициализация операции шифрования rv = pkcs11.C_EncryptInit(session, ref mechanism, publicKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = TestData.Encrypt_RSA_SourceData; // Получение длины массива с зашифрованными данными NativeULong encryptedDataLen = 0; rv = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(sourceData.Length), null, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(encryptedDataLen > 0); // Выделение памяти для массива с зашифрованными данными byte[] encryptedData = new byte[encryptedDataLen]; // Получение зашифрованных данных rv = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(sourceData.Length), encryptedData, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Инициализация операции расишфрования rv = pkcs11.C_DecryptInit(session, ref mechanism, privateKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Получение длины массива с расшифрованными данными NativeULong decryptedDataLen = 0; rv = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(encryptedData.Length), null, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(decryptedDataLen > 0); // Выделение памяти для массива с расшифрованными данными byte[] decryptedData = new byte[decryptedDataLen]; // Получение расшифрованных данных rv = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(encryptedData.Length), decryptedData, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(Convert.ToBase64String(sourceData) == Convert.ToBase64String(decryptedData)); // Уничтожение созданных ключей rv = pkcs11.C_DestroyObject(session, privateKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, publicKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Завершение сессии rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.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='pkcs11'>Initialized PKCS11 wrapper</param> /// <returns>Slot containing the token that matches criteria</returns> public static ulong GetUsableSlot(Pkcs11 pkcs11) { CKR rv = CKR.CKR_OK; // Get list of available slots with token present ulong slotCount = 0; rv = pkcs11.C_GetSlotList(true, null, ref slotCount); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(slotCount > 0); ulong[] slotList = new ulong[slotCount]; rv = pkcs11.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... ulong?matchingSlot = slotList[0]; // ...unless there are matching criteria specified in Settings class if (Settings.TokenSerial != null || Settings.TokenLabel != null) { matchingSlot = null; foreach (uint slot in slotList) { CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO(); rv = pkcs11.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 IObjectHandle ExtendedUnwrapKey( IMechanism derivationMechanism, IObjectHandle baseKey, IMechanism unwrappingMechanism, byte[] wrappedKey, List <IObjectAttribute> keyAttributes) { if (this._disposed) { throw new ObjectDisposedException(this.GetType().FullName); } if (derivationMechanism == null) { throw new ArgumentNullException(nameof(derivationMechanism)); } if (baseKey == null) { throw new ArgumentNullException(nameof(baseKey)); } if (unwrappingMechanism == null) { throw new ArgumentNullException(nameof(unwrappingMechanism)); } if (wrappedKey == null) { throw new ArgumentNullException(nameof(wrappedKey)); } if (keyAttributes == null) { throw new ArgumentNullException(nameof(keyAttributes)); } var ckDerivationMechanism = new CK_MECHANISM() { Mechanism = (NativeULong)(derivationMechanism.Type) }; var ckUnwrappingMechanism = new CK_MECHANISM() { Mechanism = (NativeULong)(unwrappingMechanism.Type) }; // Преобразование ObjectAttributes в CK_ATTRIBUTES CK_ATTRIBUTE[] ckKeyAttributes = null; NativeULong ckKeyAttributesLen = 0; ckKeyAttributes = new CK_ATTRIBUTE[keyAttributes.Count]; for (int i = 0; i < keyAttributes.Count; i++) { ckKeyAttributes[i] = (CK_ATTRIBUTE)keyAttributes[i].ToMarshalableStructure(); } ckKeyAttributesLen = (NativeULong)(keyAttributes.Count); // Размаскирование ключа NativeULong unwrappedKey = CK.CK_INVALID_HANDLE; CKR rv = ((LowLevelAPI41.RutokenPkcs11Library)_pkcs11Library).C_EX_UnwrapKey(_sessionId, ref ckDerivationMechanism, (NativeULong)(baseKey.ObjectId), ref ckUnwrappingMechanism, wrappedKey, (NativeULong)wrappedKey.Length, ckKeyAttributes, ckKeyAttributesLen, ref unwrappedKey); if (rv != CKR.CKR_OK) { throw new Pkcs11Exception("C_EX_WrapKey", rv); } if (unwrappedKey == CK.CK_INVALID_HANDLE) { throw new InvalidOperationException("C_EX_WrapKey: invalid unwrapped key handle"); } return(new Net.Pkcs11Interop.HighLevelAPI41.ObjectHandle(unwrappedKey)); }
public void _01_SignAndVerifySinglePartTest() { if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 ulong slotId = Helpers.GetUsableSlot(pkcs11); ulong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate asymetric key pair ulong pubKeyId = CK.CK_INVALID_HANDLE; ulong privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11, 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_SHA1_RSA_PKCS); // Initialize signing operation rv = pkcs11.C_SignInit(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 ulong signatureLen = 0; rv = pkcs11.C_Sign(session, sourceData, Convert.ToUInt64(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 = pkcs11.C_Sign(session, sourceData, Convert.ToUInt64(sourceData.Length), signature, ref signatureLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with signature // Initialize verification operation rv = pkcs11.C_VerifyInit(session, ref mechanism, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Verify signature rv = pkcs11.C_Verify(session, sourceData, Convert.ToUInt64(sourceData.Length), signature, Convert.ToUInt64(signature.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with verification result rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _03_GetObjectSizeTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.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(pkcs11, session, ref objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Determine object size NativeULong objectSize = 0; rv = pkcs11.C_GetObjectSize(session, objectId, ref objectSize); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(objectSize > 0); rv = pkcs11.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _LL_25_26_02_DeriveAndWrap_VKO_Gost3410_12_Test() { if (Platform.NativeULongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (RutokenPkcs11Library pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath)) { // Инициализация библиотеки rv = pkcs11.C_Initialize(Settings.InitArgs40); if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED)) { Assert.Fail(rv.ToString()); } // Установление соединения с Рутокен в первом доступном слоте NativeULong slotId = Helpers.GetUsableSlot(pkcs11); // Открытие RW сессии NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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()); } // Выполнение аутентификации пользователя rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Генерация параметра для структуры типа CK_GOSTR3410_DERIVE_PARAMS // для выработки общего ключа byte[] ukm = new byte[Settings.UKM_LENGTH]; rv = pkcs11.C_GenerateRandom(session, ukm, Convert.ToUInt32(ukm.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Генерация значения сессионного ключа byte[] sessionKeyValue = new byte[Settings.GOST_28147_KEY_SIZE]; rv = pkcs11.C_GenerateRandom(session, sessionKeyValue, Convert.ToUInt32(sessionKeyValue.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Генерация ключевой пары ГОСТ Р 34.10-2012 отправителя NativeULong senderPubKeyId = CK.CK_INVALID_HANDLE; NativeULong senderPrivKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateGost512KeyPair(pkcs11, session, ref senderPubKeyId, ref senderPrivKeyId, Settings.Gost512KeyPairId1); // Генерация ключевой пары ГОСТ Р 34.10-2012 получателя NativeULong recipientPubKeyId = CK.CK_INVALID_HANDLE; NativeULong recipientPrivKeyId = CK.CK_INVALID_HANDLE; Helpers.GenerateGost512KeyPair(pkcs11, session, ref recipientPubKeyId, ref recipientPrivKeyId, Settings.Gost512KeyPairId2); // Выработка общего ключа на стороне отправителя NativeULong senderDerivedKeyId = CK.CK_INVALID_HANDLE; Helpers.Derive_GostR3410_12_Key(pkcs11, session, recipientPubKeyId, senderPrivKeyId, ukm, ref senderDerivedKeyId); // Шаблон для создания маскируемого ключа CK_ATTRIBUTE[] sessionKeyTemplate = new CK_ATTRIBUTE[9]; sessionKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY); sessionKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.WrappedGost28147_89KeyLabel); sessionKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_GOST28147); sessionKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, false); sessionKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_MODIFIABLE, true); sessionKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, true); sessionKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, sessionKeyValue); sessionKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_EXTRACTABLE, true); sessionKeyTemplate[8] = CkaUtils.CreateAttribute(CKA.CKA_SENSITIVE, false); // Выработка ключа, который будет замаскирован NativeULong sessionKeyId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_CreateObject(session, sessionKeyTemplate, Convert.ToUInt32(sessionKeyTemplate.Length), ref sessionKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(sessionKeyId != CK.CK_INVALID_HANDLE); // Определение параметров механизма маскирования // В LowLevelAPI выделенная для параметров память должны быть освобождена после использования CK_KEY_DERIVATION_STRING_DATA wrapMechanismParams = new CK_KEY_DERIVATION_STRING_DATA(); wrapMechanismParams.Data = UnmanagedMemory.Allocate(ukm.Length); UnmanagedMemory.Write(wrapMechanismParams.Data, ukm); wrapMechanismParams.Len = Convert.ToUInt32(ukm.Length); CK_MECHANISM wrapMechanism = CkmUtils.CreateMechanism(CKM.CKM_GOST28147_KEY_WRAP, wrapMechanismParams); // Получение длины маскированного ключа NativeULong wrappedKeyLen = 0; rv = pkcs11.C_WrapKey(session, ref wrapMechanism, senderDerivedKeyId, sessionKeyId, null, ref wrappedKeyLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(wrappedKeyLen > 0); byte[] wrappedKey = new byte[wrappedKeyLen]; // Маскирование ключа на общем ключе, выработанном на стороне отправителя rv = pkcs11.C_WrapKey(session, ref wrapMechanism, senderDerivedKeyId, sessionKeyId, wrappedKey, ref wrappedKeyLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Выработка общего ключа на стороне получателя NativeULong recipientDerivedKeyId = CK.CK_INVALID_HANDLE; Helpers.Derive_GostR3410_12_Key(pkcs11, session, senderPubKeyId, recipientPrivKeyId, ukm, ref recipientDerivedKeyId); // Шаблон демаскированного ключа CK_ATTRIBUTE[] unwrappedKeyTemplate = new CK_ATTRIBUTE[8]; unwrappedKeyTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY); unwrappedKeyTemplate[1] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.UnwrappedGost28147_89KeyLabel); unwrappedKeyTemplate[2] = CkaUtils.CreateAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_GOST28147); unwrappedKeyTemplate[3] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, false); unwrappedKeyTemplate[4] = CkaUtils.CreateAttribute(CKA.CKA_MODIFIABLE, true); unwrappedKeyTemplate[5] = CkaUtils.CreateAttribute(CKA.CKA_PRIVATE, false); unwrappedKeyTemplate[6] = CkaUtils.CreateAttribute(CKA.CKA_EXTRACTABLE, true); unwrappedKeyTemplate[7] = CkaUtils.CreateAttribute(CKA.CKA_SENSITIVE, false); // Демаскирование сессионного ключа с помощью общего выработанного // ключа на стороне получателя NativeULong unwrappedKeyId = 0; rv = pkcs11.C_UnwrapKey(session, ref wrapMechanism, recipientDerivedKeyId, wrappedKey, wrappedKeyLen, unwrappedKeyTemplate, Convert.ToUInt32(unwrappedKeyTemplate.Length), ref unwrappedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } CK_ATTRIBUTE[] valueTemplate = new CK_ATTRIBUTE[1]; valueTemplate[0] = CkaUtils.CreateAttribute(CKA.CKA_VALUE); // In LowLevelAPI we have to allocate unmanaged memory for attribute value valueTemplate[0].value = UnmanagedMemory.Allocate(Convert.ToInt32(32)); valueTemplate[0].valueLen = 32; // Get attribute value in second call rv = pkcs11.C_GetAttributeValue(session, unwrappedKeyId, valueTemplate, Convert.ToUInt32(valueTemplate.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Сравнение ключа byte[] unwrappedKey = UnmanagedMemory.Read(valueTemplate[0].value, Convert.ToInt32(valueTemplate[0].valueLen)); Assert.IsTrue(Convert.ToBase64String(sessionKeyValue) == Convert.ToBase64String(unwrappedKey)); // Освобождение выделенной памяти для параметров механизма UnmanagedMemory.Free(ref wrapMechanismParams.Data); wrapMechanismParams.Len = 0; UnmanagedMemory.Free(ref wrapMechanism.Parameter); wrapMechanism.ParameterLen = 0; // Удаляем созданные пары ключей rv = pkcs11.C_DestroyObject(session, senderPrivKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, senderPubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, recipientPrivKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, recipientPubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Удаляем сессионный ключ rv = pkcs11.C_DestroyObject(session, sessionKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Удаляем наследованные ключи rv = pkcs11.C_DestroyObject(session, senderDerivedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, recipientDerivedKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Закрываем сессию rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.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 (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.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 = pkcs11.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 = pkcs11.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.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="pkcs11">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, Pkcs11 pkcs11, bool tokenPresent, out NativeULong[] slotList) { if (pkcs11Uri == null) { throw new ArgumentNullException("pkcs11Uri"); } if (pkcs11 == null) { throw new ArgumentNullException("pkcs11"); } List <NativeULong> matchingSlots = new List <NativeULong>(); // Get library information CK_INFO libraryInfo = new CK_INFO(); CKR rv = pkcs11.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 = pkcs11.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 = pkcs11.C_GetSlotList(tokenPresent, slots, ref slotCount); if (rv != CKR.CKR_OK) { slotList = new NativeULong[0]; return(rv); } // Shrink array if needed if (slots.Length != NativeLongUtils.ConvertToInt32(slotCount)) { Array.Resize(ref slots, NativeLongUtils.ConvertToInt32(slotCount)); } // Match slots with Pkcs11Uri foreach (NativeULong slot in slots) { CK_SLOT_INFO slotInfo = new CK_SLOT_INFO(); rv = pkcs11.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 = pkcs11.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 _02_EncryptAndDecryptMultiPartTest() { if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 uint slotId = Helpers.GetUsableSlot(pkcs11); uint session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key uint keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11, session, ref keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate random initialization vector byte[] iv = new byte[8]; rv = pkcs11.C_GenerateRandom(session, iv, Convert.ToUInt32(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); byte[] sourceData = ConvertUtils.Utf8StringToBytes("Our new password"); byte[] encryptedData = null; byte[] decryptedData = null; // Multipart encryption functions C_EncryptUpdate and C_EncryptFinal can be used i.e. for encryption of streamed data using (MemoryStream inputStream = new MemoryStream(sourceData), outputStream = new MemoryStream()) { // Initialize encryption operation rv = pkcs11.C_EncryptInit(session, ref mechanism, keyId); 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]; // Prepare buffer for encrypted data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] encryptedPart = new byte[8]; uint encryptedPartLen = Convert.ToUInt32(encryptedPart.Length); // Read input stream with source data int bytesRead = 0; while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0) { // Encrypt each individual source data part encryptedPartLen = Convert.ToUInt32(encryptedPart.Length); rv = pkcs11.C_EncryptUpdate(session, part, Convert.ToUInt32(bytesRead), encryptedPart, ref encryptedPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append encrypted data part to the output stream outputStream.Write(encryptedPart, 0, Convert.ToInt32(encryptedPartLen)); } // Get the length of last encrypted data part in first call byte[] lastEncryptedPart = null; uint lastEncryptedPartLen = 0; rv = pkcs11.C_EncryptFinal(session, null, ref lastEncryptedPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Allocate array for the last encrypted data part lastEncryptedPart = new byte[lastEncryptedPartLen]; // Get the last encrypted data part in second call rv = pkcs11.C_EncryptFinal(session, lastEncryptedPart, ref lastEncryptedPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append the last encrypted data part to the output stream outputStream.Write(lastEncryptedPart, 0, Convert.ToInt32(lastEncryptedPartLen)); // Read whole output stream to the byte array so we can compare results more easily encryptedData = outputStream.ToArray(); } // Do something interesting with encrypted data // Multipart decryption functions C_DecryptUpdate and C_DecryptFinal can be used i.e. for decryption of streamed data using (MemoryStream inputStream = new MemoryStream(encryptedData), outputStream = new MemoryStream()) { // Initialize decryption operation rv = pkcs11.C_DecryptInit(session, ref mechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare buffer for encrypted data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] encryptedPart = new byte[8]; // Prepare buffer for decrypted data part // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long byte[] part = new byte[8]; uint partLen = Convert.ToUInt32(part.Length); // Read input stream with encrypted data int bytesRead = 0; while ((bytesRead = inputStream.Read(encryptedPart, 0, encryptedPart.Length)) > 0) { // Decrypt each individual encrypted data part partLen = Convert.ToUInt32(part.Length); rv = pkcs11.C_DecryptUpdate(session, encryptedPart, Convert.ToUInt32(bytesRead), part, ref partLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append decrypted data part to the output stream outputStream.Write(part, 0, Convert.ToInt32(partLen)); } // Get the length of last decrypted data part in first call byte[] lastPart = null; uint lastPartLen = 0; rv = pkcs11.C_DecryptFinal(session, null, ref lastPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Allocate array for the last decrypted data part lastPart = new byte[lastPartLen]; // Get the last decrypted data part in second call rv = pkcs11.C_DecryptFinal(session, lastPart, ref lastPartLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Append the last decrypted data part to the output stream outputStream.Write(lastPart, 0, Convert.ToInt32(lastPartLen)); // Read whole output stream to the byte array so we can compare results more easily decryptedData = outputStream.ToArray(); } // Do something interesting with decrypted data Assert.IsTrue(Convert.ToBase64String(sourceData) == Convert.ToBase64String(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 = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.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 (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); // Open RW session NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, NativeLongUtils.ConvertFromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key NativeULong baseKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11, 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 = pkcs11.C_GenerateRandom(session, data, NativeLongUtils.ConvertFromInt32(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 = NativeLongUtils.ConvertFromInt32(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 = pkcs11.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 = pkcs11.C_DestroyObject(session, baseKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, derivedKey); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_EncryptAndDecryptSinglePartTest() { if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 uint slotId = Helpers.GetUsableSlot(pkcs11); uint session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key uint keyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(pkcs11, session, ref keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate random initialization vector byte[] iv = new byte[8]; rv = pkcs11.C_GenerateRandom(session, iv, Convert.ToUInt32(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 = pkcs11.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 uint encryptedDataLen = 0; rv = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(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 = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(sourceData.Length), encryptedData, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with encrypted data // Initialize decryption operation rv = pkcs11.C_DecryptInit(session, ref mechanism, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get length of decrypted data in first call uint decryptedDataLen = 0; rv = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(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 = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(encryptedData.Length), decryptedData, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with decrypted data Assert.IsTrue(Convert.ToBase64String(sourceData) == Convert.ToBase64String(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 = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _01_GenerateKeyTest() { Helpers.CheckPlatform(); CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, NativeLongUtils.ConvertFromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare attribute template of new key CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[4]; 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); // Specify key generation mechanism (needs no parameter => no unamanaged memory is needed) CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_DES3_KEY_GEN); // Generate key NativeULong keyId = CK.CK_INVALID_HANDLE; rv = pkcs11.C_GenerateKey(session, ref mechanism, template, NativeLongUtils.ConvertFromInt32(template.Length), ref keyId); 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 generated key // Destroy object rv = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _03_EncryptAndDecryptSinglePartOaepTest() { if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 uint slotId = Helpers.GetUsableSlot(pkcs11); uint session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate asymetric key pair uint pubKeyId = CK.CK_INVALID_HANDLE; uint privKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKeyPair(pkcs11, session, ref pubKeyId, ref privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify mechanism parameters CK_RSA_PKCS_OAEP_PARAMS mechanismParams = new CK_RSA_PKCS_OAEP_PARAMS(); mechanismParams.HashAlg = (uint)CKM.CKM_SHA_1; mechanismParams.Mgf = (uint)CKG.CKG_MGF1_SHA1; mechanismParams.Source = (uint)CKZ.CKZ_DATA_SPECIFIED; mechanismParams.SourceData = IntPtr.Zero; mechanismParams.SourceDataLen = 0; // Specify encryption mechanism with parameters // Note that CkmUtils.CreateMechanism() automaticaly copies mechanismParams into newly allocated unmanaged memory. CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_RSA_PKCS_OAEP, mechanismParams); // Initialize encryption operation rv = pkcs11.C_EncryptInit(session, ref mechanism, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } byte[] sourceData = ConvertUtils.Utf8StringToBytes("Hello world"); // Get length of encrypted data in first call uint encryptedDataLen = 0; rv = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(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 = pkcs11.C_Encrypt(session, sourceData, Convert.ToUInt32(sourceData.Length), encryptedData, ref encryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with encrypted data // Initialize decryption operation rv = pkcs11.C_DecryptInit(session, ref mechanism, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Get length of decrypted data in first call uint decryptedDataLen = 0; rv = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(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 = pkcs11.C_Decrypt(session, encryptedData, Convert.ToUInt32(encryptedData.Length), decryptedData, ref decryptedDataLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Array may need to be shrinked if (decryptedData.Length != decryptedDataLen) { Array.Resize(ref decryptedData, Convert.ToInt32(decryptedDataLen)); } // Do something interesting with decrypted data Assert.IsTrue(Convert.ToBase64String(sourceData) == Convert.ToBase64String(decryptedData)); // In LowLevelAPI we have to free unmanaged memory taken by mechanism parameter UnmanagedMemory.Free(ref mechanism.Parameter); mechanism.ParameterLen = 0; rv = pkcs11.C_DestroyObject(session, privKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_DestroyObject(session, pubKeyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.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 (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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(pkcs11); NativeULong session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.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(pkcs11, 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 = pkcs11.C_DigestInit(session, ref mechanism); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Digest key rv = pkcs11.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 = pkcs11.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 = pkcs11.C_DigestFinal(session, digest, ref digestLen); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with digest value rv = pkcs11.C_DestroyObject(session, keyId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
public void _02_SetAttributeValueTest() { if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 uint slotId = Helpers.GetUsableSlot(pkcs11); uint session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Create object uint objectId = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, session, ref objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare list of attributes we want to set CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, "Hello world"); template[1] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, "New data object content"); // Set attributes rv = pkcs11.C_SetAttributeValue(session, objectId, template, Convert.ToUInt32(template.Length)); 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; } rv = pkcs11.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }
/// <summary> /// Initializes new instance of Pkcs11Exception class /// </summary> /// <param name="method">Name of method that caused exception</param> /// <param name="rv">Return value of method that caused exception</param> public Pkcs11Exception(string method, CKR rv) : base(string.Format("Method {0} returned {1}", method, rv.ToString())) { _method = method; _rv = rv; }
public void _01_GetAttributeValueTest() { if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1) { Assert.Inconclusive("Test cannot be executed on this platform"); } CKR rv = CKR.CKR_OK; using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath)) { rv = pkcs11.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 uint slotId = Helpers.GetUsableSlot(pkcs11); uint session = CK.CK_INVALID_HANDLE; rv = pkcs11.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 = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Create object uint objectId = CK.CK_INVALID_HANDLE; rv = Helpers.CreateDataObject(pkcs11, session, ref objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Prepare list of empty attributes we want to read CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2]; template[0] = CkaUtils.CreateAttribute(CKA.CKA_LABEL); template[1] = CkaUtils.CreateAttribute(CKA.CKA_VALUE); // Get size of each individual attribute value in first call rv = pkcs11.C_GetAttributeValue(session, objectId, template, Convert.ToUInt32(template.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // In LowLevelAPI we have to allocate unmanaged memory for attribute value for (int i = 0; i < template.Length; i++) { template[i].value = UnmanagedMemory.Allocate(Convert.ToInt32(template[i].valueLen)); } // Get attribute value in second call rv = pkcs11.C_GetAttributeValue(session, objectId, template, Convert.ToUInt32(template.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with attribute value byte[] ckaLabel = UnmanagedMemory.Read(template[0].value, Convert.ToInt32(template[0].valueLen)); Assert.IsTrue(Convert.ToBase64String(ckaLabel) == Convert.ToBase64String(Settings.ApplicationNameArray)); // 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 = pkcs11.C_DestroyObject(session, objectId); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Logout(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_CloseSession(session); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }