Helper methods for LowLevelAPI tests.
Exemplo n.º 1
0
        public void _01_CreateDestroyObjectTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 0)
                Assert.Inconclusive("Test cannot be executed on this platform");

            CKR rv = CKR.CKR_OK;
            
            using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath))
            {
                rv = pkcs11.C_Initialize(Settings.InitArgs40);
                if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
                    Assert.Fail(rv.ToString());
                
                // Find first slot with token present
                uint slotId = Helpers.GetUsableSlot(pkcs11);
                
                uint session = CK.CK_INVALID_HANDLE;
                rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());
                
                // Login as normal user
                rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length));
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());
                
                // Prepare attribute template of new data object
                CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[5];
                template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA);
                template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true);
                template[2] = CkaUtils.CreateAttribute(CKA.CKA_APPLICATION, Settings.ApplicationName);
                template[3] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, Settings.ApplicationName);
                template[4] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, "Data object content");

                // Create object
                uint objectId = CK.CK_INVALID_HANDLE;
                rv = pkcs11.C_CreateObject(session, template, Convert.ToUInt32(template.Length), ref objectId);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                // 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;
                }

                // Do something interesting with new object

                // Destroy object
                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());
            }
        }
Exemplo n.º 2
0
        public void _01_BasicSignAndVerifyRecoverTest()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

            using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath))
            {
                rv = pkcs11Library.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(pkcs11Library);

                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.UInt32FromInt32(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(pkcs11Library, session, ref pubKeyId, ref privKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

                // Initialize signing operation
                rv = pkcs11Library.C_SignRecoverInit(session, ref mechanism, privKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

                // Get length of signature in first call
                NativeULong signatureLen = 0;
                rv = pkcs11Library.C_SignRecover(session, sourceData, ConvertUtils.UInt32FromInt32(sourceData.Length), null, ref signatureLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                Assert.IsTrue(signatureLen > 0);

                // Allocate array for signature
                byte[] signature = new byte[signatureLen];

                // Get signature in second call
                rv = pkcs11Library.C_SignRecover(session, sourceData, ConvertUtils.UInt32FromInt32(sourceData.Length), signature, ref signatureLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Do something interesting with signature

                // Initialize verification operation
                rv = pkcs11Library.C_VerifyRecoverInit(session, ref mechanism, pubKeyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Get length of recovered data in first call
                NativeULong recoveredDataLen = 0;
                rv = pkcs11Library.C_VerifyRecover(session, signature, ConvertUtils.UInt32FromInt32(signature.Length), null, ref recoveredDataLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                Assert.IsTrue(recoveredDataLen > 0);

                // Allocate array for recovered data
                byte[] recoveredData = new byte[recoveredDataLen];

                // Verify signature and get recovered data in second call
                rv = pkcs11Library.C_VerifyRecover(session, signature, ConvertUtils.UInt32FromInt32(signature.Length), recoveredData, ref recoveredDataLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Do something interesting with verification result and recovered data
                Assert.IsTrue(ConvertUtils.BytesToBase64String(sourceData) == ConvertUtils.BytesToBase64String(recoveredData));

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

                rv = pkcs11Library.C_DestroyObject(session, pubKeyId);
                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());
                }
            }
        }
Exemplo n.º 3
0
        public void _01_BasicInitTokenAndPinTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

                CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO();
                rv = pkcs11.C_GetTokenInfo(slotId, ref tokenInfo);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Check if token needs to be initialized
                if ((tokenInfo.Flags & CKF.CKF_TOKEN_INITIALIZED) != CKF.CKF_TOKEN_INITIALIZED)
                {
                    // Token label is 32 bytes long string padded with blank characters
                    byte[] label = new byte[32];
                    for (int i = 0; i < label.Length; i++)
                    {
                        label[i] = 0x20;
                    }
                    Array.Copy(Settings.ApplicationNameArray, 0, label, 0, Settings.ApplicationNameArray.Length);

                    // Initialize token and SO (security officer) pin
                    rv = pkcs11.C_InitToken(slotId, Settings.SecurityOfficerPinArray, Convert.ToUInt32(Settings.SecurityOfficerPinArray.Length), label);
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Open RW session
                    uint 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 SO (security officer)
                    rv = pkcs11.C_Login(session, CKU.CKU_SO, Settings.SecurityOfficerPinArray, Convert.ToUInt32(Settings.SecurityOfficerPinArray.Length));
                    if (rv != CKR.CKR_OK)
                    {
                        Assert.Fail(rv.ToString());
                    }

                    // Initialize user pin
                    rv = pkcs11.C_InitPIN(session, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length));
                    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());
                }
            }
        }
Exemplo n.º 4
0
        public void _02_CopyObjectTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 0)
                Assert.Inconclusive("Test cannot be executed on this platform");

            CKR rv = CKR.CKR_OK;
            
            using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath))
            {
                rv = pkcs11.C_Initialize(Settings.InitArgs40);
                if ((rv != CKR.CKR_OK) && (rv != CKR.CKR_CRYPTOKI_ALREADY_INITIALIZED))
                    Assert.Fail(rv.ToString());
                
                // Find first slot with token present
                uint slotId = Helpers.GetUsableSlot(pkcs11);
                
                uint session = CK.CK_INVALID_HANDLE;
                rv = pkcs11.C_OpenSession(slotId, (CKF.CKF_SERIAL_SESSION | CKF.CKF_RW_SESSION), IntPtr.Zero, IntPtr.Zero, ref session);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());
                
                // Login as normal user
                rv = pkcs11.C_Login(session, CKU.CKU_USER, Settings.NormalUserPinArray, Convert.ToUInt32(Settings.NormalUserPinArray.Length));
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());
                
                // Create object that can be copied
                uint objectId = CK.CK_INVALID_HANDLE;
                rv = Helpers.CreateDataObject(pkcs11, session, ref objectId);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());
                
                // Copy object
                uint copiedObjectId = CK.CK_INVALID_HANDLE;
                rv = pkcs11.C_CopyObject(session, objectId, null, 0, ref copiedObjectId);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                // Do something interesting with new object

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

                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());
            }
        }
