예제 #1
0
        /// <summary>
        /// Obtains a list of mechanism types supported by a token
        /// </summary>
        /// <returns>List of mechanism types supported by a token</returns>
        public List <CKM> GetMechanismList()
        {
            NativeULong mechanismCount = 0;
            CKR         rv             = _p11.C_GetMechanismList(_slotId, null, ref mechanismCount);

            if (rv != CKR.CKR_OK)
            {
                throw new Pkcs11Exception("C_GetMechanismList", rv);
            }

            if (mechanismCount < 1)
            {
                return(new List <CKM>());
            }

            CKM[] mechanismList = new CKM[mechanismCount];
            rv = _p11.C_GetMechanismList(_slotId, mechanismList, ref mechanismCount);
            if (rv != CKR.CKR_OK)
            {
                throw new Pkcs11Exception("C_GetMechanismList", rv);
            }

            if (mechanismList.Length != NativeLongUtils.ConvertToInt32(mechanismCount))
            {
                Array.Resize(ref mechanismList, NativeLongUtils.ConvertToInt32(mechanismCount));
            }

            return(new List <CKM>(mechanismList));
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the CkTlsPrfParams class.
        /// </summary>
        /// <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 CkTlsPrfParams(byte[] seed, byte[] label, NativeULong outputLen)
        {
            _lowLevelStruct.Seed      = IntPtr.Zero;
            _lowLevelStruct.SeedLen   = 0;
            _lowLevelStruct.Label     = IntPtr.Zero;
            _lowLevelStruct.LabelLen  = 0;
            _lowLevelStruct.Output    = IntPtr.Zero;
            _lowLevelStruct.OutputLen = IntPtr.Zero;

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

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

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

            _lowLevelStruct.Output = UnmanagedMemory.Allocate(NativeLongUtils.ConvertToInt32(outputLen));

            byte[] outputLenBytes = NativeLongUtils.ConvertToByteArray(outputLen);
            _lowLevelStruct.OutputLen = UnmanagedMemory.Allocate(outputLenBytes.Length);
            UnmanagedMemory.Write(_lowLevelStruct.OutputLen, outputLenBytes);
        }
예제 #3
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 == NativeLongUtils.ConvertFromCKA(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 = NativeLongUtils.ConvertFromInt32(originalValue.Length);
            Assert.IsTrue(attr.type == NativeLongUtils.ConvertFromCKA(CKA.CKA_VALUE));
            Assert.IsTrue(attr.value != IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == NativeLongUtils.ConvertFromInt32(originalValue.Length));

            // Read the value of attribute
            byte[] recoveredValue = UnmanagedMemory.Read(attr.value, NativeLongUtils.ConvertToInt32(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 == NativeLongUtils.ConvertFromCKA(CKA.CKA_VALUE));
            Assert.IsTrue(attr.value == IntPtr.Zero);
            Assert.IsTrue(attr.valueLen == 0);
        }
예제 #4
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)
            {
                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 < NativeLongUtils.ConvertToInt32(_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, NativeLongUtils.ConvertToInt32(ckOtpParam.ValueLen));

                // Construct new high level CkOtpParam object (creates copy of CK_OTP_PARAM structure which is good)
                _params.Add(new CkOtpParam(ckOtpParamType, ckOtpParamValue));
            }
        }
예제 #5
0
        /// <summary>
        /// Initializes a new instance of the CkWtlsKeyMatOut class.
        /// </summary>
        /// <param name='ivLength'>Length of initialization vector or 0 if IV is not required</param>
        internal CkWtlsKeyMatOut(NativeULong ivLength)
        {
            _lowLevelStruct.MacSecret = 0;
            _lowLevelStruct.Key       = 0;
            _lowLevelStruct.IV        = IntPtr.Zero;

            _ivLength = ivLength;

            if (_ivLength > 0)
            {
                _lowLevelStruct.IV = UnmanagedMemory.Allocate(NativeLongUtils.ConvertToInt32(_ivLength));
            }
        }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of the CkSsl3KeyMatOut class.
        /// </summary>
        /// <param name='ivLength'>Length of initialization vectors or 0 if IVs are not required</param>
        internal CkSsl3KeyMatOut(NativeULong ivLength)
        {
            _lowLevelStruct.ClientMacSecret = 0;
            _lowLevelStruct.ServerMacSecret = 0;
            _lowLevelStruct.ClientKey       = 0;
            _lowLevelStruct.ServerKey       = 0;
            _lowLevelStruct.IVClient        = IntPtr.Zero;
            _lowLevelStruct.IVServer        = IntPtr.Zero;

            _ivLength = ivLength;

            if (_ivLength > 0)
            {
                _lowLevelStruct.IVClient = UnmanagedMemory.Allocate(NativeLongUtils.ConvertToInt32(_ivLength));
                _lowLevelStruct.IVServer = UnmanagedMemory.Allocate(NativeLongUtils.ConvertToInt32(_ivLength));
            }
        }
