iOS Keychain randomly returning -25300

I am facing a strange issue in my app. My code saves a string password in the iOS keychain to be accessed later on. It works just fine most of the times and I am able to fetch the password back after reinstallation or device restart or both.

Problem: Sometimes which is actually rare and hard to reproduce, it does NOT return the password and instead it returns null and error status:-25300(errSecItemNotFound). Another thing is that this problem got prominent after iOS 9 update. Happening on iOS 9.1 too.


Code for setting:


NSMutableDictionary *query = [self _queryForService:service account:account]; 
[query setObject:password forKey:(__bridge id)kSecValueData]; 
status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);

if (status != errSecSuccess && error != NULL) { 
*error = [NSError errorWithDomain:kAppKeychainErrorDomain code:status userInfo:nil]; } 
return (status == noErr);


Code for fetching:


CFTypeRef result = NULL; 
NSMutableDictionary *query = [self _queryForService:service account:account]; 
[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; 
[query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; 
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);

if (status != errSecSuccess && error != NULL) { 
*error = [NSError errorWithDomain:kAppKeychainErrorDomain code:status userInfo:nil]; 
return nil; 
} 
return (__bridge_transfer NSData *)result;


Has anyone got any ideas why this is happening? Many thanks.

Most problems like this are related to folks getting confused by the difference between the dictionary you use to run a keychain query versus the dictionary you use to add keychain items. In your case it’s hard to say what’s going on because you elided

-_queryForService:account:
, which is the most critical part of your code (-:

Share and Enjoy

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

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

Thanks for your reply.

I get your point and here are the final queries for both the cases:


Final dict for setting:

{ acct = user; 
class = genp; 
svce = "myBundleIdentifier"; 
"v_Data" = <36314541 38463339 2d363737 462d3445 34372d42 4339452d 31324633 46463937 35374546>;}


Final query dict for fetching:

{ acct = user; 
class = genp; 
"m_Limit" = "m_LimitOne"; 
"r_Data" = 1; 
svce = "myBundleIdentifier";}


I hope that can help you suggest further.

Those look fine.

Can you elaborate on “rare and hard to reproduce”? Are you seeing this during development? Or getting reports from users in the field? If it’s the latter, do the users experiencing the problem have anything in common? And, once a user sees the problem, are they more likely to see it again?

Share and Enjoy

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

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

Thanks for the reply.

Can you elaborate on “rare and hard to reproduce”?

>We have around 2.86mn devices using it and out of those there are around 8000 devices affected.

Are you seeing this during development?

>Yes. However during development, this has been only happened 4-5 times in 3 months (4 devices monitored).

Or getting reports from users in the field?

>Yes, answer to #1 is the number of users in the field.

If it’s the latter, do the users experiencing the problem have anything in common?

>Not any we can narrow down to. However, this issue is definitly more prominent in iOS 9.0 and above.

And, once a user sees the problem, are they more likely to see it again?

>I would say yes. Atleast that seems to be the pattern, as it is the same users that have been affected multiple times in many cases.

Just to add, the main scenario that this happens is when we uninstall and install the app again. At that time, the application tries to query the keychain and resulting in the error.

Yeah, problems like this are hard to track down. There’s basically two possibilities:

  • The keychain is actually functioning properly but the keychain items are configured in a totally unexpected way causing your code to fail (A).

  • The keychain is not functioning properly (B)>

To distinguish between these I recommend that you add a ‘keychain dump’ feature to your app, that dumps all the keychain items you have access to. A user can then send you the dump and you can look to see if there’s anything that might be causing problem A.

Once you rule that out, and you’ve concluded this is problem B, a keychain dump would be a useful attachment for the bug report you file.

IMPORTANT It should go without saying that the dump shouldn’t include any user secrets.

Share and Enjoy

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

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

Thanks for the reply Quinn,


I will do that and update you. Keep an eye on this thread!

Hi Quinn,


I have been trying to dump Keychain contents but all the tools and ways I have stumbled upon and tried a few(searching over the internet) seems to require a jailbroken device or seems to be only doable on a simultor. Neither of these scenarios is an actual and generic scneraio for us.

Can you guide me on how can I do it on a real non-jailbroken iPhone?


Thanks.

You can’t dump the keychain with a tool; you will have to write code to do this. The Credentials class in the AdvancedURLConnections sample code shows what I’m talking about (although it’s probably best not to copy the code verbatim because it’s old and crufty).

Share and Enjoy

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

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

Hi Quinn,


Happy New Year!


I have the keychain dumps from 4 different devices(below), they look fine to me.

If you can quickly scan them? If all looks normal to you too, I will file the bug.


Device 1:

identities:

certificates:

keys:

Internet:

generic:

0

description = ''

label = ''

account = ''

service = ''

generic = 'WLUUID'

1

account = 'user'

service = 'co.comp.samplevm.v4'

URL credential storage:

------------------------------------------------------

Device 2:

identities:

certificates:

keys:

Internet:

generic:

0

account = 'user'

service = 'co.comp.samplevm.v4'

URL credential storage:

------------------------------------------------------

Device 3:

identities:

certificates:

keys:

Internet:

generic:

0

account = 'user'

service = 'co.comp.samplevm.v4'

URL credential storage:

----------------------------------------------------

Device 4:

identities:

certificates:

keys:

Internet:

generic:

0

account = 'user'

service = 'co.comp.samplevm.v4'

URL credential storage:

--------------------------------------------------


Thanks.

I am seeing the same issue with our application. I've only been able to test it on 64 bit devices at the moment, but here are some things to note:

- Keychain sharing is on. We share our keychain with one additional group, the group is second in the list

- relevant data is stored as kSecClassGenericPassword

Using the "keychain dump" routine as mentioned above, there are two entries at '..didFinishLaunching...'

generic:

0

label = 'mobilecare'

account = 'password'

service = 'mobilecare'

1

label = 'mobilecare'

account = 'keyVersion4'

service = 'mobilecare'

While the app is running, dumping shows 3 (Notice that the "keyVersion4" item is now missing, but is was there earlier)

generic:

0

label = 'mobilecare'

account = 'mrn'

service = 'mobilecare'

1

label = 'mobilecare'

account = 'userName'

service = 'mobilecare'

2

label = 'mobilecare'

account = 'password'

service = 'mobilecare'

But when it is re-run again we are back to only the two items above ("keyVersion4" has reappeared, but "mrn" and "userName" are gone).

Hi,


Coupld you try the test I did and add an item to the keychain to see if the values are there the next time the app is run?

I have now replicated this problem on a 1st gen iPad Mini (32 bit device).


It also appears that the inclusion of the the "LocalAuthenticaion.framework" has a roll in creating this defect. We did not have this issue in our previuos version which did not include TouchID. However, this bug shows up regarless of whether the user activates Touch ID for the app or not.

We've been able to isolate our occurance of this issue to a 3rd party libary, so our app does not have this particular issue.

Thanks fo the updates!

If you can please share the name of the 3rd party Library? Also, how did you isolate the issue from your app and the culprit library?

Hi - unfortunately due to agreements I can not disclose it. Also the 3rd party is still attempting to replicate, so technically I could still be wrong (I doubt it).


To make a long story short on how I was able to Isolate it, we had a release where this rarely happenned, followed by a release where this always happened. I played the "what's changed" game and discovered that a library upgrade from a 3rd party provider triggered the issue. I could swap the libraries in and out from old to new and thew new did it all the time; back to the old, no bug; re-install new, bug. etc. No other code/settings/etc. Just that library.


I might add that "Keychain Sharing" could be a culprit in this. Would love to hear from Apple on this. Or if 9.2.1 has any effect on this issue. In general I'm highly befudddled by this bug.

Oh! Thanks... I have raised a bug with Apple. Let see how it goes! Will post the outcome here.

We also have users experiencing the same "random" -25300 errSecItemNotFound issue. I'm fairly confident that the keychain items are configured properly since they can be read back without issue the vast majority of the time and they are only set once on the first run of the app (and are never deleted by the application).


The problem does seem to resolve itself after a period of time (on the order of hours, according to affected users) which also seems to suggest the keychain item configuration is not the problem. Dumping the keychain when experiencing this issue shows none of the expected keychain entries.


We have only experienced this issue with iOS 9 devices, and approximately 3% of our users have experienced it at least once. It does seem like some users are much more likely to experience it based on the reporting we have.


Here is one device log that captures some information just prior to an app launch where the keychain access failed with an unexepected -25300.

https://gist.github.com/robmaceachern/0003ec44c37b01e72af9

This is the point the app launched https://gist.github.com/robmaceachern/0003ec44c37b01e72af9#file-device-log-25300-errsecitemnotfound-L496


There are a bunch of securityd errors in there that might shed a little light. These each were logged before the application launched:


securityd[83] <Error>: SecDbRecordChange db <SecDbConnection rw open> changed outside txn

securityd[83] <Error>: __SOSUpdateKeyInterest_block_invoke_2 Error getting ring interests (null)

securityd[83] <Error>: SecOCSPSingleResponseCalculateValidity OCSPSingleResponse: nextUpdate 0.73 days ago

securityd[83] <Error>: securityd_xpc_dictionary_handler cloudd[166] copy_matching Error Domain=NSOSStatusErrorDomain Code=-50 "query missing class name" UserInfo={NSDescription=query missing class name}

securityd[83] <Error>: secTaskDiagnoseEntitlements MISSING keychain entitlements: no stored taskRef found


Notes:

- The keychain items are accessed in application:didFinishLaunchingWithOptions:

- We use a library to do the actual keychain access: https://github.com/kishikawakatsumi/KeychainAccess

- The issue has occured on App Store distributed builds, enterprise distributed builds, and debug builds – but I don't know of any reliable reproduction steps

- Keychain sharing is not enabled

- The app makes frequent use of silent push notifications (content-available flag).

- Failures have been observed while the app is in UIApplicationStateInactive and UIApplicationStateBackground

- All keychain items use the kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly accessibility setting

- Having the user force close & re-open the app doesn't seem to resolve the problem.


Quinn: Do you have any suggestions on how to proceed on this? Any hunches on what to try when attempting to reproduce?

securityd[83] <Error>: secTaskDiagnoseEntitlements MISSING keychain entitlements: no stored taskRef found

My understanding is that these log messages are a recent addition to the system to help track down the very elusive -34018 error. Please file a bug with the info you have and then post the bug number here.

Some questions:

  • Is the user reporting this likely to be running Xcode?

  • What OS version were they running? If they’re running a 9.3 beta, it’s important to know which beta (that is, the build number).

  • Do they see any “simulated” crash logs on the device?

I’d like to know the answers to these questions myself, but it’s more important you put this info in your bug report.

Share and Enjoy

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

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

Thanks Quinn. I've filed bug number 24956853.


To answer your questions:


> Is the user reporting this likely to be running Xcode?


No, most reports of the issue are from non-developer users and don't have xcode or any other debugger attached to the app.


> What OS version were they running? If they’re running a 9.3 beta, it’s important to know which beta (that is, the build number).


We have seen this problem on iOS 9.2.1, 9.2.0, and 9.1.0. We haven't seen this problem on any version of iOS 8 (about ~7% of our active users are using iOS 8 devices). I don't believe any of our users are using 9.3 beta yet, and we haven't seen any reports of the issue from 9.3 devices.


> Do they see any “simulated” crash logs on the device?


We have seen some "simulated" crash logs that appear to be related to a background NSURLSession our application uses, however they don't seem to be restricted to devices experiencing the keychain problem. Similar simulated reports also appear for other processes: eg Flixter, Google Docs, Economist, etc). Gist is here: https://gist.github.com/robmaceachern/087e875a482a9dcd693e

Hi Quinn

As already reported above, I have also filed the bug a while ago for this. Bug no. is: 24270773.

Hi Captalvins,

Any luck with this bug or response from apple? My app is also getting this issue. We use keychain to store user credential and this issue causes a % of our user to consistently relogin. We also read from keychain on app startup in didFinishLaunchingWithOptions. We noticed disabling background app refresh seems to reduce # of occurrence or completely eliminate the issue. We haven't confirm if that solve the issue since we have no luck replicating it inhouse.

Edit: As a side note, our app does not have keychain sharing enable.

Thanks

Kun

anyone found a solution / workaround? Is moving the part where keychain access is needed to places other than didFinishLaunchingWithOptions (maybe in viewDidLoad) a workaround? This issue affects all iOS versions in my case and there is no solution found online. It's frustrating it happens randomly and it's unable to tell if the value really isn't in the keychain or it happens to be unreadable at that moment.

Even we are facing issue with this API. Keychain API returns -25300 eventhoug item is present.It is mostly happening with the appstore build and with the end users. Not sure when apple responds to this. It would be helpful if anyone suggests a reliable work around for this

After some more testing, found that disabling Background Modes helped and the issue was completely gone although I have no explanation for that. Would be very much appreciated if anyone can help explaining why the Background Modes capability setting affect reading the Keychain when the app opens.

Thanks.

The typical interaction point between background modes and the keychain is data protection, as surfaced by the

kSecAttrAccessible
attribute. For example, if you set the accessible attribute to
kSecAttrAccessibleWhenUnlocked
and then run in the background due to background fetch, it’s likely you’ll run into a situation where the keychain item isn’t accessible because the device is locked at the time you receive background fetch time.

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"
iOS Keychain randomly returning -25300
 
 
Q