private static void ReleaseItemRef(ref IntPtr itemRef)
 {
     if (itemRef != IntPtr.Zero)
     {
         MacNativeMethods.CFRelease(itemRef);
         itemRef = IntPtr.Zero;
     }
 }
 private static void ReleaseValuePtr(ref IntPtr valuePtr)
 {
     if (valuePtr != IntPtr.Zero)
     {
         MacNativeMethods.SecKeychainItemFreeContent(attrList: IntPtr.Zero, data: valuePtr);
         valuePtr = IntPtr.Zero;
     }
 }
        /// <summary>
        /// Deletes the key specified by given service and account names.
        /// </summary>
        /// <param name="serviceName">Service name.</param>
        /// <param name="accountName">Account name.</param>
        public static void DeleteKey(string serviceName, string accountName)
        {
            IntPtr itemRef  = IntPtr.Zero;
            IntPtr valuePtr = IntPtr.Zero;

            try
            {
                // check if the key exists
                int status = MacNativeMethods.SecKeychainFindGenericPassword(
                    keychainOrArray: IntPtr.Zero,
                    serviceNameLength: (uint)serviceName.Length,
                    serviceName: serviceName,
                    accountNameLength: (uint)accountName.Length,
                    accountName: accountName,
                    passwordLength: out uint valueLength,
                    passwordData: out valuePtr,
                    itemRef: out itemRef);

                if (status == MacNativeMethods.errSecItemNotFound)
                {
                    return;
                }

                if (status != MacNativeMethods.errSecSuccess)
                {
                    throw new Exception(string.Format(CultureInfo.CurrentCulture, Constants.MacKeyChainFindFailed, status));
                }

                if (itemRef == IntPtr.Zero)
                {
                    return;
                }

                // key exists so delete it
                status = MacNativeMethods.SecKeychainItemDelete(itemRef);

                if (status != MacNativeMethods.errSecSuccess)
                {
                    throw new Exception(string.Format(CultureInfo.CurrentCulture, Constants.MacKeyChainDeleteFailed, status));
                }
            }
            finally
            {
                ReleaseItemRefAndValuePtr(ref itemRef, ref valuePtr);
            }
        }
        /// <summary>
        /// Writes specifies vaue for given service and account names.
        /// </summary>
        /// <param name="serviceName">Service name.</param>
        /// <param name="accountName">Account name.</param>
        /// <param name="value">Value.</param>
        public static void WriteKey(string serviceName, string accountName, byte[] value)
        {
            IntPtr itemRef  = IntPtr.Zero;
            IntPtr valuePtr = IntPtr.Zero;

            try
            {
                // check if the key already exists
                int status = MacNativeMethods.SecKeychainFindGenericPassword(
                    keychainOrArray: IntPtr.Zero,
                    serviceNameLength: (uint)serviceName.Length,
                    serviceName: serviceName,
                    accountNameLength: (uint)accountName.Length,
                    accountName: accountName,
                    passwordLength: out uint valueLength,
                    passwordData: out valuePtr,
                    itemRef: out itemRef);

                if (status != MacNativeMethods.errSecSuccess &&
                    status != MacNativeMethods.errSecItemNotFound)
                {
                    throw new Exception(string.Format(CultureInfo.CurrentCulture, Constants.MacKeyChainFindFailed, status));
                }

                if (itemRef != IntPtr.Zero)
                {
                    // key already exists so update it
                    status = MacNativeMethods.SecKeychainItemModifyAttributesAndData(
                        itemRef: itemRef,
                        attrList: IntPtr.Zero,
                        length: (uint)value.Length,
                        data: value);

                    if (status != MacNativeMethods.errSecSuccess)
                    {
                        throw new Exception(string.Format(CultureInfo.CurrentCulture, Constants.MacKeyChainUpdateFailed, status));
                    }
                }
                else
                {
                    // key doesn't exist. add key value data
                    status = MacNativeMethods.SecKeychainAddGenericPassword(
                        keychain: IntPtr.Zero,
                        serviceNameLength: (uint)serviceName.Length,
                        serviceName: serviceName,
                        accountNameLength: (uint)accountName.Length,
                        accountName: accountName,
                        passwordLength: (uint)value.Length,
                        passwordData: value,
                        itemRef: out itemRef);

                    if (status != MacNativeMethods.errSecSuccess)
                    {
                        throw new Exception(string.Format(CultureInfo.CurrentCulture, Constants.MacKeyChainInsertFailed, status));
                    }
                }
            }
            finally
            {
                ReleaseItemRefAndValuePtr(ref itemRef, ref valuePtr);
            }
        }