/// <summary>
        /// Initializes a new instance of the CkPkcs5Pbkd2Params2 class.
        /// </summary>
        /// <param name='saltSource'>Source of the salt value (CKZ)</param>
        /// <param name='saltSourceData'>Data used as the input for the salt source</param>
        /// <param name='iterations'>Number of iterations to perform when generating each block of random data</param>
        /// <param name='prf'>Pseudo-random function to used to generate the key (CKP)</param>
        /// <param name='prfData'>Data used as the input for PRF in addition to the salt value</param>
        /// <param name='password'>Password to be used in the PBE key generation</param>
        public CkPkcs5Pbkd2Params2(NativeULong saltSource, byte[] saltSourceData, NativeULong iterations, NativeULong prf, byte[] prfData, byte[] password)
        {
            _lowLevelStruct.SaltSource        = 0;
            _lowLevelStruct.SaltSourceData    = IntPtr.Zero;
            _lowLevelStruct.SaltSourceDataLen = 0;
            _lowLevelStruct.Iterations        = 0;
            _lowLevelStruct.Prf         = prf;
            _lowLevelStruct.PrfData     = IntPtr.Zero;
            _lowLevelStruct.PrfDataLen  = 0;
            _lowLevelStruct.Password    = IntPtr.Zero;
            _lowLevelStruct.PasswordLen = 0;

            _lowLevelStruct.SaltSource = saltSource;

            if (saltSourceData != null)
            {
                _lowLevelStruct.SaltSourceData = UnmanagedMemory.Allocate(saltSourceData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.SaltSourceData, saltSourceData);
                _lowLevelStruct.SaltSourceDataLen = NativeLongUtils.ConvertFromInt32(saltSourceData.Length);
            }

            _lowLevelStruct.Iterations = iterations;

            _lowLevelStruct.Prf = prf;

            if (prfData != null)
            {
                _lowLevelStruct.PrfData = UnmanagedMemory.Allocate(prfData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.PrfData, prfData);
                _lowLevelStruct.PrfDataLen = NativeLongUtils.ConvertFromInt32(prfData.Length);
            }

            if (password != null)
            {
                _lowLevelStruct.Password = UnmanagedMemory.Allocate(password.Length);
                UnmanagedMemory.Write(_lowLevelStruct.Password, password);
                _lowLevelStruct.PasswordLen = NativeLongUtils.ConvertFromInt32(password.Length);
            }
        }
        public void _03_StructureParameterTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 1)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            byte[]        data = new byte[24];
            System.Random rng  = new Random();
            rng.NextBytes(data);

            // Specify mechanism parameters
            // Note that we are allocating unmanaged memory that will have to be freed later
            CK_KEY_DERIVATION_STRING_DATA parameter = new CK_KEY_DERIVATION_STRING_DATA();

            parameter.Data = UnmanagedMemory.Allocate(data.Length);
            UnmanagedMemory.Write(parameter.Data, data);
            parameter.Len = Convert.ToUInt32(data.Length);

            // Create mechanism with the structure as parameter
            // Note that CkmUtils.CreateMechanism() automaticaly copies mechanismParams into newly allocated unmanaged memory
            CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_XOR_BASE_AND_DATA, parameter);

            Assert.IsTrue(mechanism.Mechanism == (uint)CKM.CKM_XOR_BASE_AND_DATA);
            Assert.IsTrue(mechanism.Parameter != IntPtr.Zero);
            Assert.IsTrue(mechanism.ParameterLen == UnmanagedMemory.SizeOf(typeof(CK_KEY_DERIVATION_STRING_DATA)));

            // Free all unmanaged memory we previously allocated
            UnmanagedMemory.Free(ref parameter.Data);
            parameter.Len = 0;

            // Free unmanaged memory taken by mechanism parameter
            UnmanagedMemory.Free(ref mechanism.Parameter);
            mechanism.ParameterLen = 0;
            Assert.IsTrue(mechanism.Mechanism == (uint)CKM.CKM_XOR_BASE_AND_DATA);
            Assert.IsTrue(mechanism.Parameter == IntPtr.Zero);
            Assert.IsTrue(mechanism.ParameterLen == 0);
        }