Exemplo n.º 5
0
        public void _03_DigestKeyTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

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

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

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

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

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

                // Digest key
                rv = pkcs11.C_DigestKey(session, keyId);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Get length of digest value in first call
                uint 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
                byte[] digest = new byte[digestLen];

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

                // Do something interesting with digest value

                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());
                }
            }
        }
Exemplo n.º 6
0
        public void _01_DigestSinglePartTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

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

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

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

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

                // Get length of digest value in first call
                uint digestLen = 0;
                rv = pkcs11.C_Digest(session, sourceData, Convert.ToUInt32(sourceData.Length), null, ref digestLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                Assert.IsTrue(digestLen > 0);

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

                // Get digest value in second call
                rv = pkcs11.C_Digest(session, sourceData, Convert.ToUInt32(sourceData.Length), digest, ref digestLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Do something interesting with digest value

                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());
                }
            }
        }
Exemplo n.º 7
0
        public void _02_DigestMultiPartTest()
        {
            if (Platform.UnmanagedLongSize != 4 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

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

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

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

                // Multipart digesting functions C_DigestUpdate and C_DigestFinal can be used i.e. for digesting of streamed data
                using (MemoryStream inputStream = new MemoryStream(sourceData))
                {
                    // Initialize digesting operation
                    rv = pkcs11.C_DigestInit(session, ref mechanism);
                    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];

                    // Read input stream with source data
                    int bytesRead = 0;
                    while ((bytesRead = inputStream.Read(part, 0, part.Length)) > 0)
                    {
                        // Digest each individual source data part
                        rv = pkcs11.C_DigestUpdate(session, part, Convert.ToUInt32(bytesRead));
                        if (rv != CKR.CKR_OK)
                        {
                            Assert.Fail(rv.ToString());
                        }
                    }

                    // Get length of digest value in first call
                    uint 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
                    digest = new byte[digestLen];

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

                // Do something interesting with digest value

                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_BasicObjectFindingTest()
        {
            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, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length));
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());
                
                // Let's create two objects so we can find something
                NativeULong objectId1 = CK.CK_INVALID_HANDLE;
                rv = Helpers.CreateDataObject(pkcs11, session, ref objectId1);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                NativeULong objectId2 = CK.CK_INVALID_HANDLE;
                rv = Helpers.CreateDataObject(pkcs11, session, ref objectId2);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                // Prepare attribute template that defines search criteria
                CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2];
                template[0] = CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_DATA);
                template[1] = CkaUtils.CreateAttribute(CKA.CKA_TOKEN, true);

                // Initialize searching
                rv = pkcs11.C_FindObjectsInit(session, template, ConvertUtils.UInt32FromInt32(template.Length));
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                // Get search results
                NativeULong foundObjectCount = 0;
                NativeULong[] foundObjectIds = new NativeULong[2];
                foundObjectIds[0] = CK.CK_INVALID_HANDLE;
                foundObjectIds[1] = CK.CK_INVALID_HANDLE;
                rv = pkcs11.C_FindObjects(session, foundObjectIds, ConvertUtils.UInt32FromInt32(foundObjectIds.Length), ref foundObjectCount);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                // Terminate searching
                rv = pkcs11.C_FindObjectsFinal(session);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                // Do something interesting with found objects
                Assert.IsTrue((foundObjectIds[0] != CK.CK_INVALID_HANDLE) && (foundObjectIds[1] != CK.CK_INVALID_HANDLE));

                // 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, objectId2);
                if (rv != CKR.CKR_OK)
                    Assert.Fail(rv.ToString());

                rv = pkcs11.C_DestroyObject(session, objectId1);
                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_BasicOperationStateTest()
        {
            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);

                // Open RO (read-only) session
                NativeULong session = CK.CK_INVALID_HANDLE;
                rv = pkcs11.C_OpenSession(slotId, CKF.CKF_SERIAL_SESSION, IntPtr.Zero, IntPtr.Zero, ref session);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

                Assert.IsTrue(stateLen > 0);

                // Allocate array for state
                byte[] state = new byte[stateLen];

                // Get state in second call
                rv = pkcs11.C_GetOperationState(session, state, ref stateLen);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // Let's set state so the test is complete
                rv = pkcs11.C_SetOperationState(session, state, ConvertUtils.UInt32FromInt32(state.Length), CK.CK_INVALID_HANDLE, CK.CK_INVALID_HANDLE);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

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

            CKR rv = CKR.CKR_OK;

            using (Pkcs11 pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath))
            {
                rv = pkcs11.C_Initialize(Settings.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, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

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

                // Get size of each individual attribute value in first call
                rv = pkcs11.C_GetAttributeValue(session, objectId, template, ConvertUtils.UInt32FromInt32(template.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

                // In LowLevelAPI we have to allocate unmanaged memory for attribute value
                for (int i = 0; i < template.Length; i++)
                {
                    template[i].value = UnmanagedMemory.Allocate(ConvertUtils.UInt32ToInt32(template[i].valueLen));
                }

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

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

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

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

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

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

                rv = pkcs11.C_Finalize(IntPtr.Zero);
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }
            }
        }
        public void _02_SetAttributeValueTest()
        {
            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, ConvertUtils.UInt32FromInt32(Settings.NormalUserPinArray.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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

                // Prepare list of attributes we want to set
                CK_ATTRIBUTE[] template = new CK_ATTRIBUTE[2];
                template[0] = CkaUtils.CreateAttribute(CKA.CKA_LABEL, "Hello world");
                template[1] = CkaUtils.CreateAttribute(CKA.CKA_VALUE, "New data object content");

                // Set attributes
                rv = pkcs11.C_SetAttributeValue(session, objectId, template, ConvertUtils.UInt32FromInt32(template.Length));
                if (rv != CKR.CKR_OK)
                {
                    Assert.Fail(rv.ToString());
                }

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