Hello,
I use the keychain to store a sensitive data.
Since iOS 9.2 beta 3, I cannot retrieve a sensitive data created from a previous version of iOS (e.g. iOS 9.1).
I have an error errSecItemNotFound when using SecItemCopyMatching.
No problem with iOS 9.1 (nor iOS 9.2 beta 2 nor iOS 7.x/8.x/9.0).
Very strange: my source code creates a new sensitive data if it doesn't exist, so with iOS 9.2 beta 3 I have a new sensitive data, but if I switch back to iOS 9.1, I retrieve the old sensitive data, and so on when going back to iOS 9.2 beta 3...
As I use the exact same query, it seems the keychain is duplicated...
Here is my code to add a sensitive data:
NSMutableDictionary *symmetricKeyAttr = [NSMutableDictionary dictionary];
[symmetricKeyAttr setObject:(__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];
[symmetricKeyAttr setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[symmetricKeyAttr setObject:[NSNumber numberWithUnsignedInt:CSSM_ALGID_AES] forKey:(__bridge id)kSecAttrKeyType];
[symmetricKeyAttr setObject:[NSNumber numberWithUnsignedInt:(unsigned int)(kChosenCipherKeySize << 3)] forKey:(__bridge id)kSecAttrKeySizeInBits];
[symmetricKeyAttr setObject:[NSNumber numberWithUnsignedInt:(unsigned int)(kChosenCipherKeySize << 3)]
forKey:(__bridge id)kSecAttrEffectiveKeySize];
[symmetricKeyAttr setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecAttrCanEncrypt];
[symmetricKeyAttr setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecAttrCanDecrypt];
[symmetricKeyAttr setObject:(id)kCFBooleanFalse forKey:(__bridge id)kSecAttrCanDerive];
[symmetricKeyAttr setObject:(id)kCFBooleanFalse forKey:(__bridge id)kSecAttrCanSign];
[symmetricKeyAttr setObject:(id)kCFBooleanFalse forKey:(__bridge id)kSecAttrCanVerify];
[symmetricKeyAttr setObject:(id)kCFBooleanFalse forKey:(__bridge id)kSecAttrCanWrap];
[symmetricKeyAttr setObject:(id)kCFBooleanFalse forKey:(__bridge id)kSecAttrCanUnwrap];
[symmetricKeyAttr setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
[symmetricKeyAttr setObject:applicationTag forKey:(__bridge id)kSecAttrApplicationTag];
[symmetricKeyAttr setObject:sensitiveData forKey:(__bridge id)kSecValueData];
OSStatus sanityCheck = SecItemAdd((__bridge CFDictionaryRef) symmetricKeyAttr, NULL);
Here is my code to get a sensitive data:
NSMutableDictionary * querySymmetricKey = [NSMutableDictionary dictionary];
[querySymmetricKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[querySymmetricKey setObject:[NSNumber numberWithUnsignedInt:CSSM_ALGID_AES] forKey:(__bridge id)kSecAttrKeyType];
[querySymmetricKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnData];
[querySymmetricKey setObject:applicationTag forKey:(__bridge id)kSecAttrApplicationTag];
[querySymmetricKey setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup];
CFDataRef symmetricKeyDataRef = NULL;
OSStatus sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)querySymmetricKey, (CFTypeRef *)&symmetricKeyDataRef);
Where:
- sensitiveData is the sensitive data to store (e.g. <ac746cc2 80f72948 59d0d8b7 a5de4bad 5d9e9eb1 a400fba3 c85f3f2e 675d58bf>)
- accessGroup is the concatenation of team identifier and application identifier (e.g. XXXXXXXXXX.com.toto.tata)
- applicationTag is the tag related to the sensible data (e.g. <746F746F)
Note: I switch between iOS 9.1 and 9.2 beta 3 by using IPSW files without doing a backup restore, but I have the same problem by doing backup restore.
Any idea?
EDIT 1: The issue occurs with 64-bit devices only, no problem with 32-bit devices.
EDIT 2:
- Replacing CSSM_ALGID_AES by CSSM_ALGID_NONE solves the issue (i.e. data created with iOS 9.1 can be properly retrieved with iOS 9.2 beta 3), but it's not acceptable because I must be able to read data created on iOS 9.1 with CSSM_ALGID_AES.
- The issue is not related to kSecAttrAccessGroup: I still have the problem when I remove this property.
EDIT 3:
- I've "reproduced" the issue with sample from Apple (https://developer.apple.com/library/ios/samplecode/CryptoExercise).
- This sample uses CSSM_ALGID_AES too and not kSecAttrAccessGroup.
- Using 64-bit device: a key created with iOS 9.1 (<bdd17fe1 f515e2b1 14de7c43 c4cb6a70>) is found with iOS 9.2 beta 3 but it has a different value (<73b205e2 46230f69 fa0f347c 2958e6b1>) !!
- Using 32-bit device: key is the same between iOS 9.1 and iOS 9.2 beta 3.