5 Replies
      Latest reply on Feb 24, 2016 12:56 PM by gc.
      mdu Level 1 Level 1 (0 points)

        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.