Search code examples
objective-cios8keychain

iOS8 + Apple's KeychainItemWrapper results in a crash


I've been digging around Apple forums and SO for this issue to no avail. Using Apple's KeychainItemWrapper (ARCified), trying to set the kSecAttrAccessible attribute to anything except the default (kSecAttrAccessibleWhenUnlocked) results in an assertion failure from SecItemUpdate returning an error.

KeychainItemWrapper *wrapper = [[KeyChainItemWrapper alloc] initWithIdentifier:kMyIdentifier accessGroup:nil];
[wrapper setObject:kMyServiceName forKey:(__bridge NSString*)kSecAttrService];
[wrapper setObject:kMyAccountToken forKey:(__bridge NSString*)kSecAttrAccount];
[wrapper setObject:(__bridge NSString*)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly forKey:(__bridge NSString*)kSecAttrAccessible];

The rest of our keychain updates seem to be going through fine, but the last line results in:

*** Assertion failure in -[KeychainItemWrapper writeToKeychain], /Users/john.hammerlund/.../KeychainItemWrapper.m:299

The assertion failure is due to SecItemUpdate() returning a status of -50, which appears to be a generic "invalid parameters" error.

Immediately setting the kSecAttrAccessible key has no impact, but setting it to the default kSecAttrAccessibleWhenUnlocked mitigates the issue (but eliminates the point). This other question is the only additional info I've found relating to iOS 8 causing the KeychainItemWrapper to crash. Building to a device with iOS 7 or a simulator on iOS 7/8 eliminates the issue; it's only flaring up on a real device using iOS 8.

Update

Here's a broad overview of the query dictionary:

{ accc = "<SecAccessControlRef: 0x1687cc70>"; acct = ...; agrp = ...; cdat = "2014-10-13 22:22:47 +0000"; desc = ""; gena = ...; labl = ""; mdat = "2014-10-13 22:34:16 +0000"; pdmn = cku; <-- kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly svce = ...; sync = 0; tomb = 0; "v_Data" = <>; }

and the attributesToUpdate parameter:

{ accc = "<SecAccessControlRef: 0x1687cc70>"; acct = ...; agrp = ...; cdat = "2014-10-13 22:22:47 +0000"; desc = ""; gena = ...; labl = ""; mdat = "2014-10-13 22:34:16 +0000"; pdmn = ak; <-- kSecAttrAccessibleWhenUnlocked svce = ...; sync = 0; tomb = 0; "v_Data" = <>; }

I've confirmed that changing other fields (i.e. kSecAttrService, kSecAttrAccount) have the same effect on the corresponding fields in the dictionaries, but with an expected status of 0.


Solution

  • I also had the exact problem. Gave me:

    OSStatus error -50 - conflicting kSecAccess and kSecAccessControl attributes

    Crashed to all my users in the app store just after they updated.

    Did the same as Peter. Grabed the data, deleted the item and inserted it as new item instead of trying to update the existing one.

    I guess this is an Apple bug.

    I opened a TSI but they didn't contact me yet.

    From what i understand, It happens to users updated from iOS7 to iOS 8, where their first app was compiled with XCode for iOS7 (Before iOS 8 was out), and then on iOS8 updated to the new app which was compiled with XCode to iOS8.