Пример #1
0
        public unsafe bool Contains(X509Certificate certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            if (disposed)
            {
                throw new ObjectDisposedException("SecKeychain");
            }

            // Note: we don't have to use an alias attribute, it's just that it might be faster to use it (fewer certificates we have to compare raw data for)
            byte[] alias = Encoding.UTF8.GetBytes(certificate.GetCommonName());
            IntPtr searchRef, itemRef;
            bool   found = false;

            byte[]   certData;
            OSStatus status;

            fixed(byte *aliasPtr = alias)
            {
                SecKeychainAttribute *attrs = stackalloc SecKeychainAttribute [1];
                int n = 0;

                if (alias != null)
                {
                    attrs[n++] = new SecKeychainAttribute(SecItemAttr.Alias, (uint)alias.Length, (IntPtr)aliasPtr);
                }

                SecKeychainAttributeList attrList = new SecKeychainAttributeList(n, (IntPtr)attrs);

                status = SecKeychainSearchCreateFromAttributes(Handle, SecItemClass.Certificate, &attrList, out searchRef);
                if (status != OSStatus.Ok)
                {
                    throw new Exception("Could not enumerate certificates from the keychain. Error:\n" + GetError(status));
                }

                certData = certificate.GetEncoded();

                while (!found && SecKeychainSearchCopyNext(searchRef, out itemRef) == OSStatus.Ok)
                {
                    SecItemClass itemClass = 0;
                    IntPtr       data      = IntPtr.Zero;
                    uint         length    = 0;

                    status = SecKeychainItemCopyContent(itemRef, ref itemClass, IntPtr.Zero, ref length, ref data);
                    if (status == OSStatus.Ok)
                    {
                        if (certData.Length == (int)length)
                        {
                            byte[] rawData = new byte[(int)length];

                            Marshal.Copy(data, rawData, 0, (int)length);

                            found = true;
                            for (int i = 0; i < rawData.Length; i++)
                            {
                                if (rawData[i] != certData[i])
                                {
                                    found = false;
                                    break;
                                }
                            }
                        }

                        SecKeychainItemFreeContent(IntPtr.Zero, data);
                    }

                    CFRelease(itemRef);
                }

                CFRelease(searchRef);
            }

            return(found);
        }