]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/lib/SecItem.cpp
Security-59306.140.5.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / SecItem.cpp
index c25efd5cc5fb197dfa8e10e6d156e88b3bd776b9..2cdb17f942f5d256d6dc24c426f987c6dfa1d390 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006-2015 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2006-2019 Apple Inc. All Rights Reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  */
 
 #include "SecBridge.h"
-#include "SecInternal.h"
+#include <Security/SecInternal.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <security_utilities/cfutilities.h>
 #include <Security/SecBase.h>
 #include <Security/SecKeychainItem.h>
 #include <Security/SecCertificate.h>
+#include <Security/SecCertificatePriv.h>
 #include <sys/param.h>
 #include "cssmdatetime.h"
-#include "SecItem.h"
-#include "SecItemPriv.h"
-#include "SecIdentitySearchPriv.h"
-#include "SecKeychainPriv.h"
-#include "SecCertificatePriv.h"
-#include "SecCertificatePrivP.h"
+#include <Security/SecItem.h>
+#include <Security/SecItemPriv.h>
+#include <Security/SecIdentitySearchPriv.h>
+#include <Security/SecKeychainPriv.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecPolicyPriv.h>
 #include "TrustAdditions.h"
 #include "TrustSettingsSchema.h"
 #include <Security/SecTrustPriv.h>
 #include "utilities/array_size.h"
+#include "utilities/SecCFWrappers.h"
 
 #include <AssertMacros.h>
 #include <syslog.h>
@@ -53,6 +55,8 @@
 
 #include <login/SessionAgentCom.h>
 #include <login/SessionAgentStatusCom.h>
+#include <os/activity.h>
+#include <CoreFoundation/CFPriv.h>
 
 
 const uint8_t kUUIDStringLength = 36;
@@ -73,9 +77,13 @@ OSStatus SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAtt
 OSStatus SecItemValidateAppleApplicationGroupAccess(CFStringRef group);
 CFDictionaryRef SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass,
        bool iOSOut, bool pruneMatch, bool pruneSync, bool pruneReturn, bool pruneData, bool pruneAccess);
+    
+bool _SecItemParsePersistentRef(CFDataRef persistent_ref, CFStringRef *return_class,
+                                long long int *return_rowid, CFDictionaryRef *return_token_attrs);
 }
 
 static Boolean SecItemSynchronizable(CFDictionaryRef query);
