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, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Generate symetric key NativeULong baseKeyId = CK.CK_INVALID_HANDLE; rv = Helpers.GenerateKey(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, ConvertUtils.UInt64FromInt32(data.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Specify mechanism parameters // Note that we are allocating unmanaged memory that will have to be freed later CK_KEY_DERIVATION_STRING_DATA mechanismParams = new CK_KEY_DERIVATION_STRING_DATA(); mechanismParams.Data = UnmanagedMemory.Allocate(data.Length); UnmanagedMemory.Write(mechanismParams.Data, data); mechanismParams.Len = ConvertUtils.UInt64FromInt32(data.Length); // Specify derivation mechanism with parameters // Note that CkmUtils.CreateMechanism() automaticaly copies mechanismParams into newly allocated unmanaged memory CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_XOR_BASE_AND_DATA, mechanismParams); // Derive key NativeULong derivedKey = CK.CK_INVALID_HANDLE; rv = 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()); } } }
/// <summary> /// Initializes a new instance of the CkSkipjackRelayxParams class. /// </summary> /// <param name='oldWrappedX'>Old wrapper key</param> /// <param name='oldPassword'>Old user-supplied password</param> /// <param name='oldPublicData'>Old key exchange public key value</param> /// <param name='oldRandomA'>Old Ra data</param> /// <param name='newPassword'>New user-supplied password</param> /// <param name='newPublicData'>New key exchange public key value</param> /// <param name='newRandomA'>New Ra data</param> public CkSkipjackRelayxParams(byte[] oldWrappedX, byte[] oldPassword, byte[] oldPublicData, byte[] oldRandomA, byte[] newPassword, byte[] newPublicData, byte[] newRandomA) { _lowLevelStruct.OldWrappedXLen = 0; _lowLevelStruct.OldWrappedX = IntPtr.Zero; _lowLevelStruct.OldPasswordLen = 0; _lowLevelStruct.OldPassword = IntPtr.Zero; _lowLevelStruct.OldPublicDataLen = 0; _lowLevelStruct.OldPublicData = IntPtr.Zero; _lowLevelStruct.OldRandomLen = 0; _lowLevelStruct.OldRandomA = IntPtr.Zero; _lowLevelStruct.NewPasswordLen = 0; _lowLevelStruct.NewPassword = IntPtr.Zero; _lowLevelStruct.NewPublicDataLen = 0; _lowLevelStruct.NewPublicData = IntPtr.Zero; _lowLevelStruct.NewRandomLen = 0; _lowLevelStruct.NewRandomA = IntPtr.Zero; if (oldWrappedX != null) { _lowLevelStruct.OldWrappedX = UnmanagedMemory.Allocate(oldWrappedX.Length); UnmanagedMemory.Write(_lowLevelStruct.OldWrappedX, oldWrappedX); _lowLevelStruct.OldWrappedXLen = Convert.ToUInt64(oldWrappedX.Length); } if (oldPassword != null) { _lowLevelStruct.OldPassword = UnmanagedMemory.Allocate(oldPassword.Length); UnmanagedMemory.Write(_lowLevelStruct.OldPassword, oldPassword); _lowLevelStruct.OldPasswordLen = Convert.ToUInt64(oldPassword.Length); } if (oldPublicData != null) { _lowLevelStruct.OldPublicData = UnmanagedMemory.Allocate(oldPublicData.Length); UnmanagedMemory.Write(_lowLevelStruct.OldPublicData, oldPublicData); _lowLevelStruct.OldPublicDataLen = Convert.ToUInt64(oldPublicData.Length); } if (oldRandomA != null) { _lowLevelStruct.OldRandomA = UnmanagedMemory.Allocate(oldRandomA.Length); UnmanagedMemory.Write(_lowLevelStruct.OldRandomA, oldRandomA); _lowLevelStruct.OldRandomLen = Convert.ToUInt64(oldRandomA.Length); } if (newPassword != null) { _lowLevelStruct.NewPassword = UnmanagedMemory.Allocate(newPassword.Length); UnmanagedMemory.Write(_lowLevelStruct.NewPassword, newPassword); _lowLevelStruct.NewPasswordLen = Convert.ToUInt64(newPassword.Length); } if (newPublicData != null) { _lowLevelStruct.NewPublicData = UnmanagedMemory.Allocate(newPublicData.Length); UnmanagedMemory.Write(_lowLevelStruct.NewPublicData, newPublicData); _lowLevelStruct.NewPublicDataLen = Convert.ToUInt64(newPublicData.Length); } if (newRandomA != null) { _lowLevelStruct.NewRandomA = UnmanagedMemory.Allocate(newRandomA.Length); UnmanagedMemory.Write(_lowLevelStruct.NewRandomA, newRandomA); _lowLevelStruct.NewRandomLen = Convert.ToUInt64(newRandomA.Length); } }
/// <summary> /// Initializes a new instance of the CkSkipjackPrivateWrapParams class. /// </summary> /// <param name='password'>User-supplied password</param> /// <param name='publicData'>Other party's key exchange public key value</param> /// <param name='randomA'>Ra data</param> /// <param name='primeP'>Prime, p, value</param> /// <param name='baseG'>Base, g, value</param> /// <param name='subprimeQ'>Subprime, q, value</param> public CkSkipjackPrivateWrapParams(byte[] password, byte[] publicData, byte[] randomA, byte[] primeP, byte[] baseG, byte[] subprimeQ) { _lowLevelStruct.PasswordLen = 0; _lowLevelStruct.Password = IntPtr.Zero; _lowLevelStruct.PublicDataLen = 0; _lowLevelStruct.PublicData = IntPtr.Zero; _lowLevelStruct.PAndGLen = 0; _lowLevelStruct.QLen = 0; _lowLevelStruct.RandomLen = 0; _lowLevelStruct.RandomA = IntPtr.Zero; _lowLevelStruct.PrimeP = IntPtr.Zero; _lowLevelStruct.BaseG = IntPtr.Zero; _lowLevelStruct.SubprimeQ = IntPtr.Zero; if (password != null) { _lowLevelStruct.Password = UnmanagedMemory.Allocate(password.Length); UnmanagedMemory.Write(_lowLevelStruct.Password, password); _lowLevelStruct.PasswordLen = ConvertUtils.UInt64FromInt32(password.Length); } if (publicData != null) { _lowLevelStruct.PublicData = UnmanagedMemory.Allocate(publicData.Length); UnmanagedMemory.Write(_lowLevelStruct.PublicData, publicData); _lowLevelStruct.PublicDataLen = ConvertUtils.UInt64FromInt32(publicData.Length); } if (randomA != null) { _lowLevelStruct.RandomA = UnmanagedMemory.Allocate(randomA.Length); UnmanagedMemory.Write(_lowLevelStruct.RandomA, randomA); _lowLevelStruct.RandomLen = ConvertUtils.UInt64FromInt32(randomA.Length); } if ((primeP != null) && (baseG != null)) { if (primeP.Length != baseG.Length) { throw new ArgumentException("Length of primeP has to be the same as length of baseG"); } } if (primeP != null) { _lowLevelStruct.PrimeP = UnmanagedMemory.Allocate(primeP.Length); UnmanagedMemory.Write(_lowLevelStruct.PrimeP, primeP); _lowLevelStruct.PAndGLen = ConvertUtils.UInt64FromInt32(primeP.Length); } if (baseG != null) { _lowLevelStruct.BaseG = UnmanagedMemory.Allocate(baseG.Length); UnmanagedMemory.Write(_lowLevelStruct.BaseG, baseG); _lowLevelStruct.PAndGLen = ConvertUtils.UInt64FromInt32(baseG.Length); } if (subprimeQ != null) { _lowLevelStruct.SubprimeQ = UnmanagedMemory.Allocate(subprimeQ.Length); UnmanagedMemory.Write(_lowLevelStruct.SubprimeQ, subprimeQ); _lowLevelStruct.QLen = ConvertUtils.UInt64FromInt32(subprimeQ.Length); } }
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.InitArgs41); 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 _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.InitArgs41); 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_GetAttributeValueTest() { 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()); } // Create object NativeULong 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, ConvertUtils.UInt32FromInt32(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(ConvertUtils.UInt32ToInt32(template[i].valueLen)); } // Get attribute value in second call rv = pkcs11.C_GetAttributeValue(session, objectId, template, ConvertUtils.UInt32FromInt32(template.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Do something interesting with attribute value byte[] ckaLabel = UnmanagedMemory.Read(template[0].value, ConvertUtils.UInt32ToInt32(template[0].valueLen)); Assert.IsTrue(ConvertUtils.BytesToBase64String(ckaLabel) == ConvertUtils.BytesToBase64String(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()); } } }
public void _LL_09_02_ExtendedInitTokenAndPinTest() { 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); // Инициализация токена var rutokenInitParam = new CK_RUTOKEN_INIT_PARAM() { SizeofThisStructure = Convert.ToUInt64(Marshal.SizeOf(typeof(CK_RUTOKEN_INIT_PARAM))), UseRepairMode = 0, NewAdminPinLen = Convert.ToUInt64(Settings.SecurityOfficerPinArray.Length), NewUserPinLen = Convert.ToUInt64(Settings.NewUserPinArray.Length), MinAdminPinLen = 6, MinUserPinLen = 6, ChangeUserPINPolicy = Convert.ToUInt64(RutokenFlag.AdminChangeUserPin | RutokenFlag.UserChangeUserPin), MaxAdminRetryCount = Settings.MAX_ADMIN_RETRY_COUNT, MaxUserRetryCount = Settings.MAX_USER_RETRY_COUNT, LabelLen = Convert.ToUInt64(Settings.TokenStdLabelArray.Length), SmMode = 0 }; // Выделение памяти для IntPtr (можно не выделять, а использовать GCPinnedArray) // После использования нужно освободить память rutokenInitParam.NewAdminPin = UnmanagedMemory.Allocate(Settings.SecurityOfficerPinArray.Length); UnmanagedMemory.Write(rutokenInitParam.NewAdminPin, Settings.SecurityOfficerPinArray); rutokenInitParam.NewUserPin = UnmanagedMemory.Allocate(Settings.NewUserPinArray.Length); UnmanagedMemory.Write(rutokenInitParam.NewUserPin, Settings.NewUserPinArray); rutokenInitParam.TokenLabel = UnmanagedMemory.Allocate(Settings.TokenStdLabelArray.Length); UnmanagedMemory.Write(rutokenInitParam.TokenLabel, Settings.TokenStdLabelArray); // Расширенная инициализация токена rv = pkcs11.C_EX_InitToken(slotId, Settings.SecurityOfficerPinArray, ref rutokenInitParam); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Освобождение выделенной памяти UnmanagedMemory.Free(ref rutokenInitParam.NewAdminPin); rutokenInitParam.NewAdminPinLen = 0; UnmanagedMemory.Free(ref rutokenInitParam.NewUserPin); rutokenInitParam.NewUserPinLen = 0; UnmanagedMemory.Free(ref rutokenInitParam.TokenLabel); rutokenInitParam.LabelLen = 0; // Открытие 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()); } // Блокировка PIN-кода пользователя путем ввода неверного пин-кода нужное число раз for (NativeULong i = 0; i < Settings.MAX_USER_RETRY_COUNT; i++) { rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.WrongUserPinArray, Convert.ToUInt64(Settings.WrongUserPinArray.Length)); if (rv != CKR.CKR_PIN_INCORRECT && rv != CKR.CKR_PIN_LOCKED) { Assert.Fail(rv.ToString()); } } // Аутентификация администратора rv = pkcs11.C_Login(session, CKU.CKU_SO, Settings.SecurityOfficerPinArray, Convert.ToUInt64(Settings.SecurityOfficerPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Разблокировка PIN-кода пользователя rv = pkcs11.C_EX_UnblockUserPIN(session); 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_Login(session, CKU.CKU_USER, Settings.NewUserPinArray, Convert.ToUInt64(Settings.NewUserPinArray.Length)); if (rv != CKR.CKR_OK && rv != CKR.CKR_USER_ALREADY_LOGGED_IN) { Assert.Fail(rv.ToString()); } // Изменение метки токена на "длинную" rv = pkcs11.C_EX_SetTokenName(session, Settings.TokenLongLabelArray); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Получение метки токена NativeULong tokenLabelLength = 0; rv = pkcs11.C_EX_GetTokenName(session, null, ref tokenLabelLength); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } Assert.IsTrue(tokenLabelLength > 0); byte[] tokenLabel = new byte[tokenLabelLength]; rv = pkcs11.C_EX_GetTokenName(session, tokenLabel, ref tokenLabelLength); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } // Сравнение записанной и полученной метки Assert.IsTrue(Convert.ToBase64String(Settings.TokenLongLabelArray) == Convert.ToBase64String(tokenLabel)); // Установка PIN-кода пользователя по-умолчанию rv = pkcs11.C_SetPIN(session, Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length), Settings.NormalUserPinArray, Convert.ToUInt64(Settings.NormalUserPinArray.Length)); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } rv = pkcs11.C_Finalize(IntPtr.Zero); if (rv != CKR.CKR_OK) { Assert.Fail(rv.ToString()); } } }