Reputation: 93
I'm having trouble getting this call to work for IOS. I've tried a number of approaches but nothing seems to work: I always get a status of errSecParam. Can anyone tell me what I'm doing wrong?
I started out using this to get a list of attributes for a certificate I hydrated from bytes. That didn't work so I reduced it to this and received the same error. I've tested on the simulator and an iPhone6 and get the same results.
First I get an array of certificates and then I pass the array back to SecItemCopyMatching. I've tried this where I queried for attributes only and get the same error.
I'm new to IOS so I don't doubt it's something I've missed.
Thanks.
// Call SecItemCopyMatching twice: the first time fetch an array of certificates
// and the second time use the array with kSecMatchItemList.
- (void) SecItemCopyMatchingTest2 {
// Now read them from the keychain.
NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kSecClassCertificate,(__bridge id)kSecClass,
(__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnRef,
(__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit,
nil];
CFTypeRef result;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
NSArray *rgRefs = CFBridgingRelease(result);
if (status == noErr){
// this works
}
// Use the array we received from our previous call
[query setObject:rgRefs forKey:(__bridge id)kSecMatchItemList];
CFTypeRef result2;
// Results in status = errSecParam
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result2);
if (status == errSecParam){
// the cal fails.
}
}
Upvotes: 1
Views: 1727
Reputation: 133189
Quote from the header file documentation:
@constant
kSecMatchItemList
OS X only. Specifies a dictionary key whose value is a CFArray of SecKeychainItemRef items. If provided, returned items will be limited to the subset which are contained in this list.
I know that the __OSX_AVAILABLE_STARTING
claims it exists for iOS but that is a lie, on the mailing list an Apple developer claimed it has never been implemented for iOS.
Try setting the same array with kSecUseItemList
. This wasn't implemented for iOS either at that time according to mailing list, but if Apple is going to implement either one for iOS (or has already done so), it's rather kSecUseItemList
.
There are a lot of strange keychain API differences between macOS and iOS and some of these are only found in documentation or just in the header files. Here's another example from the SecItemDelete()
delete documentation:
To delete an item identified by a transient reference, on iOS, specify kSecValueRef with a item reference. On OS X, give a kSecMatchItemList containing an item reference.
Trying to use kSecMatchItemList
for that on iOS will fail, just like using kSecValueRef
on macOS seems to fail. These API differences don't make any sense to me, but either you can do it with kSecUseItemList
or you are out of luck and it's simply not possible on iOS.
Upvotes: 1