+static CFArrayRef _CopyMatchingIssuers(CFArrayRef issuers);
 
 static void secitemlog(int priority, const char *format, ...)
 {
@@ -532,6 +540,12 @@ _ConvertNewFormatToOldFormat(
        SecKeychainAttributeList* &attrList
        )
 {
+    // make storage to extract the dictionary items
+    CFIndex itemsInDictionary = CFDictionaryGetCount(dictionaryRef);
+    if (itemsInDictionary > 10000) {
+        return errSecParam;
+    }
+
        // get the keychain attributes array from the data item
        // here's the problem.  On the one hand, we have a dictionary that is purported to contain
        // attributes for our type.  On the other hand, the dictionary may contain items we don't support,
@@ -540,15 +554,10 @@ _ConvertNewFormatToOldFormat(
        // setup the return
        attrList = (SecKeychainAttributeList*) calloc(1, sizeof(SecKeychainAttributeList));
 
-       // make storage to extract the dictionary items
-       CFIndex itemsInDictionary = CFDictionaryGetCount(dictionaryRef);
-       CFTypeRef keys[itemsInDictionary];
-       CFTypeRef values[itemsInDictionary];
-
-       CFTypeRef *keysPtr = keys;
-       CFTypeRef *valuesPtr = values;
+       std::vector<CFTypeRef> keys(itemsInDictionary);
+       std::vector<CFTypeRef> values(itemsInDictionary);
 
-       CFDictionaryGetKeysAndValues(dictionaryRef, keys, values);
+       CFDictionaryGetKeysAndValues(dictionaryRef, keys.data(), values.data());
 
        // count the number of items we are interested in
        CFIndex count = 0;
@@ -556,12 +565,12 @@ _ConvertNewFormatToOldFormat(
 
        // since this is one of those nasty order n^2 loops, we cache as much stuff as possible so that
        // we don't pay the price for this twice
-       SecKeychainAttrType tags[itemsInDictionary];
-       ItemRepresentation types[itemsInDictionary];
+       std::vector<SecKeychainAttrType> tags(itemsInDictionary);
+       std::vector<ItemRepresentation> types(itemsInDictionary);
 
        for (i = 0; i < itemsInDictionary; ++i)
        {
-               CFTypeRef key = keysPtr[i];
+               CFTypeRef key = keys[i];
 
                int j;
                for (j = 0; j < infoNumItems; ++j)
@@ -578,28 +587,33 @@ _ConvertNewFormatToOldFormat(
                if (j >= infoNumItems)
                {
                        // if we got here, we aren't interested in this item.
-                       valuesPtr[i] = NULL;
+                       values[i] = NULL;
                }
        }
 
        // now we can make the result array
        attrList->count = (UInt32)count;
-       attrList->attr = (SecKeychainAttribute*) malloc(sizeof(SecKeychainAttribute) * count);
 
-       // fill out the array
-       int resultPointer = 0;
-       for (i = 0; i < itemsInDictionary; ++i)
-       {
-               if (values[i] != NULL)
-               {
-                       attrList->attr[resultPointer].tag = tags[i];
+    if(count == 0) {
+        attrList->attr = NULL;
+    } else {
+        attrList->attr = (SecKeychainAttribute*) calloc(count, sizeof(SecKeychainAttribute));
 
-                       // we have to clone the data pointer.  The caller will need to make sure to throw these away
-                       // with _FreeAttrList when it is done...
-                       attrList->attr[resultPointer].data = CloneDataByType(types[i], valuesPtr[i], attrList->attr[resultPointer].length);
-                       resultPointer += 1;
-               }
-       }
+        // fill out the array
+        int resultPointer = 0;
+        for (i = 0; i < itemsInDictionary; ++i)
+        {
+            if (values[i] != NULL)
+            {
+                attrList->attr[resultPointer].tag = tags[i];
+
+                // we have to clone the data pointer.  The caller will need to make sure to throw these away
+                // with _FreeAttrList when it is done...
+                attrList->attr[resultPointer].data = CloneDataByType(types[i], values[i], attrList->attr[resultPointer].length);
+                resultPointer += 1;
+            }
+        }
+    }
 
        return errSecSuccess;
 }
@@ -663,6 +677,7 @@ _ConvertOldFormatToNewFormat(
                                                        break;
                                                default:
                                                        stringRef = CFStringCreateWithFormat(allocator, NULL, CFSTR("%d"), keyRecordValue);
+                            retainString = false;
                                                        break;
                                        }
                                        if (stringRef) {
@@ -949,6 +964,7 @@ _CreateAttributesDictionaryFromKeyItem(
                                                        break;
                                                default:
                                                        stringRef = CFStringCreateWithFormat(allocator, NULL, CFSTR("%u"), (unsigned int)keyRecordValue);
+                            retainString = false;
                                                        break;
                                        }
                                        if (stringRef) {
@@ -1571,7 +1587,7 @@ _CreateSecKeychainKeyAttributeListFromDictionary(
 
        // [5] get the kSecKeyKeyType number
        if (CFDictionaryGetValueIfPresent(attrDictionary, kSecAttrKeyType, (const void **)&value) && value) {
-               UInt32 keyAlgValue = _SecAlgorithmTypeFromSecAttrKeyType(kSecAttrKeyType);
+               UInt32 keyAlgValue = _SecAlgorithmTypeFromSecAttrKeyType(value);
                if (keyAlgValue != 0) {
                        attrListPtr->attr[attrListPtr->count].data = malloc(sizeof(UInt32));
                        require_action(attrListPtr->attr[attrListPtr->count].data != NULL, malloc_number_failed, status = errSecBufferTooSmall);
@@ -2233,7 +2249,7 @@ _SafeSecKeychainItemDelete(
                }
 
                // create SecTrustedApplicationRef for current application/tool
-               CFReleaseSafe(currentAppRef);
+               CFReleaseNull(currentAppRef);
                status = SecTrustedApplicationCreateFromPath(NULL, &currentAppRef);
                require_noerr(status, finish);
                require_quiet(currentAppRef != NULL, finish);
@@ -2351,24 +2367,11 @@ _ReplaceKeychainItem(
 
        // make attribute list for new item (the data is still owned by attrList)
        newAttrList.count = attrList->count;
-       newAttrList.attr = (SecKeychainAttribute *) malloc(sizeof(SecKeychainAttribute) * attrList->count);
+       newAttrList.attr = (SecKeychainAttribute *) calloc(attrList->count, sizeof(SecKeychainAttribute));
        int i, newCount;
        for (i=0, newCount=0; i < attrList->count; i++) {
                if (attrList->attr[i].length > 0) {
                        newAttrList.attr[newCount++] = attrList->attr[i];
-               #if 0
-                       // debugging code to log item attributes
-                       SecKeychainAttrType tag = attrList->attr[i].tag;
-                       SecKeychainAttrType htag=(SecKeychainAttrType)OSSwapConstInt32(tag);
-                       char tmp[sizeof(SecKeychainAttrType) + 1];
-                       char tmpdata[attrList->attr[i].length + 1];
-                       memcpy(tmp, &htag, sizeof(SecKeychainAttrType));
-                       tmp[sizeof(SecKeychainAttrType)]=0;
-                       memcpy(tmpdata, attrList->attr[i].data, attrList->attr[i].length);
-                       tmpdata[attrList->attr[i].length]=0;
-                       secitemlog(priority, "item attr '%s' = %d bytes: \"%s\"",
-                               tmp, (int)attrList->attr[i].length, tmpdata);
-               #endif
                }
        }
        newAttrList.count = newCount;
@@ -2509,7 +2512,7 @@ _UpdateKeychainItem(CFTypeRef item, CFDictionaryRef changedAttributes)
        }
        // update item
        status = SecKeychainItemModifyContent(itemToUpdate,
-                               (changeAttrList->count == 0) ? NULL : changeAttrList,
+                               (!changeAttrList || changeAttrList->count == 0) ? NULL : changeAttrList,
                                (theData != NULL) ? (UInt32)CFDataGetLength(theData) : 0,
                                (theData != NULL) ? CFDataGetBytePtrVoid(theData) : NULL);
        require_noerr(status, update_failed);
@@ -2524,7 +2527,7 @@ update_failed:
                (itemClass == kSecInternetPasswordItemClass || itemClass == kSecGenericPasswordItemClass)) {
                // if we got a cryptographic failure updating a password item, it needs to be replaced
                status = _ReplaceKeychainItem(itemToUpdate,
-                                       (changeAttrList->count == 0) ? NULL : changeAttrList,
+                                       (!changeAttrList ||  changeAttrList->count == 0) ? NULL : changeAttrList,
                                        theData);
        }
        if (itemToUpdate)
@@ -2828,6 +2831,7 @@ struct SecItemParams {
        CFTypeRef keyClass;                                     // value for kSecAttrKeyClass (may be NULL)
        CFTypeRef service;                                      // value for kSecAttrService (may be NULL)
        CFTypeRef issuer;                                       // value for kSecAttrIssuer (may be NULL)
+       CFTypeRef matchIssuers;                                 // value for kSecMatchIssuers (may be NULL)
        CFTypeRef serialNumber;                         // value for kSecAttrSerialNumber (may be NULL)
        CFTypeRef search;                                       // search reference for this query (SecKeychainSearchRef or SecIdentitySearchRef)
        CFTypeRef assumedKeyClass;                      // if no kSecAttrKeyClass provided, holds the current class we're searching for
@@ -2939,6 +2943,7 @@ _FreeSecItemParams(SecItemParams *itemParams)
        if (itemParams->keyClass) CFRelease(itemParams->keyClass);
        if (itemParams->service) CFRelease(itemParams->service);
        if (itemParams->issuer) CFRelease(itemParams->issuer);
+       if (itemParams->matchIssuers) CFRelease(itemParams->matchIssuers);
        if (itemParams->serialNumber) CFRelease(itemParams->serialNumber);
        if (itemParams->search) CFRelease(itemParams->search);
        if (itemParams->access) CFRelease(itemParams->access);
@@ -2957,6 +2962,7 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error)
 {
        OSStatus status;
        CFTypeRef value = NULL;
+    CFDictionaryRef policyDict = NULL;
        SecItemParams *itemParams = (SecItemParams *)calloc(1, sizeof(struct SecItemParams));
 
        require_action(itemParams != NULL, error_exit, status = errSecAllocate);
@@ -3065,6 +3071,33 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error)
                require_action(!(itemParams->itemClass == 0 && !itemParams->useItems), error_exit, status = errSecItemClassMissing);
        }
 
+    // kSecMatchIssuers is only permitted with identities or certificates.
+    // Convert the input issuers to normalized form.
+    require_noerr(status = _ValidateDictionaryEntry(dict, kSecMatchIssuers, (const void **)&itemParams->matchIssuers, CFArrayGetTypeID(), NULL), error_exit);
+    if (itemParams->matchIssuers) {
+        CFTypeRef allowCerts = CFDictionaryGetValue(itemParams->query, kSecUseCertificatesWithMatchIssuers);
+        require_action(itemParams->returnIdentity || (allowCerts && CFEqual(allowCerts, kCFBooleanTrue)), error_exit, status = errSecParam);
+        CFMutableArrayRef canonical_issuers = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+        CFArrayRef issuers = (CFArrayRef)itemParams->matchIssuers;
+        if (canonical_issuers) {
+            CFIndex i, count = CFArrayGetCount(issuers);
+            for (i = 0; i < count; i++) {
+                CFTypeRef issuer_data = CFArrayGetValueAtIndex(issuers, i);
+                CFDataRef issuer_canonical = NULL;
+                if (CFDataGetTypeID() == CFGetTypeID(issuer_data))
+                    issuer_canonical = SecDistinguishedNameCopyNormalizedSequence((CFDataRef)issuer_data);
+                if (issuer_canonical) {
+                    CFArrayAppendValue(canonical_issuers, issuer_canonical);
+                    CFRelease(issuer_canonical);
+                }
+            }
+            if (CFArrayGetCount(canonical_issuers) > 0) {
+                CFAssignRetained(itemParams->matchIssuers, canonical_issuers);
+            } else
+                CFRelease(canonical_issuers);
+        }
+    }
+
        itemParams->keyUsage = _CssmKeyUsageFromQuery(dict);
        itemParams->trustedOnly = CFDictionaryGetValueIfPresent(dict, kSecMatchTrustedOnly, (const void **)&value) && value && CFEqual(kCFBooleanTrue, value);
        itemParams->issuerAndSNToMatch = (itemParams->issuer != NULL && itemParams->serialNumber != NULL);
@@ -3113,12 +3146,18 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error)
                require_noerr(status, error_exit);
        }
 
-       // if we already have an item list (to add or find items in), we don't need an item class, attribute list or a search reference
+    // if we already have an item list (to add or find items in), we don't need a search reference
        if (itemParams->useItems) {
                if (itemParams->itemClass == 0) {
                        itemParams->itemClass = _ItemClassFromItemList(itemParams->useItems);
                }
-               status = errSecSuccess;
+
+        // build a SecKeychainAttributeList from the query dictionary for the specified item class
+        if (itemParams->itemClass != 0) {
+            status = _CreateSecKeychainAttributeListFromDictionary(dict, itemParams->itemClass, &itemParams->attrList);
+        } else {
+            status = errSecSuccess;
+        }
                goto error_exit; // all done here
        }
 
@@ -3127,12 +3166,12 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error)
        
     // if policy is a SMIME policy, copy email address in policy into emailAddrToMatch parameter
     if(itemParams->policy) {
-        CFDictionaryRef policyDict = SecPolicyCopyProperties(itemParams->policy);
+        policyDict = SecPolicyCopyProperties(itemParams->policy);
         CFStringRef oidStr = (CFStringRef) CFDictionaryGetValue(policyDict, kSecPolicyOid);
         if(oidStr && CFStringCompare(kSecPolicyAppleSMIME,oidStr,0) == 0) {
             require_noerr(status = _ValidateDictionaryEntry(policyDict, kSecPolicyName, (const void **)&itemParams->emailAddrToMatch, CFStringGetTypeID(), NULL), error_exit);
         }
-        CFRelease(policyDict);
+        CFReleaseNull(policyDict);
     }
 
        // create a search reference (either a SecKeychainSearchRef or a SecIdentitySearchRef)
@@ -3181,6 +3220,7 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error)
        }
 
 error_exit:
+    CFReleaseNull(policyDict);
        if (status) {
                _FreeSecItemParams(itemParams);
                itemParams = NULL;
@@ -3245,6 +3285,7 @@ _FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert)
 
        SecTrustResultType      trustResult;
        Boolean needChain = false;
+       Boolean needCSEKU = false;
        OSStatus status;
        if (!policy || !cert) return errSecParam;
 
@@ -3258,13 +3299,33 @@ _FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert)
                if(status) goto cleanup;
        }
 
