Helper methods for LowLevelAPI tests.
示例#1
0
        public void _01_DigestSinglePartTest()
        {
            if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

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

                // 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
                ulong digestLen = 0;
                rv = pkcs11.C_Digest(session, sourceData, Convert.ToUInt64(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.ToUInt64(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());
                }
            }
        }
        public void _01_BasicSignAndVerifyRecoverTest()
        {
            Helpers.CheckPlatform();

            CKR rv = CKR.CKR_OK;

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

                // Find first slot with token present
                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.UInt64FromInt32(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.UInt64FromInt32(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.UInt64FromInt32(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.UInt64FromInt32(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.UInt64FromInt32(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());
                }
            }
        }
示例#3
0
        public void _03_DigestKeyTest()
        {
            if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

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

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

                // Generate symetric key
                ulong 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
                ulong 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());
                }
            }
        }
示例#4
0
        public void _02_DigestMultiPartTest()
        {
            if (Platform.UnmanagedLongSize != 8 || Platform.StructPackingSize != 0)
            {
                Assert.Inconclusive("Test cannot be executed on this platform");
            }

            CKR rv = CKR.CKR_OK;

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

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

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

                // 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.ToUInt64(bytesRead));
                        if (rv != CKR.CKR_OK)
                        {
                            Assert.Fail(rv.ToString());
                        }
                    }

                    // Get length of digest value in first call
                    ulong 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 _06_GetMatchingSlotList()
        {
            Helpers.CheckPlatform();

            using (Pkcs11Library pkcs11Library = new Pkcs11Library(Settings.Pkcs11LibraryPath))
            {
                CKR rv = pkcs11Library.C_Initialize(Settings.InitArgs80);
                Assert.IsTrue(rv == CKR.CKR_OK);

                // Get all slots
                NativeULong allSlotsCount = 0;
                rv = pkcs11Library.C_GetSlotList(true, null, ref allSlotsCount);
                Assert.IsTrue(rv == CKR.CKR_OK);
                Assert.IsTrue(allSlotsCount > 0);
                NativeULong[] allSlots = new NativeULong[allSlotsCount];
                rv = pkcs11Library.C_GetSlotList(true, allSlots, ref allSlotsCount);
                Assert.IsTrue(rv == CKR.CKR_OK);

                // Empty URI
                Pkcs11Uri pkcs11uri = new Pkcs11Uri(@"pkcs11:");
                NativeULong[] matchedSlots = null;
                rv = Pkcs11UriUtils.GetMatchingSlotList(pkcs11uri, pkcs11Library, true, out matchedSlots);
                Assert.IsTrue(rv == CKR.CKR_OK);
                Assert.IsTrue(matchedSlots.Length == allSlots.Length);

                // Unknown path attribute in URI
                pkcs11uri = new Pkcs11Uri(@"pkcs11:vendor=foobar");
                rv = Pkcs11UriUtils.GetMatchingSlotList(pkcs11uri, pkcs11Library, true, out matchedSlots);
                Assert.IsTrue(rv == CKR.CKR_OK);
                Assert.IsTrue(matchedSlots.Length == 0);

                // All attributes matching one slot
                CK_INFO libraryInfo = new CK_INFO();
                rv = pkcs11Library.C_GetInfo(ref libraryInfo);
                Assert.IsTrue(rv == CKR.CKR_OK);
                CK_SLOT_INFO slotInfo = new CK_SLOT_INFO();
                rv = pkcs11Library.C_GetSlotInfo(allSlots[0], ref slotInfo);
                Assert.IsTrue(rv == CKR.CKR_OK);
                CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO();
                rv = pkcs11Library.C_GetTokenInfo(allSlots[0], ref tokenInfo);
                Assert.IsTrue(rv == CKR.CKR_OK);

                Pkcs11UriBuilder pkcs11UriBuilder = new Pkcs11UriBuilder();
                pkcs11UriBuilder.LibraryManufacturer = ConvertUtils.BytesToUtf8String(libraryInfo.ManufacturerId, true);
                pkcs11UriBuilder.LibraryDescription = ConvertUtils.BytesToUtf8String(libraryInfo.LibraryDescription, true);
                pkcs11UriBuilder.LibraryVersion = libraryInfo.LibraryVersion.ToString();
                pkcs11UriBuilder.SlotManufacturer = ConvertUtils.BytesToUtf8String(slotInfo.ManufacturerId, true);
                pkcs11UriBuilder.SlotDescription = ConvertUtils.BytesToUtf8String(slotInfo.SlotDescription, true);
                pkcs11UriBuilder.SlotId = allSlots[0];
                pkcs11UriBuilder.Token = ConvertUtils.BytesToUtf8String(tokenInfo.Label, true);
                pkcs11UriBuilder.Manufacturer = ConvertUtils.BytesToUtf8String(tokenInfo.ManufacturerId, true);
                pkcs11UriBuilder.Serial = ConvertUtils.BytesToUtf8String(tokenInfo.SerialNumber, true);
                pkcs11UriBuilder.Model = ConvertUtils.BytesToUtf8String(tokenInfo.Model, true);
                pkcs11uri = pkcs11UriBuilder.ToPkcs11Uri();

                rv = Pkcs11UriUtils.GetMatchingSlotList(pkcs11uri, pkcs11Library, true, out matchedSlots);
                Assert.IsTrue(rv == CKR.CKR_OK);
                Assert.IsTrue(matchedSlots.Length == 1);

                // One attribute nonmatching
                pkcs11UriBuilder.Serial = "foobar";
                pkcs11uri = pkcs11UriBuilder.ToPkcs11Uri();
                rv = Pkcs11UriUtils.GetMatchingSlotList(pkcs11uri, pkcs11Library, true, out matchedSlots);
                Assert.IsTrue(rv == CKR.CKR_OK);
                Assert.IsTrue(matchedSlots.Length == 0);

                rv = pkcs11Library.C_Finalize(IntPtr.Zero);
                Assert.IsTrue(rv == CKR.CKR_OK);
            }
        }
        public void _05_ObjectAttributesMatches()
        {
            Helpers.CheckPlatform();

            // Empty URI
            Pkcs11Uri pkcs11uri = new Pkcs11Uri(@"pkcs11:");
            List<CK_ATTRIBUTE> objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foobar"));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
            Assert.IsTrue(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            // Empty attribute
            pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=;id=%01%02%03");
            objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, string.Empty));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
            Assert.IsTrue(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            // Unknown path attribute in URI
            pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03;foo=bar");
            objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foobar"));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            // All attributes matching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
            objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foobar"));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
            Assert.IsTrue(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            // Type nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
            objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foobar"));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            // Object nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
            objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foo bar"));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            // Id nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
            objectAttributes = new List<CK_ATTRIBUTE>();
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foobar"));
            objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x04, 0x05, 0x06 }));
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes));

            try
            {
                // Type present in URI but missing in list
                pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
                objectAttributes = new List<CK_ATTRIBUTE>();
                objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_LABEL, "foobar"));
                objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
                Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes);
                Assert.Fail("Exception expected but not thrown");
            }
            catch (Exception ex)
            {
                Assert.IsTrue(ex is Pkcs11UriException);
            }

            try
            {
                // Object present in URI but missing in list
                pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
                objectAttributes = new List<CK_ATTRIBUTE>();
                objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
                objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x01, 0x02, 0x03 }));
                Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes);
                Assert.Fail("Exception expected but not thrown");
            }
            catch (Exception ex)
            {
                Assert.IsTrue(ex is Pkcs11UriException);
            }

            try
            {
                // Id present in URI but missing in list
                pkcs11uri = new Pkcs11Uri(@"pkcs11:type=private;object=foobar;id=%01%02%03");
                objectAttributes = new List<CK_ATTRIBUTE>();
                objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
                objectAttributes.Add(CkaUtils.CreateAttribute(CKA.CKA_ID, new byte[] { 0x04, 0x05, 0x06 }));
                Pkcs11UriUtils.Matches(pkcs11uri, objectAttributes);
                Assert.Fail("Exception expected but not thrown");
            }
            catch (Exception ex)
            {
                Assert.IsTrue(ex is Pkcs11UriException);
            }
        }
        public void _04_TokenInfoMatches()
        {
            Helpers.CheckPlatform();

            // Empty URI
            Pkcs11Uri pkcs11uri = new Pkcs11Uri(@"pkcs11:");
            CK_TOKEN_INFO tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsTrue(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // Empty attribute
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=;manufacturer=bar;serial=123;model=foobar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("                                ");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsTrue(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // Unknown path attribute in URI
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=foo;manufacturer=bar;serial=123;model=foobar;foo=bar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // All attributes matching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=foo;manufacturer=bar;serial=123;model=foobar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsTrue(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // Label nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=foo;manufacturer=bar;serial=123;model=foobar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // ManufacturerId nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=foo;manufacturer=bar;serial=123;model=foobar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // SerialNumber nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=foo;manufacturer=bar;serial=123;model=foobar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("012");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foobar");
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));

            // Model nonmatching
            pkcs11uri = new Pkcs11Uri(@"pkcs11:token=foo;manufacturer=bar;serial=123;model=foobar");
            tokenInfo = new CK_TOKEN_INFO();
            tokenInfo.Label = ConvertUtils.Utf8StringToBytes("foo");
            tokenInfo.ManufacturerId = ConvertUtils.Utf8StringToBytes("bar");
            tokenInfo.SerialNumber = ConvertUtils.Utf8StringToBytes("123");
            tokenInfo.Model = ConvertUtils.Utf8StringToBytes("foo bar");
            Assert.IsFalse(Pkcs11UriUtils.Matches(pkcs11uri, tokenInfo));
        }