示例#3
0
        public CkVendorVkoGostR3410_2012_512Params(ulong kdf, byte[] publicData, byte[] ukm)
        {
            _lowLevelStruct.kdf             = 0;
            _lowLevelStruct.pPublicData     = IntPtr.Zero;
            _lowLevelStruct.ulPublicDataLen = 0;
            _lowLevelStruct.pUKM            = IntPtr.Zero;
            _lowLevelStruct.ulUKMLen        = 0;

            if (publicData == null)
            {
                throw new ArgumentNullException(nameof(publicData));
            }

            if (publicData.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(publicData), "Array has to be not null length");
            }

            if (ukm == null)
            {
                throw new ArgumentNullException(nameof(ukm));
            }

            if (ukm.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(ukm), "has to be not null length");
            }

            _lowLevelStruct.kdf = (NativeULong)kdf;

            _lowLevelStruct.ulPublicDataLen = (NativeULong)publicData.Length;
            _lowLevelStruct.pPublicData     = UnmanagedMemory.Allocate(publicData.Length);
            UnmanagedMemory.Write(_lowLevelStruct.pPublicData, publicData);

            _lowLevelStruct.ulUKMLen = (NativeULong)ukm.Length;
            _lowLevelStruct.pUKM     = UnmanagedMemory.Allocate(ukm.Length);
            UnmanagedMemory.Write(_lowLevelStruct.pUKM, ukm);
        }
        /// <summary>
        /// Initializes a new instance of the CkGostR3410DeriveParams class.
        /// </summary>
        /// <param name="kdf">Additional key diversification algorithm (CKD)</param>
        /// <param name="publicData">Data with public key of a receiver</param>
        /// <param name="ukm">UKM data</param>
        public CkGostR3410DeriveParams(NativeULong kdf, byte[] publicData, byte[] ukm)
        {
            _lowLevelStruct.Kdf           = 0;
            _lowLevelStruct.PublicData    = IntPtr.Zero;
            _lowLevelStruct.PublicDataLen = 0;
            _lowLevelStruct.UKM           = IntPtr.Zero;
            _lowLevelStruct.UKMLen        = 0;

            if (publicData == null)
            {
                throw new ArgumentNullException("publicData");
            }

            if (publicData.Length != 64)
            {
                throw new ArgumentOutOfRangeException("publicData", "Array has to be 64 bytes long");
            }

            if (ukm == null)
            {
                throw new ArgumentNullException("ukm");
            }

            if (ukm.Length != 8)
            {
                throw new ArgumentOutOfRangeException("ukm", "Array has to be 8 bytes long");
            }

            _lowLevelStruct.Kdf = kdf;

            _lowLevelStruct.PublicData = UnmanagedMemory.Allocate(publicData.Length);
            UnmanagedMemory.Write(_lowLevelStruct.PublicData, publicData);
            _lowLevelStruct.PublicDataLen = NativeLongUtils.ConvertFromInt32(publicData.Length);

            _lowLevelStruct.UKM = UnmanagedMemory.Allocate(ukm.Length);
            UnmanagedMemory.Write(_lowLevelStruct.UKM, ukm);
            _lowLevelStruct.UKMLen = NativeLongUtils.ConvertFromInt32(ukm.Length);
        }
示例#5
0
        /// <summary>
        /// Initializes a new instance of the CkOtpParams class.
        /// </summary>
        /// <param name='parameters'>List of OTP parameters</param>
        public CkOtpParams(List <CkOtpParam> parameters)
        {
            _lowLevelStruct.Params = IntPtr.Zero;
            _lowLevelStruct.Count  = 0;

            if (parameters.Count > 0)
            {
                // Keep reference to parameters so GC will not free them while this object exists
                _parameters = parameters;

                // Allocate memory for parameters
                int ckOtpParamSize = UnmanagedMemory.SizeOf(typeof(CK_OTP_PARAM));
                _lowLevelStruct.Params = UnmanagedMemory.Allocate(ckOtpParamSize * _parameters.Count);
                _lowLevelStruct.Count  = (uint)_parameters.Count;

                // Copy paramaters to allocated memory
                for (int i = 0; i < _parameters.Count; i++)
                {
                    IntPtr tempPointer = new IntPtr(_lowLevelStruct.Params.ToInt32() + (i * ckOtpParamSize));
                    UnmanagedMemory.Write(tempPointer, _parameters[i].ToLowLevelParams());
                }
            }
        }