-       /* Check whether this is the X509 Basic policy, which means chain building */
+       /* Check whether we can avoid full chain evaluation, based on policy */
        props = SecPolicyCopyProperties(policy);
        if (props) {
                CFTypeRef oid = (CFTypeRef) CFDictionaryGetValue(props, kSecPolicyOid);
                if (oid && (CFEqual(oid, kSecPolicyAppleX509Basic) ||
-                    CFEqual(oid, kSecPolicyAppleRevocation))) {
+                           CFEqual(oid, kSecPolicyAppleRevocation))) {
                        needChain = true;
+               } else if (oid && (CFEqual(oid, kSecPolicyAppleCodeSigning))) {
+                       needCSEKU = true;
+               }
+       }
+
+       /* If a code signing EKU purpose is needed, filter out certs without it here
+          to reduce log noise associated with evaluation failures. */
+       if (needCSEKU) {
+               CFDataRef eku = CFDataCreate(kCFAllocatorDefault,
+                                            oidExtendedKeyUsageCodeSigning.data,
+                                            oidExtendedKeyUsageCodeSigning.length);
+               if (eku) {
+                       if (!SecPolicyCheckCertExtendedKeyUsage(cert, eku)) {
+                               needCSEKU = false;
+                       }
+                       CFRelease(eku);
+               }
+               if (!needCSEKU) {
+                       status = errSecCertificateCannotOperate;
+                       goto cleanup;
                }
        }
 
