Example #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;
        }