Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift and SecTrust

Tags:

ios

swift

I'm having some troubles trying to convert code that I've found in the Apple documentation into swift code. To be precise it is stuff about TSL and certificates...

https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html

This is the original code in Objective-C

SecTrustResultType secresult = kSecTrustResultInvalid;
if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) 
     return;
}

And this is my attempt...

var secresult:SecTrustResultType = kSecTrustResultInvalid // ERROR 1 
if (SecTrustEvaluate(trust, &secresult) != errSecSuccess) { // ERROR 2
   return;
}

ERROR 1 is:

'Int' is not convertible to 'SecTrustResultType'

ERROR 2 is:

 Could not find an overload for '!=' that accepts the supplied arguments

Now, I see that SecTrustResultType is a UInt32 and kSecTrustResultInvalid is an Int... but this header is defined by Apple so I suppose that it should be correct :P

typealias SecTrustResultType = UInt32
var kSecTrustResultInvalid: Int { get }

About the second error I really don't know how to manage it since the function SecTrustEvaluate returns a OSStatus (that is an alias for UInt32) and errSecSuccess is a OSStatus too.

I'm really confused. Do you have any suggestion to make this stuff work!?

like image 538
MatterGoal Avatar asked Apr 29 '15 10:04

MatterGoal


4 Answers

I ran into this issue myself and the header docs are a little bit confusing especially since the constants are defined as Ints and SecTrustResultType is defined as a UInt32.

But good news, the solution is rather simple just init SecTrustResultType with kSecTrustResultInvalid:

var secresult = SecTrustResultType(kSecTrustResultInvalid)
if (SecTrustEvaluate(serverTrust, &secresult) != errSecSuccess){
       return;
}
like image 69
Shuckstack Avatar answered Nov 11 '22 08:11

Shuckstack


You can init SecTrustResultType with this line in Swift 5

var secResult = SecTrustResultType.invalid

Different from the other answers, I preferred a single result handle ( SecTrustResultType ) when I checked a server's Certificate Chain. Please see below:

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

        guard let trust: SecTrust = challenge.protectionSpace.serverTrust else {
            return
        }

        var secResult = SecTrustResultType.invalid
        SecTrustEvaluate(trust, &secResult)
        switch secResult {
          case .proceed:
            // ✅
          case .recoverableTrustFailure:
            // ❌ check Root CA and Int CA trusted on IOS device
          default:
            // ❌ default error
        }

        completionHandler(.performDefaultHandling, nil)
    }
like image 34
rustyMagnet Avatar answered Nov 11 '22 06:11

rustyMagnet


Swift 2.3

var secresult = SecTrustResultType.Invalid
if (SecTrustEvaluate(serverTrust, &secresult) != errSecSuccess){
       return;
}
like image 2
Nagendra Rao Avatar answered Nov 11 '22 07:11

Nagendra Rao


Based on the great answer from rustyMagnet

Updated for Swift 5.4 and macOS 11

var secResult = SecTrustResultType.invalid
SecTrustGetTrustResult(trust, &secResult)
switch secResult {
case .proceed:
    // ✅
case .recoverableTrustFailure:
    // ❌ check Root CA and Int CA trusted on IOS device
default:
    // ❌ default error
}
like image 2
vauxhall Avatar answered Nov 11 '22 06:11

vauxhall