@@ -3357,6 +3418,77 @@ _FilterWithTrust(Boolean trustedOnly, SecCertificateRef cert)
        return status;
 }
 
+static bool items_matching_issuer_parent(CFDataRef issuer, CFArrayRef issuers, int recurse) {
+    if (!issuers || CFArrayGetCount(issuers) == 0) { return false; }
+
+    /* We found a match, we're done. */
+    if (CFArrayContainsValue(issuers, CFRangeMake(0, CFArrayGetCount(issuers)), issuer)) { return true; }
+
+    /* Prevent infinite recursion */
+    if (recurse <= 0) { return false; }
+    recurse--;
+
+    /* Query for parents */
+    CFMutableDictionaryRef query = NULL;
+    CFTypeRef parents = NULL;
+    bool found = false;
+
+    require_quiet(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks,
+                                      &kCFTypeDictionaryValueCallBacks), out);
+    CFDictionaryAddValue(query, kSecClass, kSecClassCertificate);
+    CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue);
+    CFDictionaryAddValue(query, kSecAttrSubject, issuer);
+    CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll);
+    require_noerr_quiet(SecItemCopyMatching(query, &parents), out);
+
+    if (parents && CFArrayGetTypeID() == CFGetTypeID(parents)) {
+        CFIndex i, count = CFArrayGetCount((CFArrayRef)parents);
+        for (i = 0; i < count; i++) {
+            SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex((CFArrayRef)parents, i);
+            CFDataRef cert_issuer = SecCertificateCopyNormalizedIssuerSequence(cert);
+            if (CFEqual(cert_issuer, issuer)) {
+                // Self-issued cert, don't look for parents.
+                CFReleaseNull(cert_issuer);
+                continue;
+            }
+            found = items_matching_issuer_parent(cert_issuer, issuers, recurse);
+            CFReleaseNull(cert_issuer);
+            if (found) { break; }
+        }
+    } else if (parents && SecCertificateGetTypeID() == CFGetTypeID(parents)) {
+        SecCertificateRef cert = (SecCertificateRef)parents;
+        CFDataRef cert_issuer = SecCertificateCopyNormalizedIssuerSequence(cert);
+        require_action_quiet(!CFEqual(cert_issuer, issuer), out, CFReleaseNull(cert_issuer));
+        found = items_matching_issuer_parent(cert_issuer, issuers, recurse);
+        CFReleaseNull(cert_issuer);
+    }
+
+out:
+    CFReleaseNull(query);
+    CFReleaseNull(parents);
+    return found;
+}
+
+static OSStatus
+_FilterWithIssuers(CFArrayRef issuers, SecCertificateRef cert)
+{
+    if (!issuers || CFArrayGetCount(issuers) == 0) return errSecParam;
+    if (!cert) return errSecParam;
+
+    OSStatus status = errSecInternalError;
+
+    /* kSecMatchIssuers matches certificates where ANY certificate in the chain has this issuer.
+     * So we now need to recursively query the keychain for this cert's parents to determine if
+     * they match. (This is why we limited the use of this key in _CreateSecItemParamsFromDictionary.) */
+    CFDataRef issuer = SecCertificateCopyNormalizedIssuerSequence(cert);
+    if (items_matching_issuer_parent(issuer, issuers, 10)) {
+        status = errSecSuccess;
+    }
+
+    CFReleaseNull(issuer);
+    return status;
+}
+
 static SecKeychainItemRef
 CopyResolvedKeychainItem(CFTypeRef item)
 {
@@ -3465,16 +3597,17 @@ SecItemSearchCopyNext(SecItemParams *params, CFTypeRef *item)
        OSStatus status;
        CFTypeRef search = (params) ? params->search : NULL;
        CFTypeID typeID = (search) ? CFGetTypeID(search) : 0;
-       if (typeID == SecIdentitySearchGetTypeID()) {
+
+       if (search && typeID == SecIdentitySearchGetTypeID()) {
                status = SecIdentitySearchCopyNext((SecIdentitySearchRef)search, (SecIdentityRef*)item);
        }
-       else if (typeID == SecKeychainSearchGetTypeID()) {
+       else if (search && typeID == SecKeychainSearchGetTypeID()) {
                status = SecKeychainSearchCopyNext((SecKeychainSearchRef)search, (SecKeychainItemRef*)item);
                // Check if we need to refresh the search for the next key class
                while (status == errSecItemNotFound && params->assumedKeyClass != NULL)
                        status = UpdateKeychainSearchAndCopyNext(params, item);
        }
-       else if (typeID == 0 && (params->useItems || params->itemList)) {
+       else if (typeID == 0 && params && (params->useItems || params->itemList)) {
                // No search available, but there is an item list available.
                // Return the next candidate item from the caller's item list
                CFArrayRef itemList = (params->useItems) ? params->useItems : params->itemList;
@@ -3599,6 +3732,11 @@ FilterCandidateItem(CFTypeRef *item, SecItemParams *itemParams, SecIdentityRef *
                        }
                        // certificate item is trusted on this system
                }
+        if (itemParams->matchIssuers) {
+            status = _FilterWithIssuers((CFArrayRef)itemParams->matchIssuers, (SecCertificateRef) *item);
+            if (status) goto filterOut;
+            // certificate item has one of the issuers
+        }
        }
        if (itemParams->itemList) {
                Boolean foundMatch = FALSE;
@@ -3895,10 +4033,7 @@ static Boolean SecItemSynchronizable(CFDictionaryRef query)
 static Boolean SecItemIsIOSPersistentReference(CFTypeRef value)
 {
        if (value) {
-               /* Synchronizable persistent ref consists of the sqlite rowid and 4-byte class value */
-               const CFIndex kSynchronizablePersistentRefLength = sizeof(int64_t) + 4;
-               return (CFGetTypeID(value) == CFDataGetTypeID() &&
-                               CFDataGetLength((CFDataRef)value) == kSynchronizablePersistentRefLength);
+        return ::_SecItemParsePersistentRef((CFDataRef)value, NULL, NULL, NULL);
        }
        return false;
 }
@@ -3908,21 +4043,38 @@ extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref);
 //
 // Function to find out which keychains are targetted by the query.
 //
-static OSStatus SecItemCategorizeQuery(CFDictionaryRef query, bool &can_target_ios, bool &can_target_osx)
+static OSStatus SecItemCategorizeQuery(CFDictionaryRef query, bool &can_target_ios, bool &can_target_osx, bool &useDataProtectionKeychainFlag)
 {
        // By default, target both keychain.
        can_target_osx = can_target_ios = true;
+    useDataProtectionKeychainFlag = false;
 
        // Check no-legacy flag.
-    CFTypeRef value = CFDictionaryGetValue(query, kSecAttrNoLegacy);
-       if (value != NULL) {
-               can_target_ios = readNumber(value) != 0;
+    // it's iOS or bust if we're on MZ!
+    CFTypeRef useDataProtection = NULL;
+    if (_CFMZEnabled()) {
+        useDataProtection = kCFBooleanTrue;
+    }
+    else {
+        // In case your CFDict is dumb and compares by pointer equality we check both versions of the symbol
+        if (!CFDictionaryGetValueIfPresent(query, kSecUseDataProtectionKeychain, &useDataProtection)) {
+            // Ah the irony of ignoring deprecation while checking for a legacy-avoiding attribute
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+            useDataProtection = CFDictionaryGetValue(query, kSecAttrNoLegacy);
+#pragma clang diagnostic pop
+        }
+    }
+
+       if (useDataProtection != NULL) {
+        useDataProtectionKeychainFlag = readNumber(useDataProtection);
+               can_target_ios = useDataProtectionKeychainFlag;
                can_target_osx = !can_target_ios;
                return errSecSuccess;
        }
 
        // Check whether the query contains kSecValueRef and modify can_ flags according to the kind and type of the value.
-       value = CFDictionaryGetValue(query, kSecValueRef);
+       CFTypeRef value = CFDictionaryGetValue(query, kSecValueRef);
        if (value != NULL) {
                CFTypeID typeID = CFGetTypeID(value);
                if (typeID == SecKeyGetTypeID()) {
@@ -3986,6 +4138,13 @@ static OSStatus SecItemCategorizeQuery(CFDictionaryRef query, bool &can_target_i
                can_target_ios = can_target_ios && !CFDictionaryContainsKey(query, *osx_only_items[i]);
        }
 
+    // Absence of all of kSecItemClass, kSecValuePersistentRef, and kSecValueRef means that the query can't target iOS
+    if(CFDictionaryGetValue(query, kSecClass) == NULL &&
+       CFDictionaryGetValue(query, kSecValuePersistentRef) == NULL &&
+       CFDictionaryGetValue(query, kSecValueRef) == NULL) {
+        can_target_ios = false;
+    }
+
        return (can_target_ios || can_target_osx) ? errSecSuccess : errSecParam;
 }
 
@@ -4151,7 +4310,7 @@ SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes) {
                CFTypeRef v;
 
     Item item = Item(item_class, &attrs, 0, "");
-               v = CFDictionaryGetValue(refAttributes, kSecValuePersistentRef);
+               v = CFCast(CFData, CFDictionaryGetValue(refAttributes, kSecValuePersistentRef));
                if (v) {
                        item->setPersistentRef((CFDataRef)v);
                }
@@ -4201,24 +4360,27 @@ SecItemValidateAppleApplicationGroupAccess(CFStringRef group)
        return status;
 }
 
-static Mutex gParentCertCacheLock;
+static Mutex& gParentCertCacheLock() {
+    static Mutex fParentCertCacheLock;
+    return fParentCertCacheLock;
+}
 static CFMutableDictionaryRef gParentCertCache;
 static CFMutableArrayRef gParentCertCacheList;
 #define PARENT_CACHE_SIZE 100
 
 void SecItemParentCachePurge() {
-    StLock<Mutex> _(gParentCertCacheLock);
+    StLock<Mutex> _(gParentCertCacheLock());
     CFReleaseNull(gParentCertCache);
     CFReleaseNull(gParentCertCacheList);
 }
 
-static CFArrayRef parentCacheRead(SecCertificateRef certificate) {
+static CFArrayRef CF_RETURNS_RETAINED parentCacheRead(SecCertificateRef certificate) {
     CFArrayRef parents = NULL;
     CFIndex ix;
     CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
     if (!digest) return NULL;
 
-    StLock<Mutex> _(gParentCertCacheLock);
+    StLock<Mutex> _(gParentCertCacheLock());
     if (gParentCertCache && gParentCertCacheList) {
         if (0 <= (ix = CFArrayGetFirstIndexOfValue(gParentCertCacheList,
                                                    CFRangeMake(0, CFArrayGetCount(gParentCertCacheList)),
@@ -4237,7 +4399,7 @@ static void parentCacheWrite(SecCertificateRef certificate, CFArrayRef parents)
     CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
     if (!digest) return;
 
-    StLock<Mutex> _(gParentCertCacheLock);
+    StLock<Mutex> _(gParentCertCacheLock());
     if (!gParentCertCache || !gParentCertCacheList) {
         CFReleaseNull(gParentCertCache);
         gParentCertCache = makeCFMutableDictionary();
@@ -4253,6 +4415,7 @@ static void parentCacheWrite(SecCertificateRef certificate, CFArrayRef parents)
             CFDictionaryAddValue(gParentCertCache, digest, parents);
             if (PARENT_CACHE_SIZE <= CFArrayGetCount(gParentCertCacheList)) {
                 // Remove least recently used cache entry.
+                CFDictionaryRemoveValue(gParentCertCache, CFArrayGetValueAtIndex(gParentCertCacheList, 0));
                 CFArrayRemoveValueAtIndex(gParentCertCacheList, 0);
             }
             CFArrayAppendValue(gParentCertCacheList, digest);
@@ -4261,13 +4424,13 @@ static void parentCacheWrite(SecCertificateRef certificate, CFArrayRef parents)
 }
 
 /*
- * SecItemCopyParentCertificates returns an array of zero of more possible
+ * SecItemCopyParentCertificates_osx returns an array of zero of more possible
  * issuer certificates for the provided certificate. No cryptographic validation
  * of the signature is performed in this function; its purpose is only to
  * provide a list of candidate certificates.
  */
 CFArrayRef
-SecItemCopyParentCertificates(SecCertificateRef certificate, void *context)
+SecItemCopyParentCertificates_osx(SecCertificateRef certificate, void *context)
 {
 #pragma unused (context) /* for now; in future this can reference a container object */
        /* Check for parents in keychain cache */
@@ -4277,7 +4440,7 @@ SecItemCopyParentCertificates(SecCertificateRef certificate, void *context)
        }
 
        /* Cache miss. Query for parents. */
-#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
+#if TARGET_OS_OSX
        CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerContent(certificate, NULL);
 #else
        CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate);
@@ -4328,7 +4491,7 @@ SecItemCopyParentCertificates(SecCertificateRef certificate, void *context)
        }
 
        if ((status != errSecSuccess) && (status != errSecItemNotFound)) {
-               secitemlog(LOG_WARNING, "SecItemCopyParentCertificates: %d", (int)status);
+               secitemlog(LOG_WARNING, "SecItemCopyParentCertificates_osx: %d", (int)status);
        }
        CFRelease(query);
 
@@ -4346,7 +4509,7 @@ SecItemCopyParentCertificates(SecCertificateRef certificate, void *context)
                                }
                        }
                }
-       } else if (resultType == CFDataGetTypeID()) {
+       } else if (results && resultType == CFDataGetTypeID()) {
                SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)results);
                if (cert) {
                        CFArrayAppendValue(result, cert);
@@ -4367,11 +4530,10 @@ SecCertificateRef SecItemCopyStoredCertificate(SecCertificateRef certificate, vo
 #pragma unused (context) /* for now; in future this can reference a container object */
 
        /* Certificates are unique by issuer and serial number. */
-#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
-       CFDataRef serialNumber = SecCertificateCopySerialNumber(certificate, NULL);
+       CFDataRef serialNumber = SecCertificateCopySerialNumberData(certificate, NULL);
+#if TARGET_OS_OSX
        CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerContent(certificate, NULL);
 #else
-       CFDataRef serialNumber = SecCertificateCopySerialNumber(certificate);
        CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate);
        CFRetainSafe(normalizedIssuer);
 #endif
@@ -4543,6 +4705,18 @@ SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass,
                 * which won't work once the item is updated.
                 */
                CFDictionaryRemoveValue(result, kSecAttrModificationDate);
+
+        /* Find all intermediate certificates in OSX keychain and append them in to the kSecMatchIssuers.
+         * This is required because secd cannot do query in to the OSX keychain
+         */
+        CFTypeRef matchIssuers = CFDictionaryGetValue(result, kSecMatchIssuers);
+        if (matchIssuers && CFGetTypeID(matchIssuers) == CFArrayGetTypeID()) {
+            CFArrayRef newMatchIssuers = _CopyMatchingIssuers((CFArrayRef)matchIssuers);
+            if (newMatchIssuers) {
+                CFDictionarySetValue(result, kSecMatchIssuers, newMatchIssuers);
+                CFRelease(newMatchIssuers);
+            }
+        }
     }
        else {
                /* iOS doesn't add the class attribute, so we must do it here. */
@@ -4558,13 +4732,58 @@ SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass,
        }
 
     /* This attribute is consumed by the bridge itself. */
+    CFDictionaryRemoveValue(result, kSecUseDataProtectionKeychain);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    // Also remove deprecated symbol in case your CFDict is derpy
     CFDictionaryRemoveValue(result, kSecAttrNoLegacy);
+#pragma clang diagnostic pop
 
        return result;
 }
 
 } /* extern "C" */
 
+static CFArrayRef
+_CopyMatchingIssuers(CFArrayRef matchIssuers) {
+    CFMutableArrayRef result = NULL;
+    CFMutableDictionaryRef query = NULL;
+    CFMutableDictionaryRef policyProperties = NULL;
+    SecPolicyRef policy = NULL;
+    CFTypeRef matchedCertificates = NULL;
+
+    require_quiet(policyProperties = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), out);
+    CFDictionarySetValue(policyProperties, kSecPolicyKU_KeyCertSign, kCFBooleanTrue);
+    require_quiet(policy = SecPolicyCreateWithProperties(kSecPolicyAppleX509Basic, policyProperties), out);
+    
+    require_quiet(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), out);
+    CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
+    CFDictionarySetValue(query, kSecMatchIssuers, matchIssuers);
+    CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
+    CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue);
+    CFDictionarySetValue(query, kSecUseCertificatesWithMatchIssuers, kCFBooleanTrue);
+    CFDictionarySetValue(query, kSecMatchPolicy, policy);
+    
+    if (SecItemCopyMatching_osx(query, &matchedCertificates) == errSecSuccess && CFGetTypeID(matchedCertificates) == CFArrayGetTypeID()) {
+        require_quiet(result = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)matchedCertificates), out);
+        for(CFIndex i = 0; i < CFArrayGetCount((CFArrayRef)matchedCertificates); ++i) {
+            CFDictionaryRef attributes = (CFDictionaryRef)CFArrayGetValueAtIndex((CFArrayRef)matchedCertificates, i);
+            CFTypeRef subject = CFDictionaryGetValue(attributes, kSecAttrSubject);
+            if (!CFArrayContainsValue(result, CFRangeMake(0, CFArrayGetCount(result)), subject)) {
+                CFArrayAppendValue(result, subject);
+            }
+        }
+    }
+    
+out:
+    CFReleaseSafe(query);
+    CFReleaseSafe(policyProperties);
+    CFReleaseSafe(policy);
+    CFReleaseSafe(matchedCertificates);
+
+    return result;
+}
+
 static OSStatus
 SecItemMergeResults(bool can_target_ios, OSStatus status_ios, CFTypeRef result_ios,
                                        bool can_target_osx, OSStatus status_osx, CFTypeRef result_osx,
@@ -4633,49 +4852,13 @@ SecItemMergeResults(bool can_target_ios, OSStatus status_ios, CFTypeRef result_i
        }
 }
 
