Cody Sehl

Notes on the March 2017 iOS Security Guide


I recently read through the March 2017 iOS Security Guide and made a few notes—it’s quite dense! I thought I would share these notes so other people can benefit from the time I put in, too. Additions and clarifications from external sources where noted.


When new files are created on a device, they are automatically assigned a “Data Protection Class” that determines under what conditions the file may be read/written.

They are:

  • Available when unlocked (NSFileProtectionComplete). Access is only allowed when the device is unlocked.

  • Available on create and after open (NSFileProtectionCompleteUnlessOpen). This one is difficult to explain simply. Check out the docs for more info. If a file is created when the device is locked, the file can be accessed until it is closed. After the file is closed, you can’t open it again until unlock. If a file is opened when the device is unlocked, you can access the file even if the device is locked again.

  • Available after first unlock (NSFileProtectionCompleteUntilFirstUserAuthentication). This is the default data protection class for all third-party app files, unless otherwise specified.

  • Always available (NSFileProtectionNone). Not encrypted with a passcode, but the device UID it sounds like. So, you’re unable to read the files if you don’t have access to the device.


See Keychain Services Programming Guide.

The Keychain is implemented as a database stored on the file system. There is only one keychain database, and the securityd daemon manages access.

On macOS, every new user is assigned a keychain called login.keychain. On iOS, there is one keychain used by all applications.

A keychain item has data (i.e., the stuff you want to keep secret) and metadata about the item.

Keychain items can be synced with iCloud by setting the kSecAttrSynchronizable attribute to kCFBooleanTrue. Shared items may only be used by apps with the same TEAM_ID.

On iOS, encrypted keychain items by default are not available when the device is locked. This behavior can be changed by assigning a Keychain Protection Class to a keychain item.

Keychain access is determined by an app’s:

  • keychain-access-groups (called ‘Keychain Groups’ in XCode under Project Settings > Capabilities > Keychain Sharing)
  • application-identifier, which is described in the Cocoa Core Competencies Docs and is TEAM_ID + BUNDLE_IDENTIFIER
  • application-group

Keychain items can’t be shared between applications made by different developers.

Similar to file encryption, keychain items are assigned a Keychain Protection Class, which is:

  • Available when unlocked (kSecAttrAccessibleWhenUnlocked). Access is only allowed when the device is unlocked.

  • Available after first unlock (kSecAttrAccessibleAfterFirstUnlock). Just what it says.

  • Always available (kSecAttrAccessibleAlways). Not encrypted with a passcode, but the device UID it sounds like. So, you’re unable to read the files if you don’t have access to the device.

  • Passcode enabled (kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly). The same as “Available when unlocked,” except that the item is only available on devices with a passcode. If the passcode is removed, items are deleted. Items are not migrated to a new device. Items are not synced to iCloud keychain. Items are not backed up. Items are not included in escrow keybags.

When accessing the keychain for background refresh services (e.g., on receipt of remote notifications), Apple recommends using kSecAttrAccessibleAfterFirstUnlock.


iOS requires that apps are signed to ensure they haven’t been tampered with after they’ve left the developer’s hands. Stock apps (e.g., Safari) have been signed by Apple directly. Third-party apps (i.e., yours) have been signed by you with a certificate provided by Apple.

The system will do a runtime signature check of any frameworks used by a third-party app to verify their authenticity.

(What a dig from the iOS Security Guide: “Unlike other mobile platforms, iOS doesn’t allow users to install potentially malicious unsigned apps from websites, or run untrusted code.”)

At runtime, the operating system will also verify the signature of paged memory to make sure it hasn’t been modified since last run. Intense.

App sandboxing

Every third-party app is sandboxed—it gets its own filesystem container and can’t touch the containers of other apps. A new sandbox is generated and randomly assigned at app install.

If the app needs to access resources provided by the system, it does so through APIs provided by Apple, not through direct access to the filesystem/processes. Access to these resources is controlled through Entitlements.

The OS uses Address Space Layout Randomization to reduce the likelihood of a successful buffer overflow attack.


By default, App Transport Security enforces the use of secure standards when communicating over the network. Apps must explicitly declare they wish to use insecure methods of communication.

Important concepts

App groups

  • These are described in Sharing Data with Your Containing App and the App Groups section of the iOS Security Guide.
  • They allow sharing NSUserDefaults (simple key value store) between app and extensions.
  • They allow sharing container directories (though it’s unclear what this actually achieves).
  • They allow sharing keychain items.


  • Keybags are a way of categorizing types of keys.
  • There are many different types (e.g., User, Device, Backup, Escrow, iCloud Backup).
  • Keys for both File Data Protection and Keychain Data Protection classes are stored in keybags.

Effaceable Storage

  • This storage is guaranteed, at a hardware level, to delete data properly.


  • Entitlements define an API for Apple-provided frameworks, specifically, things that would normally require root permissions on unix system.
  • Applications must explicitly ask for permission to use system functionality, minimizing the damage possible if your app is exploited.
  • They are cryptographically signed so they’re not easy to spoof.


  • According to the iOS Security Guide, “The system automatically detects extensions at install time and makes them available to other apps using a matching system.”
  • Extensions and the apps they’re based on don’t have direct access to each other’s files or memory.
  • Extensions receive the same privacy settings as their parent applications.

Core data, NSData, SQLite

  • These are encrypted by default.


  • Passcodes are stored with an iteration count of ~80ms. That is, it takes ~80ms to check if an entered passcode is correct. Tries between brute force attacks take at least that long.

Containers (filesystem/directory)

  • See Apple’s Filesystem Overview
  • They are sandbox directories.
  • Third-party apps are not allowed direct access to the iOS filesystem, and instead have access to the container in which they live.
  • iCloud also has its own container.
  • Containers limit the damage if your app is compromised.

Device UID

  • This is the device’s unique ID, a 256-bit key baked into the device processor at manufacture time.


How should I store sensitive information like passwords or API tokens?

The Security Guide recommends storing passwords in the keychain: “Many apps need to handle passwords and other short but sensitive bits of data, such as keys and login tokens. The iOS Keychain provides a secure way to store these items.”

What’s the point of the keychain?

They keychain allows you to: encrypt your secrets; allow/disallow access to secrets depending on the state of the device; and sync your secrets to iCloud by setting the kSecAttrSynchronizable attribute.

Wrapping up

The iOS Security Guide is quite technical and complicated. If I missed or misrepresented any of the information in the guide you think is important, please leave a comment below!