예제 #1
0
        /// <summary>
        /// Reads value of attribute and returns it as NativeULong array
        /// </summary>
        /// <param name="attribute">Attribute whose value should be read</param>
        /// <param name="value">Location that receives attribute value</param>
        public static void ConvertValue(ref CK_ATTRIBUTE attribute, out NativeULong[] value)
        {
            int ckmSize      = UnmanagedMemory.SizeOf(typeof(NativeULong));
            int attrCount    = ConvertUtils.UInt64ToInt32(attribute.valueLen) / ckmSize;
            int attrCountMod = ConvertUtils.UInt64ToInt32(attribute.valueLen) % ckmSize;

            if (attrCountMod != 0)
            {
                throw new Exception("Unable to convert attribute value to NativeULong array");
            }

            if (attrCount == 0)
            {
                value = null;
            }
            else
            {
                NativeULong[] attrs = new NativeULong[attrCount];

                for (int i = 0; i < attrCount; i++)
                {
                    IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckmSize));
                    attrs[i] = ConvertUtils.UInt64FromBytes(UnmanagedMemory.Read(tempPointer, ckmSize));
                }

                value = attrs;
            }
        }
예제 #2
0
        /// <summary>
        /// Reads value of attribute and returns it as attribute array
        /// </summary>
        /// <param name="attribute">Attribute whose value should be read</param>
        /// <param name="value">Location that receives attribute value</param>
        public static void ConvertValue(ref CK_ATTRIBUTE attribute, out CK_ATTRIBUTE[] value)
        {
            int ckAttributeSize = UnmanagedMemory.SizeOf(typeof(CK_ATTRIBUTE));
            int attrCount       = ConvertUtils.UInt32ToInt32(attribute.valueLen) / ckAttributeSize;
            int attrCountMod    = ConvertUtils.UInt32ToInt32(attribute.valueLen) % ckAttributeSize;

            if (attrCountMod != 0)
            {
                throw new Exception("Unable to convert attribute value to attribute array");
            }

            if (attrCount == 0)
            {
                value = null;
            }
            else
            {
                CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[attrCount];

                for (int i = 0; i < attrCount; i++)
                {
                    IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckAttributeSize));
                    attrs[i] = (CK_ATTRIBUTE)UnmanagedMemory.Read(tempPointer, typeof(CK_ATTRIBUTE));
                }

                value = attrs;
            }
        }
예제 #3
0
        public void Benchmark_ReadWrite()
        {
            Int64 size = 100 * 1000000;

            using (SmartPtr p = UnmanagedMemory.AllocHGlobalExSmartPtr(size))
            {
                string fileName = Path.GetTempFileName();
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
                DateTime start = DateTime.Now;
                using (BinaryWriter w = new BinaryWriter(File.Open(fileName, FileMode.CreateNew, FileAccess.Write)))
                {
                    UnmanagedMemory.Write(w, p, size);
                }
                double time = (DateTime.Now - start).TotalSeconds;
                Console.WriteLine("{0:#,#} bytes written to disk in {1:0.00000} s, {2:#,#} b/s", size, time, size / time);

                start = DateTime.Now;
                using (BinaryReader r = new BinaryReader(File.Open(fileName, FileMode.Open, FileAccess.Read)))
                {
                    UnmanagedMemory.Read(r, p, size);
                }
                time = (DateTime.Now - start).TotalSeconds;
                Console.WriteLine("{0:#,#} bytes read from disk in {1:0.00000} s, {2:#,#} b/s", size, time, size / time);

                File.Delete(fileName);
            }
        }