-static bool
-ShouldTryUnlockKeybag(CFDictionaryRef query, OSErr status)
-{
-    static __typeof(SASSessionStateForUser) *soft_SASSessionStateForUser = NULL;
-       static dispatch_once_t onceToken;
-       static void *framework;
-
-       if (status != errSecInteractionNotAllowed)
-               return false;
-
-    // If the query disabled authUI, respect it.
-    CFTypeRef authUI = NULL;
-    if (query) {
-        authUI = CFDictionaryGetValue(query, kSecUseAuthenticationUI);
-        if (authUI == NULL) {
-            authUI = CFDictionaryGetValue(query, kSecUseNoAuthenticationUI);
-            authUI = (authUI != NULL && CFEqual(authUI, kCFBooleanTrue)) ? kSecUseAuthenticationUIFail : NULL;
-        }
-    }
-    if (authUI && !CFEqual(authUI, kSecUseAuthenticationUIAllow))
-        return false;
-
-    dispatch_once(&onceToken, ^{
-               framework = dlopen("/System/Library/PrivateFrameworks/login.framework/login", RTLD_LAZY);
-               if (framework == NULL)
-                       return;
-               soft_SASSessionStateForUser = (__typeof(soft_SASSessionStateForUser)) dlsym(framework, "SASSessionStateForUser");
-    });
-
-    if (soft_SASSessionStateForUser == NULL)
-        return false;
-
-    SessionAgentState sessionState = soft_SASSessionStateForUser(getuid());
-    if(sessionState != kSA_state_desktopshowing)
-        return false;
-
-    return true;
-}
-
 OSStatus
 SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result)
 {
-       secitemlog(LOG_NOTICE, "SecItemCopyMatching");
+    os_activity_t activity = os_activity_create("SecItemCopyMatching", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        if (!query) {
                return errSecParam;
        }
@@ -4683,8 +4866,8 @@ SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result)
 
        OSStatus status_osx = errSecItemNotFound, status_ios = errSecItemNotFound;
        CFTypeRef result_osx = NULL, result_ios = NULL;
-       bool can_target_ios, can_target_osx;
-       OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx);
+       bool can_target_ios, can_target_osx, useDataProtectionKeychainFlag;
+       OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx, useDataProtectionKeychainFlag);
        if (status != errSecSuccess) {
                return status;
        }
