/*
- * 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 "LegacyAPICounts.h"
#include <AssertMacros.h>
#include <syslog.h>
+#include <dlfcn.h>
#include <Security/SecTrustedApplication.h>
#include <Security/SecTrustedApplicationPriv.h>
#include <Security/SecCodePriv.h>
#include <Security/SecRequirement.h>
+#include <login/SessionAgentCom.h>
+#include <login/SessionAgentStatusCom.h>
+#include <os/activity.h>
+#include <CoreFoundation/CFPriv.h>
+
+
const uint8_t kUUIDStringLength = 36;
OSStatus SecItemAdd_osx(CFDictionaryRef attributes, CFTypeRef *result);
OSStatus SecItemCopyMatching_ios(CFDictionaryRef query, CFTypeRef *result);
OSStatus SecItemUpdate_ios(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);
OSStatus SecItemDelete_ios(CFDictionaryRef query);
-OSStatus SecItemUpdateTokenItems_ios(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes);
-CFTypeRef SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes);
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, ...)
{
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,
// 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;
// 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)
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;
}
break;
default:
stringRef = CFStringCreateWithFormat(allocator, NULL, CFSTR("%d"), keyRecordValue);
+ retainString = false;
break;
}
if (stringRef) {
CFMutableDictionaryRef dict = CFDictionaryCreateMutable(allocator, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
unsigned int ix;
- SecItemClass itemClass = 0;
+ SecItemClass itemClass = (SecItemClass) 0;
UInt32 itemID;
SecKeychainAttributeList *attrList = NULL;
SecKeychainAttributeInfo *info = NULL;
break;
default:
stringRef = CFStringCreateWithFormat(allocator, NULL, CFSTR("%u"), (unsigned int)keyRecordValue);
+ retainString = false;
break;
}
if (stringRef) {
// add kSecAttrAuthenticationType
if ( attrList.attr[6].length > 0 ) {
keys[numValues] = kSecAttrAuthenticationType;
- values[numValues] = _SecAttrAuthenticationTypeForSecAuthenticationType(*(SecProtocolType*)attrList.attr[6].data);
+ values[numValues] = _SecAttrAuthenticationTypeForSecAuthenticationType( (SecAuthenticationType) (*(SecProtocolType*)attrList.attr[6].data));
if ( values[numValues] != NULL ) {
CFRetain(values[numValues]);
++numValues;
// [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);
* _AppNameFromSecTrustedApplication attempts to pull the name of the
* application/tool from the SecTrustedApplicationRef.
*/
-static CFStringRef
+static CFStringRef CF_RETURNS_RETAINED
_AppNameFromSecTrustedApplication(
CFAllocatorRef alloc,
SecTrustedApplicationRef appRef)
}
// create SecTrustedApplicationRef for current application/tool
- CFReleaseSafe(currentAppRef);
+ CFReleaseNull(currentAppRef);
status = SecTrustedApplicationCreateFromPath(NULL, ¤tAppRef);
require_noerr(status, finish);
require_quiet(currentAppRef != NULL, finish);
// 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;
return errSecParam;
}
- SecItemClass itemClass;
+ SecItemClass itemClass = (SecItemClass) 0;
SecAccessRef access = NULL;
SecKeychainAttributeList *changeAttrList = NULL;
SecKeychainItemRef itemToUpdate = NULL;
status = _CreateSecKeychainKeyAttributeListFromDictionary(changedAttributes, &changeAttrList);
require_noerr(status, update_failed);
}
+ break;
+ case kSecAppleSharePasswordItemClass:
+ {
+ // do nothing (legacy behavior).
+ }
+ break;
+
}
// get the password
}
// 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);
(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)
// Given a list of items (standard or persistent references),
// determine whether they all have the same item class. Returns
// the item class, or 0 if multiple classes in list.
- SecItemClass result = 0;
+ SecItemClass result = (SecItemClass) 0;
CFIndex index, count = (itemList) ? CFArrayGetCount(itemList) : 0;
for (index=0; index < count; index++) {
CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(itemList, index);
itemRef = (SecKeychainItemRef) CFRetain(item);
}
if (itemRef) {
- SecItemClass itemClass = 0;
+ SecItemClass itemClass = (SecItemClass) 0;
CFTypeID itemTypeID = CFGetTypeID(itemRef);
if (itemTypeID == SecIdentityGetTypeID() || itemTypeID == SecCertificateGetTypeID()) {
// Identities and certificates have the same underlying item class
CFRelease(itemRef);
if (itemClass != 0) {
if (result != 0 && result != itemClass) {
- return 0; // different item classes in list; bail out
+ return (SecItemClass) 0; // different item classes in list; bail out
}
result = itemClass;
}
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
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);
{
OSStatus status;
CFTypeRef value = NULL;
+ CFDictionaryRef policyDict = NULL;
SecItemParams *itemParams = (SecItemParams *)calloc(1, sizeof(struct SecItemParams));
require_action(itemParams != NULL, error_exit, status = errSecAllocate);
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);
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
}
// 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)
}
error_exit:
+ CFReleaseNull(policyDict);
if (status) {
_FreeSecItemParams(itemParams);
itemParams = NULL;
END_SECAPI
}
-#if !SECTRUST_OSX
-static Boolean
-_CanIgnoreLeafStatusCodes(CSSM_TP_APPLE_EVIDENCE_INFO *evidence)
-{
- /* Check for ignorable status codes in leaf certificate's evidence */
- Boolean result = true;
- unsigned int i;
- for (i=0; i < evidence->NumStatusCodes; i++) {
- CSSM_RETURN scode = evidence->StatusCodes[i];
- if (scode == CSSMERR_APPLETP_INVALID_CA) {
- // the TP has rejected this CA cert because it's in the leaf position
- result = true;
- }
- else if (ignorableRevocationStatusCode(scode)) {
- result = true;
- }
- else {
- result = false;
- break;
- }
- }
- return result;
-}
-#endif
-
static OSStatus
_FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert)
{
SecTrustRef trust = NULL;
SecTrustResultType trustResult;
-#if !SECTRUST_OSX
- CSSM_TP_APPLE_EVIDENCE_INFO *evidence = NULL;
-#endif
Boolean needChain = false;
+ Boolean needCSEKU = false;
OSStatus status;
if (!policy || !cert) return errSecParam;
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 (!needChain) {
-#if !SECTRUST_OSX
- /* To make the evaluation as lightweight as possible, specify an empty array
- * of keychains which will be searched for certificates.
- */
- keychains = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
- status = SecTrustSetKeychains(trust, keychains);
- if(status) goto cleanup;
+ /* 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;
+ }
+ }
- /* To make the evaluation as lightweight as possible, specify an empty array
- * of trusted anchors.
- */
- anchors = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
- status = SecTrustSetAnchorCertificates(trust, anchors);
- if(status) goto cleanup;
-#else
+ if (!needChain) {
status = SecTrustEvaluateLeafOnly(trust, &trustResult);
} else {
status = SecTrustEvaluate(trust, &trustResult);
-#endif
}
-#if !SECTRUST_OSX
- /* All parameters are locked and loaded, ready to evaluate! */
- status = SecTrustEvaluate(trust, &trustResult);
- if(status) goto cleanup;
-
- /* If we didn't provide trust anchors or a way to look for them,
- * the evaluation will fail with kSecTrustResultRecoverableTrustFailure.
- * However, we can tell whether the policy evaluation succeeded by
- * looking at the per-cert status codes in the returned evidence.
- */
- status = SecTrustGetResult(trust, &trustResult, &chain, &evidence);
- if(status) goto cleanup;
-#endif
-
if (!(trustResult == kSecTrustResultProceed ||
trustResult == kSecTrustResultUnspecified ||
trustResult == kSecTrustResultRecoverableTrustFailure)) {
/* If there are no per-cert policy status codes,
* and the cert has not expired, consider it valid for the policy.
*/
-#if SECTRUST_OSX
if (true) {
(void)SecTrustGetCssmResultCode(trust, &status);
-#else
- if((evidence != NULL) && _CanIgnoreLeafStatusCodes(evidence) &&
- ((evidence[0].StatusBits & CSSM_CERT_STATUS_EXPIRED) == 0) &&
- ((evidence[0].StatusBits & CSSM_CERT_STATUS_NOT_VALID_YET) == 0)) {
- status = errSecSuccess;
-#endif
- }
- else {
- status = errSecCertificateCannotOperate;
}
cleanup:
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)
{
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;
}
// 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;
//
// Note that we allocate *items if needed.
+ CFTypeRef localResult = NULL;
+
if (!item || !itemParams || !result)
return errSecParam;
CFArrayAppendValue(itemArray, itemRef);
}
else {
- *result = CFRetain((CFTypeRef)itemRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain((CFTypeRef)itemRef);
}
}
CFArrayAppendValue(itemArray, persistentRef);
}
else {
- *result = CFRetain(persistentRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(persistentRef);
}
CFRelease(persistentRef);
}
CFArrayAppendValue(itemArray, dataRef);
}
else {
- *result = CFRetain(dataRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(dataRef);
}
CFRelease(dataRef);
status = errSecSuccess;
CFArrayAppendValue(itemArray, dataRef);
}
else {
- *result = CFRetain(dataRef);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(dataRef);
}
CFRelease(dataRef);
(void) SecKeychainItemFreeContent(NULL, data);
CFArrayAppendValue(itemArray, attrsDict);
}
else {
- *result = CFRetain(attrsDict);
+ CFReleaseNull(localResult);
+ localResult = CFRetain(attrsDict);
}
CFRelease(attrsDict);
}
if (itemArray) {
CFArrayAppendValue(itemArray, itemDict);
CFRelease(itemDict);
- *result = itemArray;
+ CFReleaseNull(localResult);
+ localResult = itemArray;
}
else {
- *result = itemDict;
+ CFReleaseNull(localResult);
+ localResult = itemDict;
}
}
else if (itemArray) {
- *result = itemArray;
+ CFReleaseNull(localResult);
+ localResult = itemArray;
+ }
+
+ if (localResult) {
+ *result = localResult;
+ localResult = NULL;
}
return status;
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;
}
//
// 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()) {
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;
}
SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes) {
CFTypeRef ref = NULL;
CFStringRef item_class_string = (CFStringRef)CFDictionaryGetValue(refAttributes, kSecClass);
- SecItemClass item_class = 0;
+ SecItemClass item_class = (SecItemClass) 0;
if (CFEqual(item_class_string, kSecClassGenericPassword)) {
item_class = kSecGenericPasswordItemClass;
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);
}
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)),
CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
if (!digest) return;
- StLock<Mutex> _(gParentCertCacheLock);
+ StLock<Mutex> _(gParentCertCacheLock());
if (!gParentCertCache || !gParentCertCacheList) {
CFReleaseNull(gParentCertCache);
gParentCertCache = makeCFMutableDictionary();
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);
}
/*
- * 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 */
}
/* 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);
CFDictionaryAddValue(query, kSecMatchSearchList, combinedSearchList);
CFRelease(combinedSearchList);
}
- CFDictionaryAddValue(query, kSecAttrSubject, normalizedIssuer);
- /* Get all certificates matching our query. */
CFTypeRef results = NULL;
- status = SecItemCopyMatching_osx(query, &results);
+ if (normalizedIssuer) {
+ /* Look up certs whose subject is the same as this cert's issuer. */
+ CFDictionaryAddValue(query, kSecAttrSubject, normalizedIssuer);
+ status = SecItemCopyMatching_osx(query, &results);
+ }
+ else {
+ /* Cannot match anything without an issuer! */
+ status = errSecItemNotFound;
+ }
+
if ((status != errSecSuccess) && (status != errSecItemNotFound)) {
- secitemlog(LOG_WARNING, "SecItemCopyParentCertificates: %d", (int)status);
+ secitemlog(LOG_WARNING, "SecItemCopyParentCertificates_osx: %d", (int)status);
}
CFRelease(query);
}
}
}
- } else if (resultType == CFDataGetTypeID()) {
+ } else if (results && resultType == CFDataGetTypeID()) {
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)results);
if (cert) {
CFArrayAppendValue(result, cert);
#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
* 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. */
}
/* 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,
// If both keychains were targetted, examine returning statuses and decide what to do.
if (status_ios != errSecSuccess) {
// iOS keychain failed to produce results because of some error, go with results from OSX keychain.
+ // Since iOS keychain queries will fail without a keychain-access-group or proper entitlements, SecItemCopyMatching
+ // calls against the OSX keychain API that should return errSecItemNotFound will return nonsense from the iOS keychain.
AssignOrReleaseResult(result_osx, result);
- return status_osx;
+ return status_osx;
} else if (status_osx != errSecSuccess) {
if (status_osx != errSecItemNotFound) {
// OSX failed to produce results with some failure mode (else than not_found), but iOS produced results.
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;
}
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;
}
}
else {
status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios);
- if(status_ios == errSecInteractionNotAllowed) {
- // The keybag is locked. Attempt to unlock it...
- if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) {
- CFReleaseNull(result_ios);
- status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios);
- }
- }
CFRelease(attrs_ios);
}
secitemlog(LOG_NOTICE, "SecItemCopyMatching_ios result: %d", status_ios);
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;
}
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;
}
status = errSecParam;
} else {
status = SecItemAdd_ios(attrs_ios, &result_ios);
- if(status == errSecInteractionNotAllowed) {
- // The keybag is locked. Attempt to unlock it...
- 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);
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;
}
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);
else {
if (SecItemHasSynchronizableUpdate(true, attributesToUpdate)) {
status_ios = SecItemChangeSynchronizability(attrs_ios, attributesToUpdate, false);
- if(status_ios == errSecInteractionNotAllowed) {
- // The keybag is locked. Attempt to unlock it...
- if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) {
- status_ios = SecItemChangeSynchronizability(attrs_ios, attributesToUpdate, false);
- }
- }
} else {
status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate);
- if(status_ios == errSecInteractionNotAllowed) {
- // The keybag is locked. Attempt to unlock it...
- if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) {
- status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate);
- }
- }
}
CFRelease(attrs_ios);
}
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;
}
status_ios = errSecParam;
} else {
status_ios = SecItemDelete_ios(attrs_ios);
- if(status_ios == errSecInteractionNotAllowed) {
- // The keybag is locked. Attempt to unlock it...
- if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) {
- status_ios = SecItemDelete_ios(attrs_ios);
- }
- }
CFRelease(attrs_ios);
}
secitemlog(LOG_NOTICE, "SecItemDelete_ios result: %d", status_ios);
return status;
}
-OSStatus
-SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes)
-{
- OSStatus status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes);
- if(status == errSecInteractionNotAllowed) {
- // The keybag is locked. Attempt to unlock it...
- if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) {
- status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes);
- }
- }
- secitemlog(LOG_NOTICE, "SecItemUpdateTokenItems_ios result: %d", status);
- return status;
-}
-
OSStatus
SecItemCopyMatching_osx(
CFDictionaryRef query,
else
*result = NULL;
+ setCountLegacyAPIEnabledForThread(false);
+
CFAllocatorRef allocator = CFGetAllocator(query);
CFIndex matchCount = 0;
CFMutableArrayRef itemArray = NULL;
}
_FreeSecItemParams(itemParams);
- return status;
-}
+ setCountLegacyAPIEnabledForThread(true);
-OSStatus
-SecItemCopyDisplayNames(
- CFArrayRef items,
- CFArrayRef *displayNames)
-{
- BEGIN_SECAPI
- Required(items);
- Required(displayNames);
- //%%%TBI
- return errSecUnimplemented;
- END_SECAPI
+ return status;
}
OSStatus
else if (result)
*result = NULL;
+ setCountLegacyAPIEnabledForThread(false);
+
CFAllocatorRef allocator = CFGetAllocator(attributes);
CFMutableArrayRef itemArray = NULL;
SecKeychainItemRef item = NULL;
*result = NULL;
}
_FreeSecItemParams(itemParams);
+ setCountLegacyAPIEnabledForThread(true);
return status;
}
CFRelease(results);
}
+ setCountLegacyAPIEnabledForThread(false);
+
OSStatus result = errSecSuccess;
CFIndex ix, count = CFArrayGetCount(items);
for (ix=0; ix < count; ix++) {
}
}
+ setCountLegacyAPIEnabledForThread(true);
+
if (items) {
CFRelease(items);
}
CFRelease(results);
}
+ setCountLegacyAPIEnabledForThread(false);
+
OSStatus result = errSecSuccess;
CFIndex ix, count = CFArrayGetCount(items);
for (ix=0; ix < count; ix++) {
}
}
+ setCountLegacyAPIEnabledForThread(true);
+
if (items)
CFRelease(items);