예제 #4
0
        public void _10_CustomAttributeTest()
        {
            Helpers.CheckPlatform();

            byte[] originalValue = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };

            // Create attribute without the value
            CK_ATTRIBUTE attr = CkaUtils.CreateAttribute(CKA.CKA_VALUE);

            Assert.IsTrue(attr.type == ConvertUtils.UInt64FromCKA(CKA.CKA_VALUE));
            Assert.IsTrue(attr.value == IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == 0);

            // Allocate unmanaged memory for attribute value..
            attr.value = UnmanagedMemory.Allocate(originalValue.Length);
            // ..then set the value of attribute..
            UnmanagedMemory.Write(attr.value, originalValue);
            // ..and finally set the length of attribute value.
            attr.valueLen = ConvertUtils.UInt64FromInt32(originalValue.Length);
            Assert.IsTrue(attr.type == ConvertUtils.UInt64FromCKA(CKA.CKA_VALUE));
            Assert.IsTrue(attr.value != IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == ConvertUtils.UInt64FromInt32(originalValue.Length));

            // Read the value of attribute
            byte[] recoveredValue = UnmanagedMemory.Read(attr.value, ConvertUtils.UInt64ToInt32(attr.valueLen));
            Assert.IsTrue(ConvertUtils.BytesToBase64String(originalValue) == ConvertUtils.BytesToBase64String(recoveredValue));

            // Free attribute value
            UnmanagedMemory.Free(ref attr.value);
            attr.valueLen = 0;
            Assert.IsTrue(attr.type == ConvertUtils.UInt64FromCKA(CKA.CKA_VALUE));
            Assert.IsTrue(attr.value == IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == 0);
        }
예제 #5
0
        /// <summary>
        /// Copies attribute value from unmanaged memory to managed byte array
        /// </summary>
        /// <param name="attribute">Attribute whose value should be read</param>
        /// <returns>Managed copy of attribute value</returns>
        private static byte[] ConvertValue(ref CK_ATTRIBUTE attribute)
        {
            byte[] value = null;

            if (attribute.value != IntPtr.Zero)
            {
                value = UnmanagedMemory.Read(attribute.value, Convert.ToInt32(attribute.valueLen));
            }

            return(value);
        }
        /// <summary>
        /// Initializes a new instance of the CkOtpSignatureInfo class.
        /// </summary>
        /// <param name='signature'>Signature value returned by all OTP mechanisms in successful calls to Sign method</param>
        public CkOtpSignatureInfo(byte[] signature)
        {
            if (signature == null)
            {
                throw new ArgumentNullException("signature");
            }

            // PKCS#11 v2.20a1 page 14:
            // Since C_Sign and C_SignFinal follows the convention described in Section 11.2 of [1]
            // on producing output, a call to C_Sign (or C_SignFinal) with pSignature set to
            // NULL_PTR will return (in the pulSignatureLen parameter) the required number of bytes
            // to hold the CK_OTP_SIGNATURE_INFO structure as well as all the data in all its
            // CK_OTP_PARAM components. If an application allocates a memory block based on this
            // information, it shall therefore not subsequently de-allocate components of such a received
            // value but rather de-allocate the complete CK_OTP_PARAMS structure itself. A
            // Cryptoki library that is called with a non-NULL pSignature pointer will assume that it
            // points to a contiguous memory block of the size indicated by the pulSignatureLen
            // parameter.

            // Create CK_OTP_SIGNATURE_INFO from  C_Sign or C_SignFinal output
            // TODO : This may require different low level delegate with IntPtr as output
            //        but currently I am not aware of any implementation I could test with.
            IntPtr tmpSignature = IntPtr.Zero;

            try
            {
                tmpSignature = UnmanagedMemory.Allocate(signature.Length);
                UnmanagedMemory.Write(tmpSignature, signature);
                UnmanagedMemory.Read(tmpSignature, _lowLevelStruct);
            }
            finally
            {
                UnmanagedMemory.Free(ref tmpSignature);
            }

            // Read all CK_OTP_PARAMs from CK_OTP_SIGNATURE_INFO
            int ckOtpParamSize = UnmanagedMemory.SizeOf(typeof(CK_OTP_PARAM));

            for (int i = 0; i < ConvertUtils.UInt32ToInt32(_lowLevelStruct.Count); i++)
            {
                // Read CK_OTP_PARAM from CK_OTP_SIGNATURE_INFO
                IntPtr       tempPointer = new IntPtr(_lowLevelStruct.Params.ToInt64() + (i * ckOtpParamSize));
                CK_OTP_PARAM ckOtpParam  = new CK_OTP_PARAM();
                UnmanagedMemory.Read(tempPointer, ckOtpParam);

                // Read members of CK_OTP_PARAM structure
                NativeULong ckOtpParamType  = ckOtpParam.Type;
                byte[]      ckOtpParamValue = UnmanagedMemory.Read(ckOtpParam.Value, ConvertUtils.UInt32ToInt32(ckOtpParam.ValueLen));

                // Construct new high level CkOtpParam object (creates copy of CK_OTP_PARAM structure which is good)
                _params.Add(new CkOtpParam(ckOtpParamType, ckOtpParamValue));
            }
        }