@@ -4697,14 +4880,6 @@ SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result)
                }
                else {
                        status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios);
-            if(ShouldTryUnlockKeybag(query, status_ios)) {
-                // The keybag is locked. Attempt to unlock it...
-                               secitemlog(LOG_WARNING, "SecItemCopyMatching triggering SecurityAgent");
-                if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(1)) {
-                    CFReleaseNull(result_ios);
-                    status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios);
-                }
-            }
                        CFRelease(attrs_ios);
                }
                secitemlog(LOG_NOTICE, "SecItemCopyMatching_ios result: %d", status_ios);
@@ -4732,7 +4907,10 @@ SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result)
 OSStatus
 SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result)
 {
-       secitemlog(LOG_NOTICE, "SecItemAdd");
+    os_activity_t activity = os_activity_create("SecItemAdd", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        if (!attributes) {
                return errSecParam;
        }
@@ -4742,8 +4920,8 @@ SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result)
        secitemshow(attributes, "SecItemAdd attrs:");
 
        CFTypeRef result_osx = NULL, result_ios = NULL;
-       bool can_target_ios, can_target_osx;
-       OSStatus status = SecItemCategorizeQuery(attributes, can_target_ios, can_target_osx);
+       bool can_target_ios, can_target_osx, useDataProtectionKeychainFlag;
+       OSStatus status = SecItemCategorizeQuery(attributes, can_target_ios, can_target_osx, useDataProtectionKeychainFlag);
        if (status != errSecSuccess) {
                return status;
        }
@@ -4758,14 +4936,6 @@ SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result)
                        status = errSecParam;
                } else {
             status = SecItemAdd_ios(attrs_ios, &result_ios);
-            if(ShouldTryUnlockKeybag(attributes, status)) {
-                // The keybag is locked. Attempt to unlock it...
-                               secitemlog(LOG_WARNING, "SecItemAdd triggering SecurityAgent");
-                if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) {
-                    CFReleaseNull(result_ios);
-                    status = SecItemAdd_ios(attrs_ios, &result_ios);
-                }
-            }
                        CFRelease(attrs_ios);
                }
                secitemlog(LOG_NOTICE, "SecItemAdd_ios result: %d", status);