示例#6
0
        public void Set <T>(int binding, T data) where T : struct
        {
            ThrowIfDisposed();

            Entry?entry = GetEntry(binding);

            if (entry == null)
            {
                throw new Exception(
                          $"[{nameof(PushDataContainer)}] Binding '{binding}' unknown");
            }

            #if DEBUG
            int size = Unsafe.SizeOf <T>();
            if (size != entry.Value.Size)
            {
                throw new Exception(
                          $"[{nameof(PushDataContainer)}] Binding '{binding}' has different size then provided data");
            }
            #endif

            memory.Write(data, entry.Value.Offset);
        }
        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);
        }
        /// <summary>
        /// Initializes a new instance of the CkWtlsPrfParams class.
        /// </summary>
        /// <param name='digestMechanism'>Digest mechanism to be used (CKM)</param>
        /// <param name='seed'>Input seed</param>
        /// <param name='label'>Identifying label</param>
        /// <param name='outputLen'>Length in bytes that the output to be created shall have</param>
        public CkWtlsPrfParams(ulong digestMechanism, byte[] seed, byte[] label, ulong outputLen)
        {
            _lowLevelStruct.DigestMechanism = 0;
            _lowLevelStruct.Seed            = IntPtr.Zero;
            _lowLevelStruct.SeedLen         = 0;
            _lowLevelStruct.Label           = IntPtr.Zero;
            _lowLevelStruct.LabelLen        = 0;
            _lowLevelStruct.Output          = IntPtr.Zero;
            _lowLevelStruct.OutputLen       = IntPtr.Zero;

            _lowLevelStruct.DigestMechanism = digestMechanism;

            if (seed != null)
            {
                _lowLevelStruct.Seed = UnmanagedMemory.Allocate(seed.Length);
                UnmanagedMemory.Write(_lowLevelStruct.Seed, seed);
                _lowLevelStruct.SeedLen = Convert.ToUInt64(seed.Length);
            }

            if (label != null)
            {
                _lowLevelStruct.Label = UnmanagedMemory.Allocate(label.Length);
                UnmanagedMemory.Write(_lowLevelStruct.Label, label);
                _lowLevelStruct.LabelLen = Convert.ToUInt64(label.Length);
            }

            if (outputLen < 1)
            {
                throw new ArgumentException("Value has to be positive number", "outputLen");
            }

            _lowLevelStruct.Output = UnmanagedMemory.Allocate(Convert.ToInt32(outputLen));

            byte[] outputLenBytes = ConvertUtils.ULongToBytes(outputLen);
            _lowLevelStruct.OutputLen = UnmanagedMemory.Allocate(outputLenBytes.Length);
            UnmanagedMemory.Write(_lowLevelStruct.OutputLen, outputLenBytes);
        }
        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 CkX942Dh1DeriveParams class.
        /// </summary>
        /// <param name='kdf'>Key derivation function used on the shared secret value (CKD)</param>
        /// <param name='otherInfo'>Some data shared between the two parties</param>
        /// <param name='publicData'>Other party's X9.42 Diffie-Hellman public key value</param>
        public CkX942Dh1DeriveParams(ulong kdf, byte[] otherInfo, byte[] publicData)
        {
            _lowLevelStruct.Kdf           = 0;
            _lowLevelStruct.OtherInfoLen  = 0;
            _lowLevelStruct.OtherInfo     = IntPtr.Zero;
            _lowLevelStruct.PublicDataLen = 0;
            _lowLevelStruct.PublicData    = IntPtr.Zero;

            _lowLevelStruct.Kdf = kdf;

            if (otherInfo != null)
            {
                _lowLevelStruct.OtherInfo = UnmanagedMemory.Allocate(otherInfo.Length);
                UnmanagedMemory.Write(_lowLevelStruct.OtherInfo, otherInfo);
                _lowLevelStruct.OtherInfoLen = Convert.ToUInt64(otherInfo.Length);
            }

            if (publicData != null)
            {
                _lowLevelStruct.PublicData = UnmanagedMemory.Allocate(publicData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.PublicData, publicData);
                _lowLevelStruct.PublicDataLen = Convert.ToUInt64(publicData.Length);
            }
        }