예제 #7
0
        /// <summary>
        /// Get delegates with C_GetFunctionList function from the statically linked PKCS#11 library
        /// </summary>
        private void InitializeWithGetFunctionList()
        {
            IntPtr functionList = IntPtr.Zero;

            CKR rv = (CKR)Convert.ToUInt32(NativeMethods.C_GetFunctionList(out functionList));

            if ((rv != CKR.CKR_OK) || (functionList == IntPtr.Zero))
            {
                throw new Pkcs11Exception("C_GetFunctionList", rv);
            }

            CK_FUNCTION_LIST ckFunctionList = (CK_FUNCTION_LIST)UnmanagedMemory.Read(functionList, typeof(CK_FUNCTION_LIST));

            Initialize(ckFunctionList);
        }
예제 #8
0
        private void ReadInternal(BinaryReader r)
        {
            Version = new BdsVersion();
            Version.Read(r);
            int serFmtVer = r.ReadInt32();

            _nodesByteSize = r.ReadInt64();
            _nodesCount    = r.ReadInt64();
            _nodeByteSize  = (int)(_nodesByteSize / _nodesCount);
            Allocate(_nodesCount, _nodeByteSize);
            UnmanagedMemory.Read(r, _depthPtr, _nodesCount);
            UnmanagedMemory.Read(r, _nodesPtr, _nodesByteSize);
            ReadUserData(r);
            AfterRead();
        }
예제 #9
0
        /// <summary>
        /// Get delegates with C_GetFunctionList function from the dynamically loaded shared PKCS#11 library
        /// </summary>
        /// <param name="libraryHandle">Handle to the PKCS#11 library</param>
        private void InitializeWithGetFunctionList(IntPtr libraryHandle)
        {
            IntPtr cGetFunctionListPtr = UnmanagedLibrary.GetFunctionPointer(libraryHandle, "C_GetFunctionList");
            C_GetFunctionListDelegate cGetFunctionList = UnmanagedLibrary.GetDelegateForFunctionPointer <C_GetFunctionListDelegate>(cGetFunctionListPtr);

            IntPtr functionList = IntPtr.Zero;

            CKR rv = (CKR)Convert.ToUInt32(cGetFunctionList(out functionList));

            if ((rv != CKR.CKR_OK) || (functionList == IntPtr.Zero))
            {
                throw new Pkcs11Exception("C_GetFunctionList", rv);
            }

            CK_FUNCTION_LIST ckFunctionList = (CK_FUNCTION_LIST)UnmanagedMemory.Read(functionList, typeof(CK_FUNCTION_LIST));

            Initialize(ckFunctionList);
        }
예제 #10
0
        static LutEvaluator7()
        {
            string    fileName  = LutPath;
            Exception exception = null;

            try
            {
                using (FileStream file = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    using (BinaryReader r = new BinaryReader(file))
                    {
                        BdsVersion version = new BdsVersion();
                        version.Read(r);
                        UInt32 formatId    = r.ReadUInt32();
                        UInt32 lutSize     = r.ReadUInt32();
                        UInt32 lutByteSize = lutSize * 4;
                        _lutPtr = UnmanagedMemory.AllocHGlobalExSmartPtr(lutByteSize);
                        pLut    = (UInt32 *)_lutPtr;
                        UnmanagedMemory.Read(r, _lutPtr, lutByteSize);
                    }
                }
            }
            catch (Exception e)
            {
                exception = e;
            }
            if (exception != null)
            {
                if (_lutPtr != null)
                {
                    _lutPtr.Dispose();
                    _lutPtr = null;
                }
                pLut = (UInt32 *)IntPtr.Zero.ToPointer();

                // If IO error occured leave the class uninitialized. This is a normal case for table generation.
                // If the application tries to use an uninitialized class, an exception will be thrown somewhere.
                // Otherwise rethrow the exception.
                if (!(exception is IOException))
                {
                    throw exception;
                }
            }
        }