@@ -4789,7 +4959,10 @@ SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result)
 OSStatus
 SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
 {
-       secitemlog(LOG_NOTICE, "SecItemUpdate");
+    os_activity_t activity = os_activity_create("SecItemUpdate", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        if (!query || !attributesToUpdate) {
                return errSecParam;
        }
@@ -4797,12 +4970,29 @@ SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
        secitemshow(attributesToUpdate, "SecItemUpdate attrs:");
 
        OSStatus status_osx = errSecItemNotFound, status_ios = errSecItemNotFound;
-       bool can_target_ios, can_target_osx;
-       OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx);
+       bool can_target_ios, can_target_osx, useDataProtectionKeychainFlag;
+       OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx, useDataProtectionKeychainFlag);
        if (status != errSecSuccess) {
                return status;
        }
 
+    /*
+     * If the user have explicity opted in to UseDataProtectionKeychain, then don't touch the legacy keychain at all
+     * ie don't move the item back to legacy keychain if you remove sync=1 or the inverse.
+     */
+    if (useDataProtectionKeychainFlag) {
+        CFDictionaryRef attrs_ios = SecItemCopyTranslatedAttributes(query,
+            CFDictionaryGetValue(query, kSecClass), true, true, false, true, true, true);
+        if (!attrs_ios) {
+            status_ios = errSecParam;
+        } else {
+            status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate);
+            CFRelease(attrs_ios);
+        }
+        secitemlog(LOG_NOTICE, "SecItemUpdate(ios only) result: %d", status_ios);
+        return status_ios;
+    }
+
        if (can_target_ios) {
                CFDictionaryRef attrs_ios = SecItemCopyTranslatedAttributes(query,
                        CFDictionaryGetValue(query, kSecClass), true, true, false, true, true, true);
@@ -4812,22 +5002,8 @@ SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
                else {
             if (SecItemHasSynchronizableUpdate(true, attributesToUpdate)) {
                 status_ios = SecItemChangeSynchronizability(attrs_ios, attributesToUpdate, false);
-                if(ShouldTryUnlockKeybag(query, status_ios)) {
-                    // The keybag is locked. Attempt to unlock it...
-                                       secitemlog(LOG_WARNING, "SecItemUpdate triggering SecurityAgent");
-                    if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(1)) {
-                        status_ios = SecItemChangeSynchronizability(attrs_ios, attributesToUpdate, false);
-                    }
-                }
             } else {
                 status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate);
-                if(ShouldTryUnlockKeybag(query, status_ios)) {
-                    // The keybag is locked. Attempt to unlock it...
-                                       secitemlog(LOG_WARNING, "SecItemUpdate triggering SecurityAgent");
-                    if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(1)) {
-                        status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate);
-                    }
-                }
             }
                        CFRelease(attrs_ios);
                }
