8 Replies
      Latest reply on Mar 14, 2019 2:32 AM by eskimo
      LoileeBooz Level 1 Level 1 (0 points)

        The app I am working on cannot access the KeyChain on more than 50% of the user base ever

        since I enable Background Modes for Location Update for MarketingCloud SDK which I integrated.

        The app has Keychain Sharing enabled.

         

        The code is:

        KeyChain is read to get an encryption key, if it is not found, we create a new encryption key which is used for open a database needed to launch the app. This code is executed in AppDelegate willFinishLaunchingWithOptions.

         

        We intentionally kill the app when KeyChain returns an error since the app logic is dependent on the database.

        We cannot reproduce the same issue.

         

        Our question is, when is the keychain available for access?  Should we delay(don't use it in AppDelegate) access to the keychain during app launch?

        • Re: KeyChain SecItemAdd return -25308 when app is launched from a "suspended" state
          eskimo Apple Staff Apple Staff (10,875 points)

          Error -25308 is errSecInteractionNotAllowed.  This usually means that you’re trying to access a keychain item that’s not accessible while the device is locked.

          I’m not sure how you go from this error to a crash.  The OS won’t automatically crash your process when this error occurs.  Rather, the relevant keychain API call will return this error and it’s up to your app to handle that case.  Is your code crashing as a result of this error?

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: KeyChain SecItemAdd return -25308 when app is launched
              LoileeBooz Level 1 Level 1 (0 points)

              You are right eskimo, sorry for the confusion. I rewrote the question.

                • Re: KeyChain SecItemAdd return -25308 when app is launched
                  eskimo Apple Staff Apple Staff (10,875 points)

                  Once you enable your app to run into the background you have to start caring about data protection, and specifically the keychain access attribute.  Consider a scenario like this:

                  1. Your app is run by the user and everything is good.

                  2. The user presses the Home button and your app moves to the background.

                  3. Shortly thereafter the system suspends your app.

                  4. At some point in the future, the system needs memory and thus removes your suspended app from memory.

                  5. The user locks their device.

                  6. At some point in the future a location event causes the system to launch your app in the background.

                  7. Your ‘willFinishLaunchingWithOptions’ app delegate method runs.  If it attempts to access a keychain item with kSecAttrAccessible set to kSecAttrAccessibleWhenUnlocked, that access will fail because the device is locked.

                  How you resolve this depends on the nature of your app:

                  • If you only need your database when the app is showing UI, you can defer this access until the app is on screen.  The app can only come on screen if the device is unlocked.

                  • If you need your database while in the background, you can set kSecAttrAccessible to something less secure.  The exact value depends on how your app gets run in the background.  Most background execution is deferred until first unlock, and thus you can use kSecAttrAccessibleAfterFirstUnlock.  However, some background execution can happen before first unlock, in which case you’ll need kSecAttrAccessibleAlways.  This is measurably less secure.

                  Obviously it’s best to keep your data as secure as possible, so you should only use the second approach if your database is absolutely critical to the background operation of your app.  You may be able to come up with a hybrid approach, where you split your database in two, using better protection in general but less protection for the critical-to-background-execution stuff.  Or if you only need to write to your database, you could temporarily write new data to a less secure database and then consolidate things when the device is unlocked.

                  Keep in mind that the keychain is not the only place where data protection applies.  Ideally you should protect your files on disk as well, using the various file protection modes.  The preferred API for this is NSURLFileProtectionKey in NSURL, but most of the documentation you’ll find for the older NSFileProtectionKey in in NSFileManager.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"