Trusted SSL pinning ignore "hostname mismatch" error

In case, hostname/domain of server is unspecified. I want to use SSL pinning to trust root certificate without hostname/domain.


I tried the with below code:


extension SecTrust {
    func evaluate() -> Bool {
        var trustResult: SecTrustResultType = .invalid
        let err = SecTrustEvaluate(self, &trustResult)
        guard err == errSecSuccess else { return false }
        var allow = [.proceed, .unspecified].contains(trustResult)
        if !allow {
            guard let arr = SecTrustCopyProperties(self) as? [NSDictionary] else {
                return false
            }
            print(String(describing: arr))
            // only ignore in case hostname mismatch.
            if arr.count == 1 {
                if let errMsg = arr[0]["value"] as? String, errMsg.elementsEqual("Hostname mismatch.") {
                    SecTrustSetExceptions(self, SecTrustCopyExceptions(self))
                    SecTrustEvaluate(self, &trustResult)
                    allow = [.proceed, .unspecified].contains(trustResult)
                }
            }
        }
        
        return allow
    }
    
    func evaluateAllowing(rootCertificates: [SecCertificate]) -> Bool {
        // Apply our custom root to the trust object.
        var err = SecTrustSetAnchorCertificates(self, rootCertificates as CFArray)
        guard err == errSecSuccess else {
            return false
        }

        // Re-enable the system's built-in root certificates.
        err = SecTrustSetAnchorCertificatesOnly(self, false)
        guard err == errSecSuccess else { return false }
        
        // Run a trust evaluation and only allow the connection if it succeeds.
        return self.evaluate()
    }
}

extension Bundle {
    func certificate(named name: String, type: String = "der") -> SecCertificate? {
        let cerPath = self.path(forResource: name, ofType: type)!
        let cerData = NSData(contentsOfFile: cerPath)
        let cer = SecCertificateCreateWithData(nil, cerData!)
        return cer ?? nil
    }
}



My code is correct or not?

Accepted Reply

Is there any way to trust for any hostname?

You can use a basic X.509 policy (

SecPolicyCreateBasicX509
) rather than the TLS policy.

Do you have some other mechanism to identify the remote peer? If not, I’m concerned about the security of your approach. One of TLS’s main goals is confidentiality, and that’s completely undermined if you can’t identify the remote peer (because Mallory can intercept your connection and you can’t distinguish them from Bob).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Can you explain more about why you’re getting a host name mismatch?

The code you posted does what you says it does — at least in my limited review — but I worry about your overall strategy. Rather than use the exceptions mechanism, I usually resolve host name mismatch problems by customising the policy object used by the trust evaluation. That is, I use

SecPolicyCreateSSL
to create a policy object with the correct host name and then apply that policy to my trust object using
SecTrustSetPolicies
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the response.


As I said: Hostname/domain in my case is unspecied. Because, the hostname/domain maybe an any devices (as smart phone, etc).

Host and app are connected via IP address of specified device (IP address is not fixed).

I think that, the hostname/ domain can't determine in this case.

Is there any way to trust for any hostname?

Is there any way to trust for any hostname?

You can use a basic X.509 policy (

SecPolicyCreateBasicX509
) rather than the TLS policy.

Do you have some other mechanism to identify the remote peer? If not, I’m concerned about the security of your approach. One of TLS’s main goals is confidentiality, and that’s completely undermined if you can’t identify the remote peer (because Mallory can intercept your connection and you can’t distinguish them from Bob).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for responsing.


It helped me a lot.

Hi Eskimo,

I am recieving "recoverableTrustFailure" on evaluating the SSL certificate using SecTrustEvaluate api in iOS13. SecTrustEvaluateWithError is returning me "certificate is not trusted" as the error. This certificate was working without issues in iOS12.


Any help will be appreciated as I am blocked with my application development.


Thanks,

Jala