On Apple platforms, clients neither check Certificate Revocation List (CRL) of CAs, nor do they use OCSP by default.
Apple platforms, however, support OCSP stapling and they provide an alternative mechanism they call Revocation Enhancement, which could indeed lead to an OCSP call, as I'll show below.
OCSP Stapling
First an explanation of OCSP stapling:
Online Certificate Status Protocol (OCSP) stapling, formally known as the TLS Certificate Status Request extension, is a standard for checking the revocation status of X.509 digital certificates.1 It allows the presenter of a certificate to bear the resource cost involved in providing Online Certificate Status Protocol (OCSP) responses by appending ("stapling") a time-stamped OCSP response signed by the CA to the initial TLS handshake, eliminating the need for clients to contact the CA, with the aim of improving both security and performance.
see https://en.wikipedia.org/wiki/OCSP_stapling
Differences between OCSP and OCSP Stapling
If a client connects to a server in a traditional OCSP flow and retrieves the certificate, it checks whether the certificate received has been revoked by making a request to the CA. This has some disadvantages: for example, an additional network connection is required, the information is unencrypted and therefore represents a data privacy problem.
Through OCSP stapling, the server requests signed revocation information from the CA and adds it to the TLS handshake.
This also means that when using OCSP stapling, you do not see an OCSP request from iOS to a CA server.
Drawbacks of OCSP Stapling
The server you are connecting to must support OCSP stapling. This also does not protect against malicious servers.
These are the main reasons Apple is providing Revocation Enhancement.
Apple's Revocation Enhancement
Here's how it works:
- certificate transparency log entries are gathered by Apple
- with this info, Apple gathers information about revocations from CAs
- this aggregated information is then automatically made available to all Apple clients on a regular basis
- based on this information, when an iOS app attempts to connect to a server with a revoked certificate, it performs an additional check via OCSP.
Requirement
The only requirement for an app to support this is that the server certificate used be added to a certificate transparency log. A public Certification Authority may do this already, but you should check that the domain certificate is in the active transparency logs for public certificates, e.g. by using the following link: https://transparencyreport.google.com/https/certificates
WWDC 2017, session 701
There is an excellent WWDC session in which this topic and Apple's motives are explained in detail: WWDC 2017, session 701: https://developer.apple.com/videos/play/wwdc2017/701/
Around 12:10 mins, an Apple engineer explains the entire revocation topic in detail. At around 15:30, she explains that normal OCSP would require the use of additional APIs.
Test of OCSP Stapling on iOS
For testing, we need a server that supports OCSP stapling and uses a revoked certificate: e.g. https://revoked.grc.com
(found this server in this serverfault answer: https://serverfault.com/a/645066)
Then we can try to connect from iOS with a small test program that tries to download a HTML response and output it to the console.
Based on the information from the WWDC session mentioned above, the connection attempt should fail:
...
let session = URLSession(configuration: .default)
...
func onDownloadAction() {
let url = URL(string: "https://revoked.grc.com")!
self.download(from: url) { (result, error) in
if let result = result {
print("result: " + result)
} else {
print("download failed")
if let error = error {
print("error: \(error)")
}
}
}
}
func download(from url: URL, completion: @escaping(String?, Error?)->Void) {
let dataTask = self.session.dataTask(with: url) { data, response, error in
guard let data = data else {
if let error = error {
completion(nil, error)
return
}
completion(nil, NSError(domain: "DownloadFailure", code: 0, userInfo:nil))
return
}
guard let response = response as? HTTPURLResponse else {
completion(nil, NSError(domain: "ResponseFailure", code: 0, userInfo:nil))
return
}
print("http status: \(response.statusCode)")
let res = String(bytes: data, encoding: .utf8)
completion(res, nil)
}
dataTask.resume()
}
If we execute the above routine in the iOS Simulator, we can use Wireshark to check whether a time-stamped OCSP response signed by the CA is stapled to the TLS handshake.
With nslookup revoked.grc.com
we get the IP address of the server and can filter in Wireshark with ip.addr==4.79.142.205
.
In the screenshot, one can see that the certificate has the status revoked
.

So, taking a look into the Xcode console, one can see the following output:
2019-10-12 21:32:25.734382+0200 OCSPTests[6701:156558] ATS failed system trust
2019-10-12 21:32:25.734526+0200 OCSPTests[6701:156558] Connection 1: system TLS Trust evaluation failed(-9802)
2019-10-12 21:32:25.734701+0200 OCSPTests[6701:156558] Connection 1: TLS Trust encountered error 3:-9802
2019-10-12 21:32:25.734787+0200 OCSPTests[6701:156558] Connection 1: encountered error(3:-9802)
2019-10-12 21:32:25.737672+0200 OCSPTests[6701:156558] Task <12408947-689F-4537-9642-C8F95E86CA62>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
download failed
error: Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x6000037f8510>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"<cert(0x7fda78828200) s: revoked.grc.com i: DigiCert SHA2 Secure Server CA>",
"<cert(0x7fda7882b200) s: DigiCert SHA2 Secure Server CA i: DigiCert Global Root CA>"
), NSUnderlyingError=0x600000be9170 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x6000037f8510>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x7fda78828200) s: revoked.grc.com i: DigiCert SHA2 Secure Server CA>",
"<cert(0x7fda7882b200) s: DigiCert SHA2 Secure Server CA i: DigiCert Global Root CA>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://revoked.grc.com/, NSErrorFailingURLStringKey=https://revoked.grc.com/, NSErrorClientCertificateStateKey=0}
iOS aborts the attempt to connect to the server with a TLS error.
Test revoked.badssl.com
revoked.badssl.com does not support OCSP stapling.
If we take a look at the certificate details of https://revoked.badssl.com, we find out:
If one downloads the .crl file (2.5MB) and runs
openssl crl -inform DER -text -in ssca-sha2-g6.crl | grep 0371B58A86F6CE9C3ECB7BF42F9208FC
one can see that this certificate is indeed revoked via CRL.
Interestingly, neither Safari nor Chrome nor iOS recognize this revoked status. Only Mozilla Firefox displays an error message (Peer’s Certificate has been revoked. Error code: SEC_ERROR_REVOKED_CERTIFICATE).
The reason might be that the certificate was renewed only a few days ago and has therefore not yet found its way into all local revoke lists of browsers and operating systems.