예제 #7
0
        /// <summary>
        /// Obtains a list of slots in the system
        /// </summary>
        /// <param name="slotsType">Type of slots to be obtained</param>
        /// <returns>List of available slots</returns>
        public List <Slot> GetSlotList(SlotsType slotsType)
        {
            if (this._disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            NativeULong slotCount = 0;
            CKR         rv        = _p11.C_GetSlotList((slotsType == SlotsType.WithTokenPresent), null, ref slotCount);

            if (rv != CKR.CKR_OK)
            {
                throw new Pkcs11Exception("C_GetSlotList", rv);
            }

            if (slotCount == 0)
            {
                return(new List <Slot>());
            }
            else
            {
                NativeULong[] slotList = new NativeULong[slotCount];
                rv = _p11.C_GetSlotList((slotsType == SlotsType.WithTokenPresent), slotList, ref slotCount);
                if (rv != CKR.CKR_OK)
                {
                    throw new Pkcs11Exception("C_GetSlotList", rv);
                }

                if (slotList.Length != NativeLongUtils.ConvertToInt32(slotCount))
                {
                    Array.Resize(ref slotList, NativeLongUtils.ConvertToInt32(slotCount));
                }

                List <Slot> list = new List <Slot>();
                foreach (NativeULong slot in slotList)
                {
                    list.Add(new Slot(_p11, slot));
                }

                return(list);
            }
        }
예제 #8
0
        public void _01_GetAttributeValueTest()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

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

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

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

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

                // Create object
                NativeULong objectId = CK.CK_INVALID_HANDLE;
                rv = Helpers.CreateDataObject(pkcs11, session, ref objectId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Prepare list of empty attributes we want to read
                CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2];
                template[0] = CkaUtils.CreateAttribute(CKA.CKA_LABEL);
                template[1] = CkaUtils.CreateAttribute(CKA.CKA_VALUE);

                // Get size of each individual attribute value in first call
                rv = pkcs11.C_GetAttributeValue(session, objectId, template, NativeLongUtils.ConvertFromInt32(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(NativeLongUtils.ConvertToInt32(template[i].valueLen));
                }

                // Get attribute value in second call
                rv = pkcs11.C_GetAttributeValue(session, objectId, template, NativeLongUtils.ConvertFromInt32(template.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Do something interesting with attribute value
                byte[] ckaLabel = UnmanagedMemory.Read(template[0].value, NativeLongUtils.ConvertToInt32(template[0].valueLen));
                Assert.IsTrue(ConvertUtils.BytesToBase64String(ckaLabel) == ConvertUtils.BytesToBase64String(Settings.ApplicationNameArray));

                // In LowLevelAPI we have to free unmanaged memory taken by attributes
                for (int i = 0; i < template.Length; i++)
                {
                    UnmanagedMemory.Free(ref template[i].value);
                    template[i].valueLen = 0;
                }

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

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

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

                rv = pkcs11.C_Finalize(IntPtr.Zero);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }
            }
        }
        public void _01_BasicDigestEncryptAndDecryptDigestTest()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

            using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath))
            {
                rv = pkcs11.C_Initialize(Settings.InitArgs40);
                if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
                {
                    Assert.Fail(rv.ToString());
                }

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

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

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

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

                // Generate random initialization vector
                byte[] iv = new byte[8];
                rv = pkcs11.C_GenerateRandom(session, iv, NativeLongUtils.ConvertFromInt32(iv.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Specify encryption mechanism with initialization vector as parameter.
                // Note that CkmUtils.CreateMechanism() automaticaly copies iv into newly allocated unmanaged memory.
                CK_MECHANISM encryptionMechanism = CkmUtils.CreateMechanism(CKM.CKM_DES3_CBC, iv);

                // Specify digesting mechanism (needs no parameter => no unamanaged memory is needed)
                CK_MECHANISM digestingMechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA_1);

                byte[] sourceData    = ConvertUtils.Utf8StringToBytes("Our new password");
                byte[] encryptedData = null;
                byte[] digest1       = null;
                byte[] decryptedData = null;
                byte[] digest2       = null;

                // Multipart digesting and encryption function C_DigestEncryptUpdate can be used i.e. for digesting and encryption of streamed data
                using (MemoryStream inputStream = new MemoryStream(sourceData), outputStream = new MemoryStream())
                {
                    // Initialize digesting operation
                    rv = pkcs11.C_DigestInit(session, ref digestingMechanism);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Initialize encryption operation
                    rv = pkcs11.C_EncryptInit(session, ref encryptionMechanism, keyId);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Prepare buffer for source data part
                    // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long
                    byte[] part = new byte[8];

                    // Prepare buffer for encrypted data part
                    // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long
                    byte[]      encryptedPart    = new byte[8];
                    NativeULong encryptedPartLen = NativeLongUtils.ConvertFromInt32(encryptedPart.Length);

                    // Read input stream with source data
                    int bytesRead = 0;
                    while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0)
                    {
                        // Process each individual source data part
                        encryptedPartLen = NativeLongUtils.ConvertFromInt32(encryptedPart.Length);
                        rv = pkcs11.C_DigestEncryptUpdate(session, part, NativeLongUtils.ConvertFromInt32(bytesRead), encryptedPart, ref encryptedPartLen);
                        if (rv != CKR.CKR_OK)
                        {
                            Assert.Fail(rv.ToString());
                        }

                        // Append encrypted data part to the output stream
                        outputStream.Write(encryptedPart, 0, NativeLongUtils.ConvertToInt32(encryptedPartLen));
                    }

                    // Get length of digest value in first call
                    NativeULong digestLen = 0;
                    rv = pkcs11.C_DigestFinal(session, null, ref digestLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    Assert.IsTrue(digestLen > 0);

                    // Allocate array for digest value
                    digest1 = new byte[digestLen];

                    // Get digest value in second call
                    rv = pkcs11.C_DigestFinal(session, digest1, ref digestLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Get the length of last encrypted data part in first call
                    byte[]      lastEncryptedPart    = null;
                    NativeULong lastEncryptedPartLen = 0;
                    rv = pkcs11.C_EncryptFinal(session, null, ref lastEncryptedPartLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Allocate array for the last encrypted data part
                    lastEncryptedPart = new byte[lastEncryptedPartLen];

                    // Get the last encrypted data part in second call
                    rv = pkcs11.C_EncryptFinal(session, lastEncryptedPart, ref lastEncryptedPartLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Append the last encrypted data part to the output stream
                    outputStream.Write(lastEncryptedPart, 0, NativeLongUtils.ConvertToInt32(lastEncryptedPartLen));

                    // Read whole output stream to the byte array so we can compare results more easily
                    encryptedData = outputStream.ToArray();
                }

                // Do something interesting with encrypted data and digest

                // Multipart decryption and digesting function C_DecryptDigestUpdate can be used i.e. for digesting and decryption of streamed data
                using (MemoryStream inputStream = new MemoryStream(encryptedData), outputStream = new MemoryStream())
                {
                    // Initialize decryption operation
                    rv = pkcs11.C_DecryptInit(session, ref encryptionMechanism, keyId);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Initialize digesting operation
                    rv = pkcs11.C_DigestInit(session, ref digestingMechanism);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Prepare buffer for encrypted data part
                    // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long
                    byte[] encryptedPart = new byte[8];

                    // Prepare buffer for decrypted data part
                    // Note that in real world application we would rather use bigger buffer i.e. 4096 bytes long
                    byte[]      part    = new byte[8];
                    NativeULong partLen = NativeLongUtils.ConvertFromInt32(part.Length);

                    // Read input stream with encrypted data
                    int bytesRead = 0;
                    while ((bytesRead = inputStream.Read(encryptedPart, 0, encryptedPart.Length)) > 0)
                    {
                        // Process each individual encrypted data part
                        partLen = NativeLongUtils.ConvertFromInt32(part.Length);
                        rv      = pkcs11.C_DecryptDigestUpdate(session, encryptedPart, NativeLongUtils.ConvertFromInt32(bytesRead), part, ref partLen);
                        if (rv != CKR.CKR_OK)
                        {
                            Assert.Fail(rv.ToString());
                        }

                        // Append decrypted data part to the output stream
                        outputStream.Write(part, 0, NativeLongUtils.ConvertToInt32(partLen));
                    }

                    // Get the length of last decrypted data part in first call
                    byte[]      lastPart    = null;
                    NativeULong lastPartLen = 0;
                    rv = pkcs11.C_DecryptFinal(session, null, ref lastPartLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Allocate array for the last decrypted data part
                    lastPart = new byte[lastPartLen];

                    // Get the last decrypted data part in second call
                    rv = pkcs11.C_DecryptFinal(session, lastPart, ref lastPartLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Append the last decrypted data part to the output stream
                    outputStream.Write(lastPart, 0, NativeLongUtils.ConvertToInt32(lastPartLen));

                    // Read whole output stream to the byte array so we can compare results more easily
                    decryptedData = outputStream.ToArray();

                    // Get length of digest value in first call
                    NativeULong digestLen = 0;
                    rv = pkcs11.C_DigestFinal(session, null, ref digestLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    Assert.IsTrue(digestLen > 0);

                    // Allocate array for digest value
                    digest2 = new byte[digestLen];

                    // Get digest value in second call
                    rv = pkcs11.C_DigestFinal(session, digest2, ref digestLen);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }
                }

                // Do something interesting with decrypted data and digest
                Assert.IsTrue(ConvertUtils.BytesToBase64String(sourceData) == ConvertUtils.BytesToBase64String(decryptedData));
                Assert.IsTrue(ConvertUtils.BytesToBase64String(digest1) == ConvertUtils.BytesToBase64String(digest2));

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

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

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

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

                rv = pkcs11.C_Finalize(IntPtr.Zero);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Creates the PKCS#1 v1.5 RSA signature with SHA-1 mechanism
        /// </summary>
        /// <param name="data">Data that should be signed</param>
        /// <param name="uri">PKCS#11 URI identifying PKCS#11 library, token and private key</param>
        /// <returns>PKCS#1 v1.5 RSA signature</returns>
        private byte[] SignData(byte[] data, string uri)
        {
            // Verify input parameters
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            if (string.IsNullOrEmpty(uri))
            {
                throw new ArgumentNullException("uri");
            }

            // Parse PKCS#11 URI
            Pkcs11Uri pkcs11Uri = new Pkcs11Uri(uri);

            // Verify that URI contains all information required to perform this operation
            if (pkcs11Uri.ModulePath == null)
            {
                throw new Exception("PKCS#11 URI does not specify PKCS#11 library");
            }

            if (pkcs11Uri.PinValue == null)
            {
                throw new Exception("PKCS#11 URI does not specify PIN");
            }

            if (!pkcs11Uri.DefinesObject || pkcs11Uri.Type != CKO.CKO_PRIVATE_KEY)
            {
                throw new Exception("PKCS#11 URI does not specify private key");
            }

            // Load and initialize PKCS#11 library specified by URI
            CKR rv = CKR.CKR_OK;

            using (Pkcs11 pkcs11 = new Pkcs11(pkcs11Uri.ModulePath, true))
            {
                rv = pkcs11.C_Initialize(Settings.InitArgs41);
                if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
                {
                    Assert.Fail(rv.ToString());
                }

                // Obtain a list of all slots with tokens that match URI
                NativeULong[] slots = null;

                rv = Pkcs11UriUtils.GetMatchingSlotList(pkcs11Uri, pkcs11, true, out slots);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                if ((slots == null) || (slots.Length == 0))
                {
                    throw new Exception("None of the slots matches PKCS#11 URI");
                }

                // Open read only session with first token that matches URI
                NativeULong session = CK.CK_INVALID_HANDLE;

                rv = pkcs11.C_OpenSession(slots[0], (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 with PIN acquired from URI
                byte[] pinValue = ConvertUtils.Utf8StringToBytes(pkcs11Uri.PinValue);

                rv = pkcs11.C_Login(session, CKU.CKU_USER, pinValue, NativeLongUtils.ConvertFromInt32(pinValue.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Get list of object attributes for the private key specified by URI
                CK_ATTRIBUTE[] attributes = null;

                Pkcs11UriUtils.GetObjectAttributes(pkcs11Uri, out attributes);

                // Find private key specified by URI
                NativeULong   foundObjectCount = 0;
                NativeULong[] foundObjectIds   = new NativeULong[] { CK.CK_INVALID_HANDLE };

                rv = pkcs11.C_FindObjectsInit(session, attributes, NativeLongUtils.ConvertFromInt32(attributes.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                rv = pkcs11.C_FindObjects(session, foundObjectIds, NativeLongUtils.ConvertFromInt32(foundObjectIds.Length), ref foundObjectCount);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

                if ((foundObjectCount == 0) || (foundObjectIds[0] == CK.CK_INVALID_HANDLE))
                {
                    throw new Exception("None of the private keys match PKCS#11 URI");
                }

                // Create signature with the private key specified by URI
                CK_MECHANISM mechanism = CkmUtils.CreateMechanism(CKM.CKM_SHA1_RSA_PKCS);

                rv = pkcs11.C_SignInit(session, ref mechanism, foundObjectIds[0]);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                NativeULong signatureLen = 0;

                rv = pkcs11.C_Sign(session, data, NativeLongUtils.ConvertFromInt32(data.Length), null, ref signatureLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                Assert.IsTrue(signatureLen > 0);

                byte[] signature = new byte[signatureLen];

                rv = pkcs11.C_Sign(session, data, NativeLongUtils.ConvertFromInt32(data.Length), signature, ref signatureLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                if (signature.Length != NativeLongUtils.ConvertToInt32(signatureLen))
                {
                    Array.Resize(ref signature, NativeLongUtils.ConvertToInt32(signatureLen));
                }

                // Release PKCS#11 resources
                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());
                }

                return(signature);
            }
        }
        public void _03_EncryptAndDecryptSinglePartOaepTest()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

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

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

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

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

                // Generate asymetric key pair
                NativeULong pubKeyId  = CK.CK_INVALID_HANDLE;
                NativeULong privKeyId = CK.CK_INVALID_HANDLE;
                rv = Helpers.GenerateKeyPair(pkcs11, session, ref pubKeyId, ref privKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Specify mechanism parameters
                CK_RSA_PKCS_OAEP_PARAMS mechanismParams = new CK_RSA_PKCS_OAEP_PARAMS();
                mechanismParams.HashAlg       = NativeLongUtils.ConvertFromCKM(CKM.CKM_SHA_1);
                mechanismParams.Mgf           = NativeLongUtils.ConvertFromCKG(CKG.CKG_MGF1_SHA1);
                mechanismParams.Source        = NativeLongUtils.ConvertFromUInt32(CKZ.CKZ_DATA_SPECIFIED);
                mechanismParams.SourceData    = IntPtr.Zero;
                mechanismParams.SourceDataLen = 0;

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

                // Initialize encryption operation
                rv = pkcs11.C_EncryptInit(session, ref mechanism, pubKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                byte[] sourceData = ConvertUtils.Utf8StringToBytes("Hello world");

                // Get length of encrypted data in first call
                NativeULong encryptedDataLen = 0;
                rv = pkcs11.C_Encrypt(session, sourceData, NativeLongUtils.ConvertFromInt32(sourceData.Length), null, ref encryptedDataLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                Assert.IsTrue(encryptedDataLen > 0);

                // Allocate array for encrypted data
                byte[] encryptedData = new byte[encryptedDataLen];

                // Get encrypted data in second call
                rv = pkcs11.C_Encrypt(session, sourceData, NativeLongUtils.ConvertFromInt32(sourceData.Length), encryptedData, ref encryptedDataLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Do something interesting with encrypted data

                // Initialize decryption operation
                rv = pkcs11.C_DecryptInit(session, ref mechanism, privKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Get length of decrypted data in first call
                NativeULong decryptedDataLen = 0;
                rv = pkcs11.C_Decrypt(session, encryptedData, NativeLongUtils.ConvertFromInt32(encryptedData.Length), null, ref decryptedDataLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                Assert.IsTrue(decryptedDataLen > 0);

                // Allocate array for decrypted data
                byte[] decryptedData = new byte[decryptedDataLen];

                // Get decrypted data in second call
                rv = pkcs11.C_Decrypt(session, encryptedData, NativeLongUtils.ConvertFromInt32(encryptedData.Length), decryptedData, ref decryptedDataLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Array may need to be shrinked
                if (decryptedData.Length != NativeLongUtils.ConvertToInt32(decryptedDataLen))
                {
                    Array.Resize(ref decryptedData, NativeLongUtils.ConvertToInt32(decryptedDataLen));
                }

                // Do something interesting with decrypted data
                Assert.IsTrue(ConvertUtils.BytesToBase64String(sourceData) == ConvertUtils.BytesToBase64String(decryptedData));

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

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

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

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

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

                rv = pkcs11.C_Finalize(IntPtr.Zero);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }
            }
        }