I'm currently trying to work out how to interact with the Device Provisioning Service (DPS) in Azure's IoT Hub from iOS. I'm using the REST API (which seems to be very poorly documented) due to the fact that the Azure IoT CocoaPods don't include the DPS functionality.
Our application requires that a device registers using a self-signed X509 certificate. In order to do this I'm generating a CSR and then submitting that to a certificate signing server and receiving a self-signed certificate that can be used with Azure.
I'm converting the certificate to 'DER' data and importing it into the Keychain. The Private Key already exists in the keychain from when the CSR was generated.
When I make a request to the DPS Register Device API I receive two authentication challenges; a Server Trust challenge (NSURLAuthenticationMethodServerTrust) and a Client Certificate challenge (NSURLAuthenticationMethodClientCertificate)
This where I'm running into problems. I'm not sure how to correctly proceed here. I'm constructing a URLCredential for the second challenge like so:
let identityQuery: [String: Any] = [
String(kSecClass): kSecClassIdentity,
String(kSecReturnRef): kCFBooleanTrue,
String(kSecAttrLabel): certificateName(forDevice: device)
]
var rawIdentity: AnyObject?
let identitySuccess = SecItemCopyMatching(identityQuery as CFDictionary, &rawIdentity)
if identitySuccess == errSecSuccess {
let identity = rawIdentity as! SecIdentity
var certificate: SecCertificate?
SecIdentityCopyCertificate(identity, &certificate)
return URLCredential(identity: identity, certificates: [certificate], persistence: .forSession)
}
This extracts both the certificate and the identity, but when I respond to the challenge I get an SSL error:
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to
the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9816, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?,
NSUnderlyingError=0x6000022b8240 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)"
UserInfo={_kCFStreamPropertySSLClientCertificateState=0,
_kCFNetworkCFStreamSSLErrorOriginalValue=-9816, _kCFStreamErrorDomainKey=3,
_kCFStreamErrorCodeKey=-9816}}, NSLocalizedDescription=An SSL error has occurred and a secure
connection to the server cannot be made., NSErrorFailingURLKey=https://global.azure-devices-provisioning.net/[scope_id]/registrations/[device-uuid]/register?api-version=2019-03-31,
NSErrorFailingURLStringKey=https://global.azure-devices-provisioning.net/[scope_id]/registrations/[device-uuid]/register?api-version=2019-03-31,
_kCFStreamErrorDomainKey=3}
If anyone has any experience with this on iOS, any help would be greatly appreciated.