@@ -4860,15 +5036,18 @@ SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
 OSStatus
 SecItemDelete(CFDictionaryRef query)
 {
-       secitemlog(LOG_NOTICE, "SecItemDelete");
+    os_activity_t activity = os_activity_create("SecItemDelete", OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT);
+    os_activity_scope(activity);
+    os_release(activity);
+
        if (!query) {
                return errSecParam;
        }
        secitemshow(query, "SecItemDelete query:");
 
        OSStatus status_osx = errSecItemNotFound, status_ios = errSecItemNotFound;
-       bool can_target_ios, can_target_osx;
-       OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx);
+       bool can_target_ios, can_target_osx, useDataProtectionKeychainFlag;
+       OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx, useDataProtectionKeychainFlag);
        if (status != errSecSuccess) {
                return status;
        }
@@ -4907,13 +5086,6 @@ OSStatus
 SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes)
 {
        OSStatus status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes);
-    if(ShouldTryUnlockKeybag(NULL, status)) {
-        // The keybag is locked. Attempt to unlock it...
-        if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(1)) {
-                       secitemlog(LOG_WARNING, "SecItemUpdateTokenItems triggering SecurityAgent");
-            status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes);
-        }
-    }
        secitemlog(LOG_NOTICE, "SecItemUpdateTokenItems_ios result: %d", status);
        return status;
 }