示例#11
0
        /// <summary>
        /// Initializes a new instance of the CkPbeParams class.
        /// </summary>
        /// <param name='initVector'>8-byte initialization vector (IV), if an IV is required</param>
        /// <param name='password'>Password to be used in the PBE key generation</param>
        /// <param name='salt'>Salt to be used in the PBE key generation</param>
        /// <param name='iteration'>Number of iterations required for the generation</param>
        public CkPbeParams(byte[] initVector, byte[] password, byte[] salt, NativeULong iteration)
        {
            _lowLevelStruct.InitVector  = IntPtr.Zero;
            _lowLevelStruct.Password    = IntPtr.Zero;
            _lowLevelStruct.PasswordLen = 0;
            _lowLevelStruct.Salt        = IntPtr.Zero;
            _lowLevelStruct.SaltLen     = 0;
            _lowLevelStruct.Iteration   = 0;

            if (initVector != null)
            {
                if (initVector.Length != 8)
                {
                    throw new ArgumentOutOfRangeException("initVector", "Array has to be 8 bytes long");
                }

                _lowLevelStruct.InitVector = UnmanagedMemory.Allocate(initVector.Length);
                UnmanagedMemory.Write(_lowLevelStruct.InitVector, initVector);
            }

            if (password != null)
            {
                _lowLevelStruct.Password = UnmanagedMemory.Allocate(password.Length);
                UnmanagedMemory.Write(_lowLevelStruct.Password, password);
                _lowLevelStruct.PasswordLen = ConvertUtils.UInt32FromInt32(password.Length);
            }

            if (salt != null)
            {
                _lowLevelStruct.Salt = UnmanagedMemory.Allocate(salt.Length);
                UnmanagedMemory.Write(_lowLevelStruct.Salt, salt);
                _lowLevelStruct.SaltLen = ConvertUtils.UInt32FromInt32(salt.Length);
            }

            _lowLevelStruct.Iteration = iteration;
        }
        /// <summary>
        /// Initializes a new instance of the CkGostR3410KeyWrapParams class.
        /// </summary>
        /// <param name="wrapOID">Data with DER-encoding of the object identifier indicating the data object type of GOST 28147-89</param>
        /// <param name="ukm">Data with UKM</param>
        /// <param name="key">Key handle of a sender for wrapping operation or key handle of a receiver for unwrapping operation</param>
        public CkGostR3410KeyWrapParams(byte[] wrapOID, byte[] ukm, NativeULong key)
        {
            _lowLevelStruct.WrapOID    = IntPtr.Zero;
            _lowLevelStruct.WrapOIDLen = 0;
            _lowLevelStruct.UKM        = IntPtr.Zero;
            _lowLevelStruct.UKMLen     = 0;
            _lowLevelStruct.Key        = 0;

            if (wrapOID != null)
            {
                _lowLevelStruct.WrapOID = UnmanagedMemory.Allocate(wrapOID.Length);
                UnmanagedMemory.Write(_lowLevelStruct.WrapOID, wrapOID);
                _lowLevelStruct.WrapOIDLen = ConvertUtils.UInt64FromInt32(wrapOID.Length);
            }

            if (ukm != null)
            {
                _lowLevelStruct.UKM = UnmanagedMemory.Allocate(ukm.Length);
                UnmanagedMemory.Write(_lowLevelStruct.UKM, ukm);
                _lowLevelStruct.UKMLen = ConvertUtils.UInt64FromInt32(ukm.Length);
            }

            _lowLevelStruct.Key = key;
        }
示例#13
0
        /// <summary>
        /// Creates attribute of given type with ulong array value
        /// </summary>
        /// <param name="type">Attribute type</param>
        /// <param name="value">Attribute value</param>
        /// <returns>Attribute of given type with ulong array value</returns>
        public static CK_ATTRIBUTE CreateAttribute(ulong type, ulong[] value)
        {
            CK_ATTRIBUTE attribute = new CK_ATTRIBUTE();

            attribute.type = type;
            if ((value != null) && (value.Length > 0))
            {
                int ckmSize = UnmanagedMemory.SizeOf(typeof(ulong));
                attribute.value = UnmanagedMemory.Allocate(ckmSize * value.Length);
                for (int i = 0; i < value.Length; i++)
                {
                    IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckmSize));
                    UnmanagedMemory.Write(tempPointer, ConvertUtils.ULongToBytes(value[i]));
                }
                attribute.valueLen = Convert.ToUInt64(ckmSize * value.Length);
            }
            else
            {
                attribute.value    = IntPtr.Zero;
                attribute.valueLen = 0;
            }

            return(attribute);
        }
        /// <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));
            }
        }
