This post documents Proton Mail’s iOS security model and illustrates how our application protects sensitive data on client iOS devices. The advantages and limitations of this approach are discussed, and the source code can be viewed here(new window). You can also see Proton Mail’s iOS open source announcement(new window).
In addition to this, you can read our previously published Proton Mail threat model(new window), which gives general information about what Proton Mail is and is not designed to protect against. Our iOS trust model(new window) is available on our Github page.
In this document, terms like Keychain, File Data Protection classes, Secure Enclave, etc., are defined in Apple’s security documentation found here(new window). This document is technical in nature, but is also designed to be accessible to a general audience, with key features described in plain language.
Overview
As with most iOS applications, Proton Mail needs to store some data locally on your device:
- Encrypted messages, attachments, and metadata
- Public and private keys for sending and reading messages
- An access token for communication with the back end
- A token for push notification payload decryption
- User account details
- Technical data, such as date of first login and version of caching system
Some of these pieces of data are kept in Keychain, some are stored in our local CoreData database, and some are located in the UserDefaults dictionary inside the application directory. iOS offers a high level of data protection using its built-in security system: Keychain Data Protection and File Data Protection classes. But on top of these we have also introduced our own additional layer of protection called the AppKey Protection System.
We explain the security features of the Proton Mail iOS app in greater detail below, followed by four key security recommendations from our team.
Default data protection on iOS
Proton Mail leverages many of the default protections available on iOS. Late-model iPhones and iPads offer an extremely high level of security, provided the user takes proper precautions, including using a strong device password and maintaining the latest software versions. We have not tried to reinvent the wheel when it comes to Apple’s security system, which has been thoroughly vetted and audited.
Most Keychain items are saved with the kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly flag that decrypts data locally after the first time the device is unlocked. We cannot use more strict flags because the app must often work in the background, even when the device is locked (for example, when sending large attachments). In order to share items stored in Keychain (such as access tokens, for example) across all our application extensions (Share and Push Application Extensions), we keep them in one Keychain Access Group. kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly also prevents an attacker from retrieving data via a logical extraction from a rebooted device or restoring a stolen backup on another device.
The data protection class for files is set as NSFileProtectionComplete in app entitlements with default exceptions for CoreData (which includes messages, attachments, folders, contacts, etc.) and UserDefaults (which includes user account information and settings) files, which the app needs to be able to access in the background and when the device is locked.
Proton Mail’s AppKey Protection System
While the default iOS security mechanisms are satisfactory for many purposes, Proton Mail operates on a heightened threat model, which requires stronger protection than what is available by default to guard against enhanced attacks. Known attacks include mobile forensic hardware, stalkerware, and recently discovered state-sponsored spyware targeting Chinese minority groups. (We have provided further details in this security recommendation(new window).)
To increase the chance of protecting data even when the iOS sandbox is compromised or if a rogue application manages to steal decrypted items in Keychain, we have introduced the AppKey Protection System.
This system works by encrypting all sensitive local data with a per-login local key called AppKey, which is not stored in a place that can be compromised. Users can activate this protection system by turning on TouchID, FaceID, or PIN protection in their app settings.
AppKey protects:
- Messages, attachments, contacts, labels, addresses, and other items saved in CoreData
- User account information and settings
- The user’s encryption keys
- Access token
On every app launch, the AppKey ciphertext stored in Keychain is decrypted and placed into the app memory before any other app process can work. The app is not functional unless the user authenticates with their PIN, TouchID, or FaceID. Without this authentication, the app cannot access local data and does not know anything about the user to request data from the server.
A side effect of this architecture is that the Share extension, which allows users to send files or links via Proton Mail directly from another app, requires authentication every time. This takes the user to an in-app authentication modal before opening the Composer.
AppKey is kept in the app’s memory for a user-determined amount of time, which is configured in the app settings after enabling FaceID, TouchID, or PIN protection (i.e. the Auto lock timer). The user can require authentication after the Auto lock timer expires or after each time the app goes to the background.
Here’s how AppKey is handled for each app authentication scenario:
TouchID or FaceID protection: The Secure Enclave chip (see page 8 in the iOS security documentation) generates an asymmetric keypair, keeps the private key, and gives the public key to the app. The Proton Mail app encrypts the AppKey with the public key and saves the ciphertext to Keychain, asking Secure Enclave to decrypt it every time the Proton Mail app needs to retrieve the cleartext AppKey. Secure Enclave decrypts the AppKey only after biometric authentication or device passcode, and the private key never leaves Secure Enclave.
PIN protection: The Proton Mail app derives a temporary key from the user’s PIN string, symmetrically encrypts the AppKey with this temporary key, and saves the ciphertext to Keychain. The temporary key and PIN string are never persisted and are removed from memory as fast as possible. Without the PIN input, the AppKey is not accessible.
No protection: For cases when the user does not want to switch on additional protection in their app settings, the AppKey is saved cleartext in Keychain. This case is weak against forensic attacks and in cases when the device is compromised, but the data should not be extractable from backups.
Push notifications encryption
Unfortunately, we could not apply the AppKey Protection System to the contents of push notifications because this decryption happens in a Notification Service Application Extension, which runs in a separate process and cannot request users’ local authentication by means of TouchID, FaceID, or PIN.
On each login, the app generates an asymmetric keypair, saves the private key on Keychain, and sends the public key to Proton’s push notification server accompanied by the user’s session ID. This server encrypts every push notification with the public key, and the application extension decrypts it using the private key from Keychain, ensuring that Apple (or an intelligence agency sitting on Apple’s servers) does not have access to the contents of push notifications. Raw push notifications are not persisted on the device for long and are not included in backup. The private key is removed from Keychain on logout, and the public key is not reused across sessions.
More info about the Notification Service Application Extension is available in iOS documentation(new window).
Web-based attacks
All emails are treated as HTML emails and are rendered by means of the WKWebView component. Since incoming messages can contain malware, we’ve implemented a number of protective techniques.
DOMPurify
When the user opens a message, the app decrypts the message body and then passes it through DOMPurify(new window), an open source filter that sanitizes HTML and prevents XSS attacks. It works in JavaScript runtime before the content is loaded into WebView.
JavaScript execution in WebViews
JavaScript execution for web content is forbidden by the WKWebView configuration for incoming messages right after DOMPurify is done but before message contents are loaded into WebView.
Please note: Like other email mobile apps, JavaScript execution is allowed in the Composer because this is necessary for editing within a webview. This can pose some risk when forwarding or replying to a malicious email, but this is mitigated by the DOMPurifier and our Content Security Policy.
Content Security Policy against XSS
The Content Security Policy (CSP) is a computer security standard introduced to prevent cross-site scripting (XSS), clickjacking, and other code injection attacks resulting from execution of malicious content in the trusted web page context. We take advantage of this technology when presenting a message body and the Composer in WebViews.
During the process of loading the HTML into WebView, CSP configuration passes three states:
- Restricts everything until DOMPurify sanitizes the HTML
- Allows only embedded images (which arrive inside an encrypted message and are considered a local resource)
- Optionally allows loading of remote resources (according to whether the user has enabled “Auto show images” in the app settings)
The Content Security Policy for Composer additionally allows inline scripts that are needed for editing.
Content Security Policy against tracking
Including remote content in the body of a message is a common method of tracking used by marketing companies. When a typical email client renders the message body HTML, it requests remote content (i.e. images, background-svg, fonts, or scripts) from a server, which can thereby obtain the user’s IP address, click ratio, or message opening status.
When the “Auto show images” option in the Proton Mail iOS app settings is disabled, it limits the WebView and controls what remote data can be loaded (including all kinds of remote content, not only images). This locking is powered by the CSP configuration of WebView.
Attachments
Normal attachments are cached as encrypted files in the app directory for a period of time depending on the iOS version (usually three or four days), or whenever the user logs out of their Proton Mail account in the app. Embedded attachments are part of the message body itself.
When an attachment is decrypted, the cleartext file is stored in the app directory during the time the attachment is being previewed via the native QLPreviewController(new window). These files are removed as soon as QLPreviewController is closed.
Be careful with what you open because Apple maintains this object, and our restrictions blocking JavaScript in HTML, blocking remote images (if enabled), etc.do not cover it. For example, an HTML document sent as an attachment can contain JavaScript, which could run if QLPreviewController allows. The Proton Mail app cannot protect you if you open a malicious file, and any protection here must be done by the iOS operating system.
Man-in-the-middle attacks
Man-in-the-middle (MITM) attacks are more difficult to accomplish in Proton Mail because of our use of end-to-end encryption and zero-access encryption. We have further implemented a number of safeguards in our overall security architecture, including Address Verification(new window) which prevents MITM via a fake public key. There are also safeguards against network level MITM. The following information is specific to our iOS client:
Certificate pinning
We use TrustKit(new window) for certificate pinning. If the app notices a man-in-the-middle attack, you will see an alert pop up, and the app will cut the connection to the Proton Mail server.
Other attacks
We do our best to protect your data even when the device is compromised, but every security system has its limits in a compromised device. We do not run any jailbreak detections because they are trivial to bypass for a sophisticated attacker and only cause problems for legitimate jailbreak users.
Audits and open source
The Proton Mail iOS client is released as free and open source software under a GNU General Public License. The app has been audited by the renowned security firm SEC Consult, and we have published the results of this audit(new window). We invite the developer community to inspect our code and participate in our public bug bounty program(new window). Bounty submissions can be sent to [email protected].
Our recommendations for keeping your device secure
No system is 100% secure, but we have invested heavily in the security of our iOS app. You can help maximize the security of your own device by taking a few simple measures:
- Enable TouchID, FaceID, or PIN protection in the app settings, which is the only way to take advantage of our AppKey Protection System.
- Install all the latest iOS updates.
- Set a long alphanumeric device passcode in your device settings.
- Do not install untrusted configuration profiles or root certificates in your device settings.
- Do not open links or download attachments from untrusted senders.
If you have any questions about the Proton Mail iOS security model, please contact our team at [email protected]. Thank you for your support.
Best Regards,
The Proton Mail Team
This work was conducted by Anatoly Rosencrantz and Yanfeng Zhang from the Proton Mail team.
You can get a free secure email account(new window) from Proton Mail here.
We also provide a free VPN service(new window) to protect your privacy.
Proton Mail and Proton VPN are funded by community contributions. If you would like to support our development efforts, you can upgrade to a paid plan(new window). Thank you for your support.