Esempio n. 1
0
        public void _01_BasicDeriveKeyTest()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

            using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath))
            {
                rv = pkcs11Library.C_Initialize(Settings.InitArgs81);
                if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
                {
                    Assert.Fail(rv.ToString());
                }

                // Find first slot with token present
                NativeULong slotId = Helpers.GetUsableSlot(pkcs11Library);

                // Open RW session
                NativeULong session = CK.CK_INVALID_HANDLE;
                rv = pkcs11Library.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Login as normal user
                rv = pkcs11Library.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, ConvertUtils.UInt64FromInt32(Settings.NormalUserPinArray.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Generate symetric key
                NativeULong baseKeyId = CK.CK_INVALID_HANDLE;
                rv = Helpers.GenerateKey(pkcs11Library, session, ref baseKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Generate random data needed for key derivation
                byte[] data = new byte[24];
                rv = pkcs11Library.C_GenerateRandom(session, data, ConvertUtils.UInt64FromInt32(data.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Specify mechanism parameters
                // Note that we are allocating unmanaged memory that will have to be freed later
                CK_KEY_DERIVATION_STRING_DATA mechanismParams = new CK_KEY_DERIVATION_STRING_DATA();
                mechanismParams.Data = UnmanagedMemory.Allocate(data.Length);
                UnmanagedMemory.Write(mechanismParams.Data, data);
                mechanismParams.Len = ConvertUtils.UInt64FromInt32(data.Length);

                // Specify derivation mechanism with parameters
                // Note that CkmUtils.CreateMechanism() automaticaly copies mechanismParams into newly allocated unmanaged memory
                CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_XOR_BASE_AND_DATA, mechanismParams);

                // Derive key
                NativeULong derivedKey = CK.CK_INVALID_HANDLE;
                rv = pkcs11Library.C_DeriveKey(session, ref mechanism, baseKeyId, null, 0, ref derivedKey);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Do something interesting with derived key
                Assert.IsTrue(derivedKey != CK.CK_INVALID_HANDLE);

                // In LowLevelAPI we have to free all unmanaged memory we previously allocated
                UnmanagedMemory.Free(ref mechanismParams.Data);
                mechanismParams.Len = 0;

                // In LowLevelAPI we have to free unmanaged memory taken by mechanism parameter
                UnmanagedMemory.Free(ref mechanism.Parameter);
                mechanism.ParameterLen = 0;

                rv = pkcs11Library.C_DestroyObject(session, baseKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                rv = pkcs11Library.C_DestroyObject(session, derivedKey);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                rv = pkcs11Library.C_Logout(session);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                rv = pkcs11Library.C_CloseSession(session);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                rv = pkcs11Library.C_Finalize(IntPtr.Zero);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }
            }
        }
Esempio n. 2
0
        public void _LL_25_26_02_DeriveAndWrap_VKO_Gost3410_12_Test()
        {
            Helpers.CheckPlatform();

            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());
                }
            }
        }