예제 #11
0
 public void GetNode(Int64 nodeIdx, void *node)
 {
     // Do only an assertion to get the max. performance
     Debug.Assert(nodeIdx < _nodesCount, "Index out of range");
     if (_nodesPtr != null)
     {
         byte *p = ((byte *)_nodesPtr) + nodeIdx * _nodeByteSize;
         byte *n = (byte *)node;
         for (int i = 0; i < _nodeByteSize; ++i)
         {
             n[i] = p[i];
         }
     }
     else
     {
         _fdaReader.BaseStream.Seek(this._nodesFilePos + nodeIdx * _nodeByteSize, SeekOrigin.Begin);
         UnmanagedMemory.Read(_fdaReader, new IntPtr(node), _nodeByteSize);
     }
 }
예제 #12
0
        public void _01_AllocateAndFreeTest()
        {
            Helpers.CheckPlatform();

            byte[] originalValue  = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
            byte[] recoveredValue = null;

            IntPtr ptr = IntPtr.Zero;

            ptr = UnmanagedMemory.Allocate(originalValue.Length);
            Assert.IsTrue(ptr != IntPtr.Zero);

            UnmanagedMemory.Write(ptr, originalValue);
            recoveredValue = UnmanagedMemory.Read(ptr, originalValue.Length);
            Assert.IsTrue(recoveredValue != null);
            Assert.IsTrue(ConvertUtils.BytesToBase64String(originalValue) == ConvertUtils.BytesToBase64String(recoveredValue));

            UnmanagedMemory.Free(ref ptr);
            Assert.IsTrue(ptr == IntPtr.Zero);
        }
