My app is using a self signed certificate and we are planning to use the same in production.
To avoid asking user to install the certificate manually, can I add the certificate to the list of trusted anchors using SecTrustSetAnchorCertificates(_: _:)
. Is this a correct approach ?
Please find the code below:
func addAnchorToTrust(trust: SecTrust, certificate: SecCertificate) -> SecTrust { let array: NSMutableArray = NSMutableArray() array.add(certificate) SecTrustSetAnchorCertificates(trust, array) return trust } func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let serverTrust = challenge.protectionSpace.serverTrust else { completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) return } let filePath = Bundle.main.path(forResource: "httpsPublicCertificate", ofType: "cer") guard let file = filePath, let savedCertificateData = NSData(contentsOfFile: file), let rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, savedCertificateData) else { completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) return } let sslInput = addAnchorToTrust(trust: serverTrust, certificate: rootCert) var result: SecTrustResultType = SecTrustResultType.unspecified let error: OSStatus = SecTrustEvaluate(sslInput, &result) if (error != 0){ completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) return } guard self.validate(trust: serverTrust, with: SecPolicyCreateBasicX509()), let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else { completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil) return } let serverCertificateData = SecCertificateCopyData(serverCertificate) let serverCertificateDataPtr = CFDataGetBytePtr(serverCertificateData); let serverCertificateDataSize = CFDataGetLength(serverCertificateData); let serverCertificateNSData = NSData(bytes: serverCertificateDataPtr, length: serverCertificateDataSize) if serverCertificateNSData.isEqual(to: savedCertificateData as Data) { completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:serverTrust)) return } } private func validate(trust: SecTrust, with policy: SecPolicy) -> Bool { let status = SecTrustSetPolicies(trust, policy) guard status == errSecSuccess else { return false } return SecTrustEvaluateWithError(trust, nil) }
The communication is between app and a local accessory
OK, well, that’s a critical tidbit.
The situation with accessories on the local network is a tricky one. It’s something I’ve discussed with developers many times before, so I took the time today to write it up properly. Please have a read through TLS For Accessory Developers and post back here if you have any questions.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"