I am setting the kSecAttrAccessibleWhenUnlocked
key when adding a value to the keychain. The documentation states:
The data in the keychain item can be accessed only while the device is unlocked by the user.
I wrote a simple test app, here is the viewDidLoad
method:
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
// Device (with passcode lock) is locked now
double delayInSeconds = 6.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSError * error = nil;
[MyKeychainWrapper setKeychainObject:@"abc"
forKey:@"key"
error:&error];
NSLog(@"Setting Error: %@", error); // No error logged
NSString * value = (NSString *) [MyKeychainWrapper keychainObjectForKey:@"key"
error:&error];
NSLog(@"value: %@", value); // Logs ABC when the device is locked
NSLog(@"Getting Error: %@", error); // No error logged
});
How is it saving and reading the data while the device is locked?
It's a bit unclear how you are testing this, I'm assuming that you are running you code and then pressing the power button on the phone. Keychain locking does not happen immediately when the power button is pressed, so your application will be able to access keychain items for a short while (about 10 seconds) after the power button is pressed.
For iOS; If you run this code on a phone in developer mode, looking at the console, you will notice that it takes a few seconds before the keychain is actually locked after you press the power button on the phone. On my iPhone 5, it takes between 10 seconds, depending on what applications are running. The same goes for unlocking the device, it takes a while before the keychain is unlocked. Here is an example that I just did; notice that it takes about 10 seconds from the "Locking" to the "Locked" printouts.
May 5 14:26:20 I50 kernel[0] <Debug>: AppleKeyStore::start_keybag_locking: Device Locking..
May 5 14:26:20 I50 kernel[0] <Debug>: ALS: AppleARMBacklight::handleMessageGated - framebufferState -> 0
May 5 14:26:30 I50 UserEventAgent[14] <Error>: LockStateNotifier aksNotificationCallback posting notification: com.apple.mobile.keybagd.lock_status
May 5 14:26:30 I50 kernel[0] <Debug>: AppleKeyStore:Sending lock change 1
May 5 14:26:30 I50 kernel[0] <Debug>: AppleKeyStore::device_state_transition: Device Locked, lockstate=1
AFAIK the exact time is not specified by Apple, but 6 seconds is maybe not enough for the keychain to lock down.