예제 #13
0
        void DoTestReadWrite(IntPtr p, Int64 size)
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter w  = new BinaryWriter(ms);

            UnmanagedMemory.Write(w, p, size);
            byte[] buffer = ms.ToArray();
            ms = new MemoryStream(buffer);
            using (SmartPtr p1 = UnmanagedMemory.AllocHGlobalExSmartPtr(size))
            {
                BinaryReader r = new BinaryReader(ms);
                UnmanagedMemory.Read(r, p1.Ptr, size);
                byte *pBytes  = (byte *)p;
                byte *pBytes1 = (byte *)p1;
                for (Int64 i = 0; i < size; ++i)
                {
                    Assert.AreEqual(pBytes[i], pBytes1[i], String.Format("Values differ at pos {0}, size {1}", i, size));
                }
                p1.Dispose();
            }
        }
        public void _01_AllocateAndFreeTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            byte[] originalValue  = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
            byte[] recoveredValue = null;

            IntPtr ptr = IntPtr.Zero;

            ptr = UnmanagedMemory.Allocate(originalValue.Length);
            Assert.IsTrue(ptr != IntPtr.Zero);

            UnmanagedMemory.Write(ptr, originalValue);
            recoveredValue = UnmanagedMemory.Read(ptr, originalValue.Length);
            Assert.IsTrue(recoveredValue != null);
            Assert.IsTrue(Convert.ToBase64String(originalValue) == Convert.ToBase64String(recoveredValue));

            UnmanagedMemory.Free(ref ptr);
            Assert.IsTrue(ptr == IntPtr.Zero);
        }
        public void _10_CustomAttributeTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            byte[] originalValue = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };

            // Create attribute without the value
            CK_ATTRIBUTE attr = CkaUtils.CreateAttribute(CKA.CKA_VALUE);

            Assert.IsTrue(attr.type == (uint)CKA.CKA_VALUE);
            Assert.IsTrue(attr.value == IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == 0);

            // Allocate unmanaged memory for attribute value..
            attr.value = UnmanagedMemory.Allocate(originalValue.Length);
            // ..then set the value of attribute..
            UnmanagedMemory.Write(attr.value, originalValue);
            // ..and finally set the length of attribute value.
            attr.valueLen = (uint)originalValue.Length;
            Assert.IsTrue(attr.type == (uint)CKA.CKA_VALUE);
            Assert.IsTrue(attr.value != IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == originalValue.Length);

            // Read the value of attribute
            byte[] recoveredValue = UnmanagedMemory.Read(attr.value, Convert.ToInt32(attr.valueLen));
            Assert.IsTrue(Convert.ToBase64String(originalValue) == Convert.ToBase64String(recoveredValue));

            // Free attribute value
            UnmanagedMemory.Free(ref attr.value);
            attr.valueLen = 0;
            Assert.IsTrue(attr.type == (uint)CKA.CKA_VALUE);
            Assert.IsTrue(attr.value == IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == 0);
        }
        /// <summary>
        /// Initializes a new instance of the CkOtpSignatureInfo class.
        /// </summary>
        /// <param name='signature'>Signature value returned by all OTP mechanisms in successful calls to Sign method</param>
        public CkOtpSignatureInfo(byte[] signature)
        {
            if (signature == null)
            {
                return;
            }

            int ckOtpParamSize = UnmanagedMemory.SizeOf(typeof(CK_OTP_PARAM));

            if (signature.Length % ckOtpParamSize != 0)
            {
                throw new ArgumentException("Invalid array length", "signature");
            }

            // Copy signature to unmanaged memory
            _signature = UnmanagedMemory.Allocate(signature.Length);
            UnmanagedMemory.Write(_signature, signature);

            // Read CK_OTP_SIGNATURE_INFO from unmanaged memory
            UnmanagedMemory.Read(_signature, _lowLevelStruct);

            for (int i = 0; i < _lowLevelStruct.Count; i++)
            {
                // Read CK_OTP_PARAM from CK_OTP_SIGNATURE_INFO
                IntPtr       tempPointer = new IntPtr(_lowLevelStruct.Params.ToInt32() + (i * ckOtpParamSize));
                CK_OTP_PARAM ckOtpParam  = new CK_OTP_PARAM();
                UnmanagedMemory.Read(tempPointer, ckOtpParam);

                // Read members of CK_OTP_PARAM structure
                uint   ckOtpParamType  = ckOtpParam.Type;
                byte[] ckOtpParamValue = UnmanagedMemory.Read(ckOtpParam.Value, (int)ckOtpParam.ValueLen);

                // Construct high level CkOtpParam class
                _params.Add(new CkOtpParam(ckOtpParamType, ckOtpParamValue));
            }
        }
예제 #17
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.InitArgs81);
                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_GOSTR3410_DERIVE_PARAMS
                // для выработки общего ключа
                byte[] ukm = new byte[Settings.UKM_LENGTH];
                rv = pkcs11.C_GenerateRandom(session, ukm, Convert.ToUInt64(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.ToUInt64(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.ToUInt64(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.ToUInt64(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.ToUInt64(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.ToUInt64(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()
        {
            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());
                }

                // Create object
                ulong 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.ToUInt64(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.ToUInt64(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());
                }
            }
        }
예제 #19
0
        public void _LL_25_26_03_KegKexp15KuznechikTwisted_Test()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

            using (var pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath))
            {
                // Инициализация библиотеки
                rv = pkcs11.C_Initialize(Settings.InitArgs81);
                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_VENDOR_GOST_KEG_PARAMS
                // для выработки двойственного ключа экспорта
                byte[] ukm = new byte[Settings.KEG_256_UKM_LENGTH];
                rv = pkcs11.C_GenerateRandom(session, ukm, Convert.ToUInt64(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.ToUInt64(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.ToUInt64(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.ToUInt64(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.ToUInt64(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.ToUInt64(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());
                }
            }
        }