There are a lot of questions from our customers about certificate issues during the TLS connection between IoT devices and IoT hub. So here I write this article to reveal something that you need to know when you are trying to connect your IoT devices to Azure IoT hub.
IoT Hub requires all device communication to be secured using TLS/SSL (hence, IoT Hub doesn’t support non-secure connections over port 1883). The supported TLS version is TLS 1.2, TLS 1.1 and TLS 1.0, in this order. Support for TLS 1.0 is provided for backward compatibility only. It is recommended to use TLS 1.2 since it provides the most security.
Firstly, let’s have a look at the process of TLS handshake. Here I quote the steps from this link: https://msdn.microsoft.com/en-us/library/windows/desktop/aa380513(v=vs.85).aspx
- The client sends a "Client hello" message to the server, along with the client's random value and supported cipher suites.
- The server responds by sending a "Server hello" message to the client, along with the server's random value.
- The server sends its certificate to the client for authentication and may request a certificate from the client. The server sends the "Server hello done" message.
- If the server has requested a certificate from the client, the client sends it.
- The client creates a random and encrypts it with the public key from the server's certificate, sending the encrypted Pre-Master Secret to the server.
- The server receives the Pre-Master Secret. The server and client each generate the Master Secret and session keys based on the Pre-Master Secret.
- The client sends "Change cipher spec" notification to server to indicate that the client will start using the new session keys for hashing and encrypting messages. Client also sends "Client finished" message.
- Server receives "Change cipher spec" and switches its record layer security state to symmetric encryption using the session keys. Server sends "Server finished" message to the client.
- Client and server can now exchange application data over the secured channel they have established. All messages sent from client to server and from server to client are encrypted using session key.
In step 3, the server would send server certificate and may request client certificate. There are two types of certificate involved during the TLS handshake:
- Server side certificate. Sent by Azure IoT Hub Server to client.
- Client side certificate. Sent by client to server. It’s optional.
Please note that IoT Hub doesn’t support X.509 mutual authentication at the end of writing this article. So, there isn’t any client certificate required. But we do provide a mechanism to authenticate a device with IoT Hub using X.509 certificate. You can refer to following link for more detail:https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-security#supported-x509-certificates
Since IoT Hub doesn’t support mutual authentication, here we just need to discuss server authentication. There are 3 certificates in play here during the server authentication. These form part of cert chain and are linked together as a chain.
|Type||Issued by||Other info||Expiration|
|Root CA||Baltimore CyberTrust Root||azure-iot-master\c\certs\ms.der, certs.c, certs.h (part of Azure IoT SDK)||5/13/2025|
|Intermediate CA||Baltimore CyberTrust||Sent by Server||12/20/2017|
|Wild Card certificate (leaf)||Microsoft IT SSL SHA2||Sent to all host names ending in *.azure-devices.net (wildcard certificate)||8/26/2017|
Only 2 and 3 are sent by the server as part of TLS handshake. Client will normally validate Root CA of the chain and will determine if it is trusted. If the device doesn’t pass the verification of the server certificate, it will generally report “Unknown CA” error in the network log. You can see from above table that Root CA is included in Azure IoT SDK. So you can either install this Root CA in your device or trust this CA in your device application code explicitly. Generally, CyberTrust Root CA has existed in your Windows and most of Linux desktop version. You don’t need to install the CA to trust the certificate from IOT hub. But in a lot of embedded Linux devices which are tailored CyberTrust Root CA is not provided. And you might not even install it to the system. In this case, you should explicitly trust the certificate in you code. In IoT SDK for C，the sample application has included related code like this but not enabled by default.
#endif // MBED_BUILD_TIMESTAMP
// For mbed add the certificate information
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
printf("failure to set option \"TrustedCerts\"\r\n");
#endif // MBED_BUILD_TIMESTAMP
Here MBED_BUILD_TIMESTAMP is only defined in mBED system. If you want to enable it in other platform which doesn’t include CyberTrust Root CA, you should remove this ifdef or add the definition before compilation.
The certificates data is hardcoded in certs.c. In your real code, you should provide an interface to adjust it in case there is any certificate change. There aren’t many cases which need to do the change. The certificates sent from IoT hub is not changeable and configurable by the users. But Microsoft might change the certificate for some reason. And the root certificates still may expire or be revoked though they are long-lived. If there is no way of updating the certificate on the device, the device may not be able to subsequently connect to the IoT Hub (or any other cloud service). Having a means to update the root certificate once the IoT device is deployed will effectively mitigate this risk.
Note that China Azure didn’t use CyberTrust Root CA. Instead it still uses WoSign Root CA. This certificate is also included in certs.c so that you don’t need to change anything for China Azure connection. But it only works for IoT SDK for C. In IoT SDK for other language, this certificate might not be included in the sample code. You should add the correct certificate data explicitly.
You can also bypass the certificate validation although it’s definitely not recommended. We don’t provide the surface in the IoT SDK APIs. You can modify the code in OpenSSL or websocket layer to disable SSL verification if needed for development or if you know exactly what your case is.
That’s all I want to discuss in this post. I hope it helps to solve connection issue between device and IoT Hub. .