Hi @eskimo,
Thank you very much for your tips it works for me like a charm!
However I am facing now new issue and can not find anywhere clear enough answer to my problem. So briefly to remaind what I am trying to achieve:
1. Generate pair of keys
2. Create CSR using keys from step 1
3. Do receive PEM in response to CSR post
4. Decode it
5. Store in same keychain as keys are
6. Create digital identity credentials and use for URLAuthenticationChallenge for NSURLAuthenticationMethodClientCertificate
7. When try to call final enpoint (https://192.168.***.YYY:8080/myrequest), veryfing serves with ca_self_signed_cert and use digital identity credentials from step 6 do receive error in URLSession dataTask completion handler as follows:
NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."
NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x1c0119740>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-1, NSErrorPeerCertificateChainKey=(...)
Also in debbuger do notice following message:
[BoringSSL] Function boringssl_context_parse_identity_certificate_chain: line 3781 The type of the leaf certificate is not that of `SecIdentityGetTypeID()`
I am able to create now SecIdentity with success and add to URLSessionDelegate challange, however do receive error and it looks like ATS blocks something.
FYI my url looks as follows and it is not a local one: https://192.168.***.YYY:8080/myrequest
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {
let getCertQuery: [String: Any] = [
kSecClass as String : kSecClassCertificate,
kSecReturnData as String : kCFBooleanTrue,
kSecReturnAttributes as String : kCFBooleanTrue,
kSecReturnRef as String : kCFBooleanTrue
]
var certItem: CFTypeRef?
let certStatus = withUnsafeMutablePointer(to: &certItem) {
SecItemCopyMatching(getCertQuery as CFDictionary, UnsafeMutablePointer($0))
}
guard certStatus == errSecSuccess else { return }
let certificate = certItem as! SecCertificate
let getIdentityQuery: [String: Any] = [
kSecClass as String : kSecClassIdentity,
kSecReturnData as String : kCFBooleanTrue,
kSecReturnAttributes as String : kCFBooleanTrue,
kSecReturnRef as String : kCFBooleanTrue,
kSecMatchLimit as String : kSecMatchLimitAll
]
var identityItem: CFTypeRef?
let identityStatus = withUnsafeMutablePointer(to: &identityItem) {
SecItemCopyMatching(getIdentityQuery as CFDictionary, UnsafeMutablePointer($0))
}
guard identityStatus == errSecSuccess else { return }
let identity = identityItem as! SecIdentity
// Create digital identity credentials
let credentials = URLCredential(identity: identity, certificates: [certificate], persistence: .forSession)
return completionHandler(.useCredential, credentials)
} else if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
var localTrust: SecTrust?
let policy = SecPolicyCreateBasicX509()
let serverTrust = challenge.protectionSpace.serverTrust!
for index in 0..<SecTrustGetCertificateCount(serverTrust) {
guard let cert = SecTrustGetCertificateAtIndex(serverTrust, index) else { break }
var servTrust: SecTrust?
SecTrustCreateWithCertificates(cert, policy, &servTrust)
let localServKey = SecTrustCopyPublicKey(servTrust!)!
let certificateData = NSData(contentsOfFile: Bundle.main.path(forResource: "ca_self_signed_cert", ofType: "der")!)
let localCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, certificateData!)
if SecTrustCreateWithCertificates(localCertificate!, policy, &localTrust) == errSecSuccess {
let localPublicKey = SecTrustCopyPublicKey(localTrust!)!
if (localPublicKey as AnyObject).isEqual(localServKey as AnyObject) {
print("trusted")
let credential = URLCredential(trust: serverTrust)
return completionHandler(.useCredential, credential)
}
}
}
}
}
I would be very gratefull for any tips here
Cheers