I’m reviewing the Losant SDK code for Arduino.
I notice that while the device connects to Losant platform over TLS, it has no way to verify the certificate.
- The CA certificate or server certificate is not specified in the code, and I doubt the device would have a complete CA certificate bundle.
- Even if we put in a CA certificate or server certificate: The device does not have a reliable source of clock, and therefore cannot determine whether the certificate is expired.
- If we set clock from NTP: the device cannot verify the identity of the NTP server.
Man-In-The-Middle attacker can use an invalid certificate and pretend as the Losant broker.
Therefore, the protocol design of MQTT over TLS is flawed.
I think a better design is to use symmetric encryption negotiated with ECDH.
The workflow would be:
- To register a device, the user generates an EC key pair locally, and enter the public key into Losant platform.
- When a device connects to Losant, it sends its deviceId in plaintext.
- The server queries the database to find the public key of the device.
- The server generates a temporary EC key pair, and sends the public key to the device. The device does not verify this public key.
- Both the server and the device calculate a symmetric key with ECDH algorithm. This algorithm, with 160-bit keys, is reasonable fast on a microcontroller.
- Subsequent messages are encrypted with the symmetric key.
Note that the device’s EC public key from step1 is not actually be public. It’s only shared between Losant and the device.
Since the device’s EC public key is only known by the device itself and the Losant platform, MITM attacker cannot calculate the correct symmetric key with ECDH.
A simpler design is to use a pre-shared symmetric key for all communication.
However, a drawback for this approach is that all traffic is using the same symmetric key, so the key has higher exposure.