示例#15
0
        /// <summary>
        /// Creates attribute of given type with attribute array value
        /// </summary>
        /// <param name="type">Attribute type</param>
        /// <param name="value">Attribute value</param>
        /// <returns>Attribute of given type with attribute array value</returns>
        public static CK_ATTRIBUTE CreateAttribute(NativeULong type, CK_ATTRIBUTE[] value)
        {
            CK_ATTRIBUTE attribute = new CK_ATTRIBUTE();

            attribute.type = type;
            if ((value != null) && (value.Length > 0))
            {
                int ckAttributeSize = UnmanagedMemory.SizeOf(typeof(CK_ATTRIBUTE));
                attribute.value = UnmanagedMemory.Allocate(ckAttributeSize * value.Length);
                for (int i = 0; i < value.Length; i++)
                {
                    IntPtr tempPointer = new IntPtr(attribute.value.ToInt64() + (i * ckAttributeSize));
                    UnmanagedMemory.Write(tempPointer, value[i]);
                }
                attribute.valueLen = NativeLongUtils.ConvertFromInt32(ckAttributeSize * value.Length);
            }
            else
            {
                attribute.value    = IntPtr.Zero;
                attribute.valueLen = 0;
            }

            return(attribute);
        }
        /// <summary>
        /// Initializes a new instance of the CkX942Dh1DeriveParams class.
        /// </summary>
        /// <param name='kdf'>Key derivation function used on the shared secret value (CKD)</param>
        /// <param name='otherInfo'>Some data shared between the two parties</param>
        /// <param name='publicData'>Other party's X9.42 Diffie-Hellman public key value</param>
        public CkX942Dh1DeriveParams(NativeULong kdf, byte[] otherInfo, byte[] publicData)
        {
            _lowLevelStruct.Kdf           = 0;
            _lowLevelStruct.OtherInfoLen  = 0;
            _lowLevelStruct.OtherInfo     = IntPtr.Zero;
            _lowLevelStruct.PublicDataLen = 0;
            _lowLevelStruct.PublicData    = IntPtr.Zero;

            _lowLevelStruct.Kdf = kdf;

            if (otherInfo != null)
            {
                _lowLevelStruct.OtherInfo = UnmanagedMemory.Allocate(otherInfo.Length);
                UnmanagedMemory.Write(_lowLevelStruct.OtherInfo, otherInfo);
                _lowLevelStruct.OtherInfoLen = NativeLongUtils.ConvertFromInt32(otherInfo.Length);
            }

            if (publicData != null)
            {
                _lowLevelStruct.PublicData = UnmanagedMemory.Allocate(publicData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.PublicData, publicData);
                _lowLevelStruct.PublicDataLen = NativeLongUtils.ConvertFromInt32(publicData.Length);
            }
        }
