Keychain access no longer works in Guided Access mode (iOS9)

(Just copy-pasting information from my openradar post here ... there seems to be no reaction on either the official bugtracker nor openradar so far.)

(Also, sorry for the abhorrent formatting of the code... this new editor is really all kinds of terrible. 😉)


http://www.openradar.me/radar?id=6104753268326400

rdar://23045769


Summary:


We use Guided Access mode to create a ‘hand-off’ mode in our app, in which the iPad is handed to a non-privileged user. The user ‘locks’ the app, causing Guided Access mode to be enabled, using “UIAccessibilityRequestGuidedAccessSession(TRUE, lockdownCallback);”. Afterwards, the ‘normal’ user can unlock the app by either re-entering his credentials or authenticating via TouchId, using “SecItemCopyMatching(query, &data);”

If the authentication went successful, we leave Guided Access mode. “UIAccessibilityRequestGuidedAccessSession(TRUE, nil);”

All of this worked perfectly prior to iOS 9. Now, in the current iOS (9.1), The “SecItemCopyMatching” call blocks for 3 seconds or so, then returning “errSecAuthFailed” (-25293).

Has this functionality been removed, or is it a temporary bug? I could not find any notice of this in any of the changelogs.

Steps to Reproduce:

  1. You will need your iPad to be in a MDM which allows your app to enable/disable in Guided Access mode.
  2. Insert a keychain item with information like this (outside guided access mode)
  3. Enter guided access mode.
  4. Once in guided access mode:

Code for step 2:

NSData *secretData = [NSKeyedArchiver archivedDataWithRootObject:@{@"username":username, @"password":password}]; 
NSDictionary *addAttributes = @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrService: [self getLocalAuthServerName], (id)kSecValueData: secretData, (id)kSecAttrAccessControl: (id)TouchIdSecurityObject }; 
SecItemAdd((__bridge CFDictionaryRef)addAttributes, nil);

Code for step 3:

UIAccessibilityRequestGuidedAccessSession(TRUE, lockdownCallback);


Code for step 4:

NSDictionary *query = @{ (id)kSecClass: (id)kSecClassGenericPassword, (id)kSecAttrService: [LoginBox getLocalAuthServerName], (id)kSecReturnData: @YES, (id)kSecAttrAccessControl: (id)TouchIdSecurityObject, (id)kSecUseOperationPrompt: $(@"TOUCHID IDENTIFY PROMPT") }; CFTypeRef dataTypeRef = NULL; OSStatus status = SecItemCopyMatching((CFDictionaryRef)(query), &dataTypeRef); if (status == errSecSuccess) { NSData *authData = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)dataTypeRef]; NSLog(@"%@", authData); } else { NSLog(@"Authentication failed"); }

Expected Results:

TouchID prompt popping up, after successful TouchId authentication, “errSecSuccess” (0) return value.

Actual Results:

Long block time, no TouchId prompt, “errSecAuthFailed” (-25293) return value.

Version:

iOS9.0.2 & iOS 9.1

Configuration:

Any iDevice with TouchId

Replies

Ever figure out a solution to your problem? I may be experiencing something similar, but with LocalAuthentication instead.

Did you ever find an answer to this problem? I am having the same difficulty.

The bug referenced above (r. 23045769) was reported fixed in iOS 10. If you’re still having problems with this, you should file your own bug report about it. Please post your bug number, just for the record.

IMPORTANT Make sure to include a sysdiagnose log with your bug report. Instructions for creating this are available on the Bug Reporting > Profiles and Logs page.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"