Keychain Data Not Storing in iCloud
Asked Answered
M

1

10

I am using the keychain to store data on the local device but have decided to adapt it for use over multiple devices via iCloud. I have enabled the iCloud entitlement and created the necessary configuration within the Member Center. However, while the data is being stored it does not appear that it is being stored in the cloud. I am testing between the simulator and my iPhone device. The simulator is logged in using my account. Each device continues to save the data but the other device does not see the results.

I only added the kSecAttrSynchronizable and kCFBooleanTrue to the exiting setup which I understood was all that was required to make the keychain use the cloud.

Here the code used for storing and recalling keychain data.

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service
{
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass,
            service, (__bridge id)kSecAttrService,
            service, (__bridge id)kSecAttrAccount,
            (__bridge id)kCFBooleanTrue, (__bridge id)kSecAttrSynchronizable,
            (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,
            nil];
}

+ (void)save:(NSString *)service data:(id)data
{
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    CFTypeRef result = NULL;
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, &result);

    if (status == errSecSuccess) NSLog(@"Succcessfully Stored Value");
    else NSLog(@"Failed to store value with code: %ld",(long)status);
}

+ (id)load:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
    [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
        @try {
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
        }
        @catch (NSException *e) {
            NSLog(@"Unarchive of %@ failed: %@", service, e);
        }
        @finally {}
    }
    if (keyData) CFRelease(keyData);
    return ret;
}

+ (void)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
}
Madelinemadella answered 18/6, 2014 at 21:4 Comment(3)
A bit of a follow-up. I was watching the keychain on my Mac while using the app on the phone. I was seeing keychain data being written so it does appear to be working. However, I was under the impression that the simulator should also work and there is a "trigger iCloud Sync" option under Debug in the sim. Apple's documentation also indicates that the simulator can be used. However, it appears it does not interact with the main key chain even though my account is entered on the simulator.Madelinemadella
When you say enabled the "iCloud entitlement", do you mean that you have turned on the keychain functionality under "iCloud" in the settings app? Or is there some flip you have to switch on in pList?Sepulcher
Enabled under "Capabilities" in the Targets settings. In Member Center added "iCloud" to the App ID (this is the entitlement they reference within the "capabilities" tab.Madelinemadella
S
0

The simulator - version 7.1 (463.9.41) - does not have (I guess "does not simulate" is more accurate) the necessary hardware for secure management of the keychain.

You'll notice on the simulator in Settngs.app under iCloud there isn't an option for Keychain, whereas on device this option exists.

If you dig into ~/Library/Application Support/iPhone Simulator/7.1/Library/Keychains you'll find the simulator's keychain. The kSecAttrAccessGroup is test for all of the items that I've put into the simulator's keychain. When running on device, I get the expected access group (my app's App ID).

All of this points me in the direction that the Simulator doesn't support iCloud Keychain sync. The 2014 WWDC session #711 Keychain and Authentication with Touch ID goes into detail about how the hardware features of the device support keychain encryption.

Two iOS devices or iOS and OS X have been the only way I've been able to reliably develop, debug, and troubleshoot iCloud Keychain sync.

Selfsustaining answered 25/7, 2014 at 16:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.