示例#17
0
        /// <summary>
        /// Initializes a new instance of the CkEcdh1DeriveParams class.
        /// </summary>
        /// <param name='kdf'>Key derivation function used on the shared secret value (CKD)</param>
        /// <param name='sharedData'>Some data shared between the two parties</param>
        /// <param name='publicData'>Other party's EC public key value</param>
        public CkEcdh1DeriveParams(NativeULong kdf, byte[] sharedData, byte[] publicData)
        {
            _lowLevelStruct.Kdf           = 0;
            _lowLevelStruct.SharedDataLen = 0;
            _lowLevelStruct.SharedData    = IntPtr.Zero;
            _lowLevelStruct.PublicDataLen = 0;
            _lowLevelStruct.PublicData    = IntPtr.Zero;

            _lowLevelStruct.Kdf = kdf;

            if (sharedData != null)
            {
                _lowLevelStruct.SharedData = UnmanagedMemory.Allocate(sharedData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.SharedData, sharedData);
                _lowLevelStruct.SharedDataLen = ConvertUtils.UInt64FromInt32(sharedData.Length);
            }

            if (publicData != null)
            {
                _lowLevelStruct.PublicData = UnmanagedMemory.Allocate(publicData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.PublicData, publicData);
                _lowLevelStruct.PublicDataLen = ConvertUtils.UInt64FromInt32(publicData.Length);
            }
        }
        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());
                }
            }
        }
        /// <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 = NativeLongUtils.ConvertFromInt32(oldWrappedX.Length);
            }

            if (oldPassword != null)
            {
                _lowLevelStruct.OldPassword = UnmanagedMemory.Allocate(oldPassword.Length);
                UnmanagedMemory.Write(_lowLevelStruct.OldPassword, oldPassword);
                _lowLevelStruct.OldPasswordLen = NativeLongUtils.ConvertFromInt32(oldPassword.Length);
            }

            if (oldPublicData != null)
            {
                _lowLevelStruct.OldPublicData = UnmanagedMemory.Allocate(oldPublicData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.OldPublicData, oldPublicData);
                _lowLevelStruct.OldPublicDataLen = NativeLongUtils.ConvertFromInt32(oldPublicData.Length);
            }

            if (oldRandomA != null)
            {
                _lowLevelStruct.OldRandomA = UnmanagedMemory.Allocate(oldRandomA.Length);
                UnmanagedMemory.Write(_lowLevelStruct.OldRandomA, oldRandomA);
                _lowLevelStruct.OldRandomLen = NativeLongUtils.ConvertFromInt32(oldRandomA.Length);
            }

            if (newPassword != null)
            {
                _lowLevelStruct.NewPassword = UnmanagedMemory.Allocate(newPassword.Length);
                UnmanagedMemory.Write(_lowLevelStruct.NewPassword, newPassword);
                _lowLevelStruct.NewPasswordLen = NativeLongUtils.ConvertFromInt32(newPassword.Length);
            }

            if (newPublicData != null)
            {
                _lowLevelStruct.NewPublicData = UnmanagedMemory.Allocate(newPublicData.Length);
                UnmanagedMemory.Write(_lowLevelStruct.NewPublicData, newPublicData);
                _lowLevelStruct.NewPublicDataLen = NativeLongUtils.ConvertFromInt32(newPublicData.Length);
            }

            if (newRandomA != null)
            {
                _lowLevelStruct.NewRandomA = UnmanagedMemory.Allocate(newRandomA.Length);
                UnmanagedMemory.Write(_lowLevelStruct.NewRandomA, newRandomA);
                _lowLevelStruct.NewRandomLen = NativeLongUtils.ConvertFromInt32(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_09_02_ExtendedInitTokenAndPinTest()
        {
            if (Platform.NativeULongSize != 4 || Platform.StructPackingSize != 1)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

            using (RutokenPkcs11Library pkcs11 = new RutokenPkcs11Library(Settings.Pkcs11LibraryPath))
            {
                // Инициализация библиотеки
                rv = pkcs11.C_Initialize(Settings.InitArgs40);
                if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
                {
                    Assert.Fail(rv.ToString());
                }

                // Установление соединения с Рутокен в первом доступном слоте
                NativeULong slotId = Helpers.GetUsableSlot(pkcs11);

                // Инициализация токена
                var rutokenInitParam = new CK_RUTOKEN_INIT_PARAM()
                {
                    SizeofThisStructure = Convert.ToUInt32(Marshal.SizeOf(typeof(CK_RUTOKEN_INIT_PARAM))),
                    UseRepairMode       = 0,
                    NewAdminPinLen      = Convert.ToUInt32(Settings.SecurityOfficerPinArray.Length),
                    NewUserPinLen       = Convert.ToUInt32(Settings.NewUserPinArray.Length),
                    MinAdminPinLen      = 6,
                    MinUserPinLen       = 6,
                    ChangeUserPINPolicy = Convert.ToUInt32(RutokenFlag.AdminChangeUserPin | RutokenFlag.UserChangeUserPin),
                    MaxAdminRetryCount  = Settings.MAX_ADMIN_RETRY_COUNT,
                    MaxUserRetryCount   = Settings.MAX_USER_RETRY_COUNT,
                    LabelLen            = Convert.ToUInt32(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.ToUInt32(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.ToUInt32(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.ToUInt32(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.ToUInt32(Settings.NormalUserPinArray.Length),
                                     Settings.NormalUserPinArray,
                                     Convert.ToUInt32(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());
                }
            }
        }
示例#22
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());
                }
            }
        }