]> git.saurik.com Git - apple/security.git/blobdiff - OSX/sec/securityd/SecDbQuery.c
Security-59306.41.2.tar.gz
[apple/security.git] / OSX / sec / securityd / SecDbQuery.c
diff --git a/OSX/sec/securityd/SecDbQuery.c b/OSX/sec/securityd/SecDbQuery.c
deleted file mode 100644 (file)
index ae67d53..0000000
+++ /dev/null
@@ -1,987 +0,0 @@
-
-/*
- * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- *  SecDbQuery.c - CoreFoundation-based constants and functions for
-    access to Security items (certificates, keys, identities, and
-    passwords.)
- */
-
-#include <securityd/SecDbQuery.h>
-
-#include <securityd/SecItemDb.h>
-#include <securityd/SecItemSchema.h>
-#include <securityd/SecItemServer.h>
-#include <securityd/spi.h>
-#include <Security/SecBasePriv.h>
-#include <Security/SecCertificateInternal.h>
-#include <Security/SecItem.h>
-#include <Security/SecItemPriv.h>
-#include <Security/SecItemInternal.h>
-#include <Security/SecAccessControl.h>
-#include <Security/SecAccessControlPriv.h>
-#include <Security/SecPolicyPriv.h>
-#include <Security/SecuritydXPC.h>
-#include <CommonCrypto/CommonDigest.h>
-#include <CommonCrypto/CommonDigestSPI.h>
-
-#include <pthread/pthread.h>
-
-#if USE_KEYSTORE
-#include <LocalAuthentication/LAPublicDefines.h>
-#include <coreauthd_spi.h>
-#include <libaks_acl_cf_keys.h>
-#endif
-
-/* Upper limit for number of keys in a QUERY dictionary. */
-#define QUERY_KEY_LIMIT_BASE    (128)
-#ifdef NO_SERVER
-#define QUERY_KEY_LIMIT  (31 + QUERY_KEY_LIMIT_BASE)
-#else
-#define QUERY_KEY_LIMIT  QUERY_KEY_LIMIT_BASE
-#endif
-
-
-static const uint8_t systemKeychainUUID[] = "\xF6\x23\xAE\x5C\xCC\x81\x4C\xAC\x8A\xD4\xF0\x01\x3F\x31\x35\x11";
-
-CFDataRef
-SecMUSRCopySystemKeychainUUID(void)
-{
-    return CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)systemKeychainUUID, 16, kCFAllocatorNull);
-}
-
-CFDataRef
-SecMUSRGetSystemKeychainUUID(void)
-{
-    static dispatch_once_t onceToken;
-    static CFDataRef systemKeychainData = NULL;
-    dispatch_once(&onceToken, ^{
-        systemKeychainData = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)systemKeychainUUID, 16, kCFAllocatorNull);
-    });
-    return systemKeychainData;
-}
-
-CFDataRef
-SecMUSRGetSingleUserKeychainUUID(void)
-{
-    static dispatch_once_t onceToken;
-    static CFDataRef singleUser = NULL;
-    dispatch_once(&onceToken, ^{
-        singleUser = CFDataCreateWithBytesNoCopy(NULL, NULL, 0, kCFAllocatorNull);
-    });
-    return singleUser;
-}
-
-bool
-SecMUSRIsSingleUserView(CFDataRef musr)
-{
-    return CFEqual(musr, SecMUSRGetSingleUserKeychainUUID());
-}
-
-static const uint8_t allKeychainViewsUUID[16] = "\xC8\x60\x07\xEC\x89\x62\x4D\xAF\x85\x65\x1F\xE6\x0F\x50\x5D\xB7";
-
-CFDataRef
-SecMUSRGetAllViews(void)
-{
-    static dispatch_once_t onceToken;
-    static CFDataRef allKeychainViewsData = NULL;
-    dispatch_once(&onceToken, ^{
-        allKeychainViewsData = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)allKeychainViewsUUID, 16, kCFAllocatorNull);
-    });
-    return allKeychainViewsData;
-}
-
-bool
-SecMUSRIsViewAllViews(CFDataRef musr)
-{
-    return CFEqual(musr, SecMUSRGetAllViews());
-}
-
-#if TARGET_OS_IPHONE
-
-CFDataRef
-SecMUSRCreateActiveUserUUID(uid_t uid)
-{
-    uint8_t uuid[16] = "\xA7\x5A\x3A\x35\xA5\x57\x4B\x10\xBE\x2E\x83\x94\x7E\x4A\x34\x72";
-    uint32_t num = htonl(uid);
-    memcpy(&uuid[12], &num, sizeof(num));
-    return CFDataCreate(NULL, uuid, sizeof(uuid));
-}
-
-CFDataRef
-SecMUSRCreateSyncBubbleUserUUID(uid_t uid)
-{
-    uint8_t uuid[16] = "\x82\x1A\xAB\x9F\xA3\xC8\x4E\x11\xAA\x90\x4C\xE8\x9E\xA6\xD7\xEC";
-    uint32_t num = htonl(uid);
-    memcpy(&uuid[12], &num, sizeof(num));
-    return CFDataCreate(NULL, uuid, sizeof(uuid));
-}
-
-static const uint8_t bothUserAndSystemUUID[12] = "\x36\xC4\xBE\x2E\x99\x0A\x46\x9A\xAC\x89\x09\xA4";
-
-
-CFDataRef
-SecMUSRCreateBothUserAndSystemUUID(uid_t uid)
-{
-    uint8_t uuid[16];
-    memcpy(uuid, bothUserAndSystemUUID, 12);
-    uint32_t num = htonl(uid);
-    memcpy(&uuid[12], &num, sizeof(num));
-    return CFDataCreate(NULL, uuid, sizeof(uuid));
-}
-
-bool
-SecMUSRGetBothUserAndSystemUUID(CFDataRef musr, uid_t *uid)
-{
-    if (CFDataGetLength(musr) != 16)
-        return false;
-    const uint8_t *uuid = CFDataGetBytePtr(musr);
-    if (memcmp(uuid, bothUserAndSystemUUID, 12) != 0)
-        return false;
-    if (uid) {
-        uint32_t num;
-        memcpy(&num, &uuid[12], sizeof(num));
-        *uid = htonl(num);
-    }
-    return true;
-}
-
-#endif
-
-/* Inline accessors to attr and match values in a query. */
-CFIndex query_attr_count(const Query *q)
-{
-    return q->q_attr_end;
-}
-
-Pair query_attr_at(const Query *q, CFIndex ix)
-{
-    return q->q_pairs[ix];
-}
-
-CFIndex query_match_count(const Query *q)
-{
-    return q->q_match_end - q->q_match_begin;
-}
-
-__unused static inline Pair query_match_at(const Query *q, CFIndex ix)
-{
-    return q->q_pairs[q->q_match_begin + ix];
-}
-
-/* Private routines used to parse a query. */
-
-const SecDbClass *kc_class_with_name(CFStringRef name) {
-    if (isString(name)) {
-        if (CFEqual(name, kSecClassGenericPassword))
-            return genp_class();
-        else if (CFEqual(name, kSecClassInternetPassword))
-            return inet_class();
-        else if (CFEqual(name, kSecClassCertificate))
-            return cert_class();
-        else if (CFEqual(name, kSecClassKey))
-            return keys_class();
-        else if (CFEqual(name, kSecClassIdentity))
-            return identity_class();
-    }
-    return NULL;
-}
-
-static void query_set_access_control(Query *q, SecAccessControlRef access_control) {
-    if (q->q_access_control) {
-        if (!CFEqual(q->q_access_control, access_control)) {
-            SecError(errSecItemIllegalQuery, &q->q_error, CFSTR("conflicting kSecAccess and kSecAccessControl attributes"));
-        }
-    } else {
-        /* Store access control virtual attribute. */
-        q->q_access_control = (SecAccessControlRef)CFRetain(access_control);
-        
-        /* Also set legacy access attribute. */
-        CFTypeRef protection = SecAccessControlGetProtection(q->q_access_control);
-        if (!protection) {
-            SecError(errSecParam, &q->q_error, CFSTR("kSecAccessControl missing protection"));
-            return;
-        }
-        CFDictionarySetValue(q->q_item, kSecAttrAccessible, protection);
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, string or number of length 4.
- value (ok) is a caller provided, non NULL CFTypeRef.
- */
-void query_add_attribute_with_desc(const SecDbAttr *desc, const void *value, Query *q)
-{
-    if (CFEqual(desc->name, kSecAttrSynchronizable)) {
-        q->q_sync = true;
-        if (CFEqual(value, kSecAttrSynchronizableAny))
-            return; /* skip the attribute so it isn't part of the search */
-    }
-
-    CFTypeRef attr = NULL;
-    switch (desc->kind) {
-        case kSecDbDataAttr:
-            attr = copyData(value);
-            break;
-        case kSecDbBlobAttr:
-        case kSecDbAccessControlAttr:
-            attr = copyBlob(value);
-            break;
-        case kSecDbDateAttr:
-        case kSecDbCreationDateAttr:
-        case kSecDbModificationDateAttr:
-            attr = copyDate(value);
-            break;
-        case kSecDbNumberAttr:
-        case kSecDbSyncAttr:
-        case kSecDbTombAttr:
-            attr = copyNumber(value);
-            break;
-        case kSecDbAccessAttr:
-        case kSecDbStringAttr:
-            attr = copyString(value);
-            break;
-        case kSecDbSHA1Attr:
-            attr = copySHA1(value);
-            break;
-        case kSecDbRowIdAttr:
-        case kSecDbPrimaryKeyAttr:
-        case kSecDbEncryptedDataAttr:
-        case kSecDbUTombAttr:
-            break;
-        case kSecDbUUIDAttr:
-            attr = copyUUID(value);
-            break;
-    }
-
-    if (!attr) {
-        SecError(errSecItemInvalidValue, &q->q_error, CFSTR("attribute %@: value: %@ failed to convert"), desc->name, value);
-        return;
-    }
-
-    /* Store plaintext attr data in q_item unless it's a kSecDbSHA1Attr. */
-    if (q->q_item && desc->kind != kSecDbSHA1Attr) {
-        CFDictionarySetValue(q->q_item, desc->name, attr);
-    }
-
-    /* Convert attr to (sha1) digest if requested. */
-    if (desc->flags & kSecDbSHA1ValueInFlag) {
-        CFDataRef data = copyData(attr);
-        CFRelease(attr);
-        if (!data) {
-            SecError(errSecInternal, &q->q_error, CFSTR("failed to get attribute %@ data"), desc->name);
-            return;
-        }
-
-        CFMutableDataRef digest = CFDataCreateMutable(0, CC_SHA1_DIGEST_LENGTH);
-        CFDataSetLength(digest, CC_SHA1_DIGEST_LENGTH);
-        /* 64 bits cast: worst case is we generate the wrong hash */
-        assert((unsigned long)CFDataGetLength(data)<UINT32_MAX); /* Debug check. Correct as long as CFIndex is long */
-        CCDigest(kCCDigestSHA1, CFDataGetBytePtr(data), (CC_LONG)CFDataGetLength(data),
-                 CFDataGetMutableBytePtr(digest));
-        CFRelease(data);
-        attr = digest;
-    }
-
-    if (desc->kind != kSecDbAccessControlAttr) {
-        /* Record the new attr key, value in q_pairs. */
-        if (q->q_attr_end + 1 < q->q_pairs_count) {
-            q->q_pairs[q->q_attr_end].key = desc->name;
-            q->q_pairs[q->q_attr_end++].value = attr;
-        } else {
-            SecError(errSecInternal, &q->q_error, CFSTR("q_pairs overflow"));
-            CFReleaseSafe(attr);
-        }
-    } else {
-        CFReleaseSafe(attr);
-    }
-}
-
-void query_add_attribute(const void *key, const void *value, Query *q)
-{
-    if (CFEqual(key, kSecAttrDeriveSyncIDFromItemAttributes)) {
-        q->q_uuid_from_primary_key = CFBooleanGetValue(value);
-        return; /* skip the attribute so it isn't part of the search */
-    }
-
-    const SecDbAttr *desc = SecDbAttrWithKey(q->q_class, key, &q->q_error);
-    if (desc) {
-        query_add_attribute_with_desc(desc, value, q);
-
-        if (desc->kind == kSecDbAccessControlAttr) {
-            CFDataRef attr = (CFDataRef)CFDictionaryGetValue(q->q_item, desc->name);
-            if (attr) {
-                SecAccessControlRef access_control = SecAccessControlCreateFromData(kCFAllocatorDefault, attr, &q->q_error);
-                if (access_control) {
-                    query_set_access_control(q, access_control);
-                    CFRelease(access_control);
-                }
-            }
-        }
-
-        if (desc->kind == kSecDbAccessAttr) {
-            SecAccessControlRef access_control = SecAccessControlCreate(kCFAllocatorDefault, &q->q_error);
-            if (access_control) {
-                CFStringRef attr = (CFStringRef)CFDictionaryGetValue(q->q_item, desc->name);
-                if (attr) {
-                    if (SecAccessControlSetProtection(access_control, attr, &q->q_error))
-                        query_set_access_control(q, access_control);
-                }
-                CFRelease(access_control);
-            }
-        }
-    }
-}
-
-void query_add_or_attribute(const void *key, const void *value, Query *q)
-{
-    const SecDbAttr *desc = SecDbAttrWithKey(q->q_class, key, &q->q_error);
-    if (desc) {
-        CFTypeRef oldValue = CFDictionaryGetValue(q->q_item, desc->name);
-        CFMutableArrayRef array = NULL;
-        if (oldValue) {
-            if (isArray(oldValue)) {
-                array = (CFMutableArrayRef)CFRetain(oldValue);
-            } else {
-                array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-                CFArrayAppendValue(array, oldValue);
-            }
-            CFDictionaryRemoveValue(q->q_item, desc->name);
-        } else {
-            array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-        }
-        if (array) {
-            query_add_attribute_with_desc(desc, value, q);
-            CFTypeRef newValue = CFDictionaryGetValue(q->q_item, desc->name);
-            CFArrayAppendValue(array, newValue);
-            CFDictionarySetValue(q->q_item, desc->name, array);
-            CFRelease(array);
-        }
-    }
-}
-
-void query_add_not_attribute(const void *key, const void *value, Query *q)
-{
-    const SecDbAttr *desc = SecDbAttrWithKey(q->q_class, key, &q->q_error);
-    if (desc) {
-        CFTypeRef oldValue = CFDictionaryGetValue(q->q_item, desc->name);
-        CFMutableArrayRef array = NULL;
-        if (oldValue) {
-            if (isArray(oldValue)) {
-                array = (CFMutableArrayRef)CFRetain(oldValue);
-            } else {
-                // This should never run, as we shouldn't be turning a attr = value into a attr not in (value, value2)
-                secerror("negating %@ = %@ in query", desc->name, oldValue);
-                array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-                CFArrayAppendValue(array, kCFNull);
-                CFArrayAppendValue(array, oldValue);
-            }
-            CFDictionaryRemoveValue(q->q_item, desc->name);
-        } else {
-            array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-            CFArrayAppendValue(array, kCFNull);
-        }
-        if (array) {
-            query_add_attribute_with_desc(desc, value, q);
-            CFTypeRef newValue = CFDictionaryGetValue(q->q_item, desc->name);
-            CFArrayAppendValue(array, newValue);
-            CFDictionarySetValue(q->q_item, desc->name, array);
-            CFRelease(array);
-        }
-    }
-}
-
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, string starting with 'm'.
- value (ok) is a caller provided, non NULL CFTypeRef.
- */
-static void query_add_match(const void *key, const void *value, Query *q)
-{
-    /* Record the match key, value in q_pairs. */
-    --(q->q_match_begin);
-    q->q_pairs[q->q_match_begin].key = key;
-    q->q_pairs[q->q_match_begin].value = value;
-
-    if (CFEqual(kSecMatchLimit, key)) {
-        /* Figure out what the value for kSecMatchLimit is if specified. */
-        if (CFGetTypeID(value) == CFNumberGetTypeID()) {
-            if (!CFNumberGetValue(value, kCFNumberCFIndexType, &q->q_limit))
-                SecError(errSecItemInvalidValue, &q->q_error, CFSTR("failed to convert match limit %@ to CFIndex"), value);
-        } else if (CFEqual(kSecMatchLimitAll, value)) {
-            q->q_limit = kSecMatchUnlimited;
-        } else if (CFEqual(kSecMatchLimitOne, value)) {
-            q->q_limit = 1;
-        } else {
-            SecError(errSecItemInvalidValue, &q->q_error, CFSTR("unsupported match limit %@"), value);
-        }
-    } else if (CFEqual(kSecMatchIssuers, key) &&
-               (CFGetTypeID(value) == CFArrayGetTypeID()))
-    {
-        CFMutableArrayRef canonical_issuers = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-        if (canonical_issuers) {
-            CFIndex i, count = CFArrayGetCount(value);
-            for (i = 0; i < count; i++) {
-                CFTypeRef issuer_data = CFArrayGetValueAtIndex(value, i);
-                CFDataRef issuer_canonical = NULL;
-                if (CFDataGetTypeID() == CFGetTypeID(issuer_data))
-                    issuer_canonical = SecDistinguishedNameCopyNormalizedContent((CFDataRef)issuer_data);
-                if (issuer_canonical) {
-                    CFArrayAppendValue(canonical_issuers, issuer_canonical);
-                    CFRelease(issuer_canonical);
-                }
-            }
-
-            if (CFArrayGetCount(canonical_issuers) > 0) {
-                q->q_match_issuer = canonical_issuers;
-            } else
-                CFRelease(canonical_issuers);
-        }
-    } else if (CFEqual(kSecMatchPolicy, key)) {
-        if (CFGetTypeID(value) != CFArrayGetTypeID()) {
-            SecError(errSecParam, &q->q_error, CFSTR("unsupported value for kSecMatchPolicy attribute"));
-            return;
-        }
-        xpc_object_t policiesArrayXPC = _CFXPCCreateXPCObjectFromCFObject(value);
-        if (!policiesArrayXPC) {
-            SecError(errSecParam, &q->q_error, CFSTR("unsupported kSecMatchPolicy object in query"));
-            return;
-        }
-
-        CFArrayRef policiesArray = SecPolicyXPCArrayCopyArray(policiesArrayXPC, &q->q_error);
-        xpc_release(policiesArrayXPC);
-        if (!policiesArray)
-            return;
-
-        if (CFArrayGetCount(policiesArray) != 1 || CFGetTypeID(CFArrayGetValueAtIndex(policiesArray, 0)) != SecPolicyGetTypeID()) {
-            CFRelease(policiesArray);
-            SecError(errSecParam, &q->q_error, CFSTR("unsupported array of policies"));
-            return;
-        }
-
-        query_set_policy(q, (SecPolicyRef)CFArrayGetValueAtIndex(policiesArray, 0));
-        CFRelease(policiesArray);
-    } else if (CFEqual(kSecMatchValidOnDate, key)) {
-        if (CFGetTypeID(value) == CFNullGetTypeID()) {
-            CFDateRef date = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
-            query_set_valid_on_date(q, date);
-            CFRelease(date);
-        } else if (CFGetTypeID(value) == CFDateGetTypeID()) {
-            query_set_valid_on_date(q, value);
-        } else {
-            SecError(errSecParam, &q->q_error, CFSTR("unsupported value for kSecMatchValidOnDate attribute"));
-            return;
-        }
-    } else if (CFEqual(kSecMatchTrustedOnly, key)) {
-        if ((CFGetTypeID(value) == CFBooleanGetTypeID())) {
-            query_set_trusted_only(q, value);
-        } else {
-            SecError(errSecParam, &q->q_error, CFSTR("unsupported value for kSecMatchTrustedOnly attribute"));
-            return;
-        }
-    }
-}
-
-static bool query_set_class(Query *q, CFStringRef c_name, CFErrorRef *error) {
-    const SecDbClass *value;
-    if (c_name && CFGetTypeID(c_name) == CFStringGetTypeID() &&
-        (value = kc_class_with_name(c_name)) &&
-        (q->q_class == 0 || q->q_class == value)) {
-        q->q_class = value;
-        return true;
-    }
-
-    if (error && !*error)
-        SecError((c_name ? errSecNoSuchClass : errSecItemClassMissing), error, CFSTR("can find class named: %@"), c_name);
-
-
-    return false;
-}
-
-static const SecDbClass *query_get_class(CFDictionaryRef query, CFErrorRef *error) {
-    CFStringRef c_name = NULL;
-    const void *value = CFDictionaryGetValue(query, kSecClass);
-    if (isString(value)) {
-        c_name = value;
-    } else {
-        value = CFDictionaryGetValue(query, kSecValuePersistentRef);
-        if (isData(value)) {
-            CFDataRef pref = value;
-            _SecItemParsePersistentRef(pref, &c_name, NULL, NULL);
-        }
-    }
-
-    if (c_name && (value = kc_class_with_name(c_name))) {
-        return value;
-    } else {
-        if (c_name)
-            SecError(errSecNoSuchClass, error, CFSTR("can't find class named: %@"), c_name);
-        else
-            SecError(errSecItemClassMissing, error, CFSTR("query missing class name"));
-        return NULL;
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, string starting with 'c'.
- value (ok) is a caller provided, non NULL CFTypeRef.
- */
-static void query_add_class(const void *key, const void *value, Query *q)
-{
-    if (CFEqual(key, kSecClass)) {
-        query_set_class(q, value, &q->q_error);
-    } else {
-        SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_class: key %@ is not %@"), key, kSecClass);
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, string starting with 'r'.
- value (ok) is a caller provided, non NULL CFTypeRef.
- */
-static void query_add_return(const void *key, const void *value, Query *q)
-{
-    ReturnTypeMask mask;
-    if (CFGetTypeID(value) != CFBooleanGetTypeID()) {
-        SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_return: value %@ is not CFBoolean"), value);
-        return;
-    }
-
-    int set_it = CFEqual(value, kCFBooleanTrue);
-
-    if (CFEqual(key, kSecReturnData))
-        mask = kSecReturnDataMask;
-    else if (CFEqual(key, kSecReturnAttributes))
-        mask = kSecReturnAttributesMask;
-    else if (CFEqual(key, kSecReturnRef))
-        mask = kSecReturnRefMask;
-    else if (CFEqual(key, kSecReturnPersistentRef))
-        mask = kSecReturnPersistentRefMask;
-    else {
-        SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_return: unknown key %@"), key);
-        return;
-    }
-
-    if ((q->q_return_type & mask) && !set_it) {
-        /* Clear out this bit (it's set so xor with the mask will clear it). */
-        q->q_return_type ^= mask;
-    } else if (!(q->q_return_type & mask) && set_it) {
-        /* Set this bit. */
-        q->q_return_type |= mask;
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, string starting with 'u'.
- value (ok since q_use_item_list is unused) is a caller provided, non
- NULL CFTypeRef.
- */
-static void query_add_use(const void *key, const void *value, Query *q)
-{
-    // Gotta use a string literal because we just outlawed this symbol on iOS
-    if (CFEqual(key, CFSTR("u_ItemList"))) {
-        /* TODO: Add sanity checking when we start using this. */
-        q->q_use_item_list = value;
-    } else if (CFEqual(key, kSecUseTombstones)) {
-        if (CFGetTypeID(value) == CFBooleanGetTypeID()) {
-            q->q_use_tomb = value;
-        } else if (CFGetTypeID(value) == CFNumberGetTypeID()) {
-            q->q_use_tomb = CFBooleanGetValue(value) ? kCFBooleanTrue : kCFBooleanFalse;
-        } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
-            q->q_use_tomb = CFStringGetIntValue(value) ? kCFBooleanTrue : kCFBooleanFalse;
-        } else {
-            SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is neither CFBoolean nor CFNumber"), value, key);
-            return;
-        }
-    } else if (CFEqual(key, kSecUseCredentialReference)) {
-        if (isData(value)) {
-            CFRetainAssign(q->q_use_cred_handle, value);
-        } else {
-            SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not CFData"), value, key);
-            return;
-        }
-    } else if (CFEqual(key, kSecUseAuthenticationUI)) {
-        if (isString(value)) {
-            q->q_skip_acl_items = CFEqualSafe(kSecUseAuthenticationUISkip, value);
-        } else {
-            SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not CFString"), value, key);
-            return;
-        }
-#if TARGET_OS_IPHONE
-    } else if (CFEqual(key, kSecUseSystemKeychain)) {
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
-        q->q_keybag = KEYBAG_DEVICE;
-#endif
-        q->q_system_keychain = true;
-    } else if (CFEqual(key, kSecUseSyncBubbleKeychain)) {
-        if (isNumber(value) && CFNumberGetValue(value, kCFNumberSInt32Type, &q->q_sync_bubble) && q->q_sync_bubble > 0) {
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
-            q->q_keybag = KEYBAG_DEVICE;
-#endif
-        } else {
-            SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not valid uid"), value, key);
-            return;
-        }
-#endif
-    } else {
-        SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_use: unknown key %@"), key);
-        return;
-    }
-}
-
-static void query_set_data(const void *value, Query *q) {
-    if (!isData(value)) {
-        SecError(errSecItemInvalidValue, &q->q_error, CFSTR("set_data: value %@ is not type data"), value);
-    } else {
-        q->q_data = value;
-        if (q->q_item)
-            CFDictionarySetValue(q->q_item, kSecValueData, value);
-    }
-}
-
-static void query_set_token_persistent_ref(Query *q, CFDictionaryRef token_persistent_ref) {
-    if (token_persistent_ref) {
-        query_add_attribute(kSecAttrTokenID, CFDictionaryGetValue(token_persistent_ref, kSecAttrTokenID), q);
-        CFRetainAssign(q->q_token_object_id, CFDictionaryGetValue(token_persistent_ref, kSecAttrTokenOID));
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, string starting with 'u'.
- value (ok) is a caller provided, non NULL CFTypeRef.
- */
-static void query_add_value(const void *key, const void *value, Query *q)
-{
-    if (CFEqual(key, kSecValueData)) {
-        query_set_data(value, q);
-#ifdef NO_SERVER
-    } else if (CFEqual(key, kSecValueRef)) {
-        q->q_ref = value;
-        /* TODO: Add value type sanity checking. */
-#endif
-    } else if (CFEqual(key, kSecValuePersistentRef)) {
-        CFStringRef c_name;
-        CFDictionaryRef token_persistent_ref = NULL;
-        if (_SecItemParsePersistentRef(value, &c_name, &q->q_row_id, &token_persistent_ref)) {
-            query_set_class(q, c_name, &q->q_error);
-            query_set_token_persistent_ref(q, token_persistent_ref);
-            CFReleaseNull(token_persistent_ref);
-        } else
-            SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_value: value %@ is not a valid persitent ref"), value);
-    } else {
-        SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_value: unknown key %@"), key);
-        return;
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, unchecked.
- value (ok) is a caller provided, unchecked.
- */
-static void query_update_applier(const void *key, const void *value,
-                                 void *context)
-{
-    Query *q = (Query *)context;
-    /* If something went wrong there is no point processing any more args. */
-    if (q->q_error)
-        return;
-
-    /* Make sure we have a string key. */
-    if (!isString(key)) {
-        SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("update_applier: unknown key type %@"), key);
-        return;
-    }
-
-    if (!value) {
-        SecError(errSecItemInvalidValue, &q->q_error, CFSTR("update_applier: key %@ has NULL value"), key);
-        return;
-    }
-
-    if (CFEqual(key, CFSTR("musr"))) {
-        secnotice("item", "update_applier: refusing to update musr");
-        return;
-    }
-
-    if (CFEqual(key, kSecValueData)) {
-        query_set_data(value, q);
-    } else {
-        query_add_attribute(key, value, q);
-    }
-}
-
-/* AUDIT[securityd](done):
- key (ok) is a caller provided, unchecked.
- value (ok) is a caller provided, unchecked.
- */
-static void query_applier(const void *key, const void *value, void *context)
-{
-    Query *q = (Query *)context;
-    /* If something went wrong there is no point processing any more args. */
-    if (q->q_error)
-        return;
-
-    /* Make sure we have a key. */
-    if (!key) {
-        SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("applier: NULL key"));
-        return;
-    }
-
-    /* Make sure we have a value. */
-    if (!value) {
-        SecError(errSecItemInvalidValue, &q->q_error, CFSTR("applier: key %@ has NULL value"), key);
-        return;
-    }
-
-    /* Figure out what type of key we are dealing with. */
-    CFTypeID key_id = CFGetTypeID(key);
-    if (key_id == CFStringGetTypeID()) {
-        CFIndex key_len = CFStringGetLength(key);
-        /* String keys can be different things.  The subtype is determined by:
-         length 4 strings are all attributes.  Otherwise the first char
-         determines the type:
-         c: class must be kSecClass
-         m: match like kSecMatchPolicy
-         r: return like kSecReturnData
-         u: use keys
-         v: value
-         f: callbacks (ignored by the query applier)
-         */
-        if (key_len == 4) {
-            /* attributes */
-            query_add_attribute(key, value, q);
-        } else if (key_len > 1) {
-            // We added a database column named 'persistref', which is returned as an attribute but doesn't comply with
-            // these matching rules. skip it for now, since it isn't filled in anyway.
-            if(CFEqualSafe(key, CFSTR("persistref"))) {
-                return;
-            }
-
-            UniChar k_first_char = CFStringGetCharacterAtIndex(key, 0);
-            switch (k_first_char)
-            {
-                case 'c': /* class */
-                    query_add_class(key, value, q);
-                    break;
-                case 'm': /* match */
-                    query_add_match(key, value, q);
-                    break;
-                case 'r': /* return */
-                    query_add_return(key, value, q);
-                    break;
-                case 'u': /* use */
-                    query_add_use(key, value, q);
-                    break;
-                case 'v': /* value */
-                    query_add_value(key, value, q);
-                    break;
-                case 'f':
-                    break;
-                default:
-                    SecError(errSecItemInvalidKey, &q->q_error, CFSTR("applier: key %@ invalid"), key);
-                    break;
-            }
-        } else {
-            SecError(errSecItemInvalidKey, &q->q_error, CFSTR("applier: key %@ invalid length"), key);
-        }
-    } else if (key_id == CFNumberGetTypeID()) {
-        /* Numeric keys are always (extended) attributes. */
-        /* TODO: Why is this here? query_add_attribute() doesn't take numbers. */
-        query_add_attribute(key, value, q);
-    } else {
-        /* We only support string and number type keys. */
-        SecError(errSecItemInvalidKeyType, &q->q_error, CFSTR("applier: key %@ neither string nor number"), key);
-    }
-}
-
-static CFStringRef query_infer_keyclass(Query *q, CFStringRef agrp) {
-    /* apsd are always dku. */
-    if (CFEqual(agrp, CFSTR("com.apple.apsd"))) {
-        return kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate;
-    }
-    /* All other certs or in the apple agrp is dk. */
-    if (q->q_class == cert_class()) {
-        /* third party certs are always dk. */
-        return kSecAttrAccessibleAlwaysPrivate;
-    }
-    /* The rest defaults to ak. */
-    return kSecAttrAccessibleWhenUnlocked;
-}
-
-void query_ensure_access_control(Query *q, CFStringRef agrp) {
-    if (q->q_access_control == 0) {
-        CFStringRef accessible = query_infer_keyclass(q, agrp);
-        query_add_attribute(kSecAttrAccessible, accessible, q);
-    }
-}
-
-bool query_error(Query *q, CFErrorRef *error) {
-    CFErrorRef tmp = q->q_error;
-    q->q_error = NULL;
-    return SecErrorPropagate(tmp, error);
-}
-
-bool query_destroy(Query *q, CFErrorRef *error) {
-    bool ok = query_error(q, error);
-    CFIndex ix, attr_count = query_attr_count(q);
-    for (ix = 0; ix < attr_count; ++ix) {
-        CFReleaseSafe(query_attr_at(q, ix).value);
-    }
-    CFReleaseSafe(q->q_item);
-    CFReleaseSafe(q->q_musrView);
-    CFReleaseSafe(q->q_primary_key_digest);
-    CFReleaseSafe(q->q_match_issuer);
-    CFReleaseSafe(q->q_access_control);
-    CFReleaseSafe(q->q_use_cred_handle);
-    CFReleaseSafe(q->q_caller_access_groups);
-    CFReleaseSafe(q->q_match_policy);
-    CFReleaseSafe(q->q_match_valid_on_date);
-    CFReleaseSafe(q->q_match_trusted_only);
-    CFReleaseSafe(q->q_token_object_id);
-
-    free(q);
-    return ok;
-}
-
-bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error) {
-    if (ok && !q->q_error && (q->q_sync_changed || (q->q_changed && !SecMUSRIsSingleUserView(q->q_musrView)))) {
-        SecKeychainChanged();
-    }
-    return query_destroy(q, error) && ok;
-}
-
-/* Allocate and initialize a Query object for query. */
-Query *query_create(const SecDbClass *qclass,
-                    CFDataRef musr,
-                    CFDictionaryRef query,
-                    CFErrorRef *error)
-{
-    if (!qclass) {
-        if (error && !*error)
-            SecError(errSecItemClassMissing, error, CFSTR("Missing class"));
-        return NULL;
-    }
-
-    if (musr == NULL)
-        musr = SecMUSRGetSingleUserKeychainUUID();
-
-    /* Number of pairs we need is the number of attributes in this class
-     plus the number of keys in the dictionary, minus one for each key in
-     the dictionary that is a regular attribute. */
-    CFIndex key_count = SecDbClassAttrCount(qclass);
-    if (key_count == 0) {
-        // Identities claim to have 0 attributes, but they really support any keys or cert attribute.
-        key_count = SecDbClassAttrCount(cert_class()) + SecDbClassAttrCount(keys_class());
-    }
-
-    if (query) {
-        key_count += CFDictionaryGetCount(query);
-        SecDbForEachAttr(qclass, attr) {
-            if (CFDictionaryContainsKey(query, attr->name))
-                --key_count;
-        }
-    }
-
-    if (key_count > QUERY_KEY_LIMIT) {
-        if (error && !*error)
-        {
-            secerror("key_count: %ld, QUERY_KEY_LIMIT: %d", (long)key_count, QUERY_KEY_LIMIT);
-            SecError(errSecItemIllegalQuery, error, CFSTR("Past query key limit"));
-        }
-        return NULL;
-    }
-
-    Query *q = calloc(1, sizeof(Query) + sizeof(Pair) * key_count);
-    if (q == NULL) {
-        if (error && !*error)
-            SecError(errSecAllocate, error, CFSTR("Out of memory"));
-        return NULL;
-    }
-
-    q->q_pairs_count = key_count;
-    q->q_musrView = (CFDataRef)CFRetain(musr);
-    q->q_uuid_from_primary_key = false;
-    q->q_keybag = KEYBAG_DEVICE;
-    q->q_class = qclass;
-    q->q_match_begin = q->q_match_end = key_count;
-    q->q_item = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
-    return q;
-}
-
-/* Parse query for a Query object q. */
-static bool query_parse_with_applier(Query *q, CFDictionaryRef query,
-                                     CFDictionaryApplierFunction applier,
-                                     CFErrorRef *error) {
-    CFDictionaryApplyFunction(query, applier, q);
-    return query_error(q, error);
-}
-
-/* Parse query for a Query object q. */
-static bool query_parse(Query *q, CFDictionaryRef query,
-                        CFErrorRef *error) {
-    return query_parse_with_applier(q, query, query_applier, error);
-}
-
-/* Parse query for a Query object q. */
-bool query_update_parse(Query *q, CFDictionaryRef update,
-                               CFErrorRef *error) {
-    return query_parse_with_applier(q, update, query_update_applier, error);
-}
-
-Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error) {
-    Query *q;
-    q = query_create(query_get_class(query, error), musr, query, error);
-    if (q) {
-        q->q_limit = limit;
-        if (!query_parse(q, query, error)) {
-            query_destroy(q, error);
-            return NULL;
-        }
-        if (!q->q_sync && !q->q_row_id && !q->q_token_object_id) {
-            /* query did not specify a kSecAttrSynchronizable attribute,
-             * and did not contain a persistent reference. */
-            query_add_attribute(kSecAttrSynchronizable, kCFBooleanFalse, q);
-        }
-    }
-    return q;
-}
-
-
-void
-query_set_caller_access_groups(Query *q, CFArrayRef caller_access_groups) {
-    CFRetainAssign(q->q_caller_access_groups, caller_access_groups);
-}
-
-void
-query_set_policy(Query *q, SecPolicyRef policy) {
-    CFRetainAssign(q->q_match_policy, policy);
-}
-
-void query_set_valid_on_date(Query *q, CFDateRef date) {
-    CFRetainAssign(q->q_match_valid_on_date, date);
-}
-
-void query_set_trusted_only(Query *q, CFBooleanRef trusted_only) {
-    CFRetainAssign(q->q_match_trusted_only, trusted_only);
-}