How to check certificate transparency used during server trust

We are building an iOS SDK using certificate transparency to verify SSL connections. This is was initially implemented using ATS in the info.plist but we came across an issue:

Users could install a profile and fully trust a root certificate that will allow them to override these checks. Burpsuite does this out of the box as well.

The workaround we found was to use URLSessionDelegate and after evaluation, check the result of SecTrustCopyResult(_: SecTrust) for the key kSecTrustCertificateTransparency, making sure the value was true.

The issue here is that this key is only present from iOS 13 onwards. How would you suggest we implement this for earlier versions of iOS? (we are currently supporting iOS 11.0 and up)

How would you suggest we implement this for earlier versions of iOS? (we are currently supporting iOS 11.0 and up)

Performing certificate transparency checks using the local CT logs on the device for iOS 11.4 (r.74226999 and r. 30743827) are now out of date, and so when performing extra validations using the ATS key for NSRequiresCertificateTransparency on iOS 11 these validations are not guaranteed to work anymore.

Regarding:

The issue here is that this key is only present from iOS 13 onwards.

kSecTrustCertificateTransparency and NSRequiresCertificateTransparency are available in iOS 9+.

I would still recommend that you look at the certificate chain in the SecTrust object from the URLSessionDelegate. This should be able to tell you what certificates are being used here, and if another party is using a certificate to perform a proxy action, you should be able to see this here.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Hi, Need help, I don't have solution but i would like to have hrybrn or meaton help me on How to do what is said above,

... use URLSessionDelegate and after evaluation, check the result of SecTrustCopyResult(_: SecTrust) for the key kSecTrustCertificateTransparency, making sure the value was true.

-Thanks !!

@Youraj

How to do what is said above

Typically a barebones example of this would look something like:

extension ViewController: URLSessionDelegate {

    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            if let secTrustRef = challenge.protectionSpace.serverTrust {
                let host = challenge.protectionSpace.host
                let sslPolicy = SecPolicyCreateSSL(true, host as CFString)
                SecTrustSetPolicies(secTrustRef, sslPolicy)

                var error: CFError?
                if !SecTrustEvaluateWithError(secTrustRef, &error) {
                    print("SecTrustEvaluateWithError failed: \(error.debugDescription)")
                    // Decide whether to do further evaluation on the certificate or fail immediately
                    // completionHandler(.cancelAuthenticationChallenge, nil)
                }

                if let trustDetails = SecTrustCopyResult(secTrustRef) as? [String: AnyObject] {
                    // Extract - trustDetails[kSecTrustCertificateTransparency as String]
                    // Extract - trustDetails[kSecTrustRevocationValidUntilDate as String]
                }
                // Proceed with the completion handler or extracting any other data from
                // secTrustRef or from the server's certificates.
            }
        }
        completionHandler(.cancelAuthenticationChallenge, nil)
    }
}

However there can be much more functionality added here based on your app's requirements.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

Thanks a lot @meaton !!

How to check certificate transparency used during server trust
 
 
Q