IoT (Internet of Things) is all about connecting to the internet. And even more it is about security. Without security and without encrypted communication, everyone possibly can see what I send or receive. And this is especially bad if passwords or user names are sent in an unencrypted way. So encryption and secure communication is key. The solution to that is to use a connection which uses the TLS (Transport Layer Security) protocol.
I want to use TLS for my MQTT communication (see “MQTT with lwip and NXP FRDM-K64F Board“). I’m still learning MQTT, and I’m even more learning about the fundamentals of security and security protocols. So this article is about what I have learned recently, and what I can use to make my data communication secure: Network stack architecture, symmetric and asymmetric encryption and certificates.
This article walks though the basic principles for a secure communication using the TLS (Transport Layer Security) protocol, with MQTT in mind. TLS is the successor of SSL (Secure Sockets Layer), and often are used together (TLS/SSL). TLS (as the name indicates) is an encryption on the transport layer: that means that the application layer does not have to implement the encryption itself: instead, it configures the transport layer to use the encryption protocol.
For an application (e.g. running on a microcontroller) to communicate with the internet, it requires a communication stack (TCP/IP, e.g. lwip) plus the needed hardware to communicate with the physical layer (e.g. the FRDM-K64F board). TCP/IP itself is the common ‘language’ how the application communicates with the other side:
The same principle applies to running the MQTT Mosquitto broker (or any server) on my host machine.
MQTT is a special ‘language’ using TCP (Transmission Control Protocol), and basically sits between the application and the TCP/IP stack: the application uses the MQTT layer to talk and understand the ‘MQTT language’:
TCP/IP uses ‘sockets’ and/or ‘ports’. By default, Mosquitto is using the port 1883 (see “MQTT with lwip and NXP FRDM-K64F Board“) which is not using an encryption protocol. That means that potentially everyone can see the exchange of data between the MQTT broker and clients. Having an unencrypted connection is a great with MQTT, as this is simple and gives an easy way to start exploring MQTT. Configuring encryption and using an encrypted connection on the other side is much more complex. But once I have things working in the unencrypted way for testing purposes, I definitely want to use an encrypted communication.
Instead doing an ‘end-to-end’ encryption in the application itself, a better approach is to put in an encryption layer on top of the communication stack:
That way the application (or MQTT language speaking part) does not need to implement the encryption protocol itself, it simply talks to the encryption layer and that will do all the work.
Symmetric and Asymmetric Encryption
Encryption relies a lot on math, random number generators and cryptographic algorithms. And with encryption there is the need for ‘keys’: a sequence of bits and bytes which are used to ‘lock’ (encrypt) and ‘unlock’ (decrypt) the data.
With symmetric encryption, the same key is used to encrypt and decrypt a message:
It means that everyone having that (blue) key will be able to decrypt the message. So the security depends how secure I can distribute and keep that key.
With the asymmetric encryption, I have a pair of mathematically connected keys: a shared green and a private red key. I keep the red key private and do not disclose and distribute it. The green key is public: everyone can have it. Everyone can encrypt a message with the green public key, but only the one with the red private key is able to decrypt it:
💡 The public and private key build a pair of keys. They are different, but are mathematically related. That way only the private key is able to decrypt a message encrypted with the public key.
But how can I know that the public key I have received is really from the person I think it is coming from? Maybe I think I have received the public key from the person I think it is, but indeed it is a ‘man in the middle’ intercepting all messages and an I have that middle men public key instead?
Here ‘certificates’ come into the play. Certificates are a kind of passport, provided by a ‘Certification Authority’ (CA) which testifies that person is really that person.
The certificate itself can be used to encrypt and verify a key, similar like packing the key into a certificate:
Sue then can use the trusted certificate to extract the key. If that fails, Sue knows that the certificate with the key is not coming from Joe.
There are different ways and protocols how to distribute the keys and certificate. Usually the keys/certificates are pre-distributed (e.g. pre-installed on the devices), or the secret information is built up and exchanged using a multi-stage protocol like TLS.
Transport Layer Security (TLS) Protocol
TLS exists in different versions (current version is 1.2, with 1.3 in the draft state). TLS is using a special protocol called ‘Handshake’ to agree on the protocol and to exchange keys (see this link for details). Basically the certificate is used to verify the server identity, and the asymmetric encryption is used to exchange a shared secret key for symmetric encryption:
- Client sends a clear (unencrypted) ‘hello’ message to the server, asking for an encrypted session.
- Server responds with a his server certificate which includes the server public key in it.
- Client verifies the certificate and extracts the public key.
- Client uses the public key to send a ‘pre-master’ key he has generated to the server.
- The server uses its private key to extract the ‘pre-master’ key.
- Both the client and the server use the ‘pre-master’ key to compute a shared secret key.
- Client sends a message to the server encrypted by that shared secret key.
- The server decrypts the received message and checks it.
- If that passes, the server sends back an encrypted message using the shared secret key to the client to confirm that everything is ok.
- From this point on, both the client and server are using the shared secret key for their communication.
The graph from https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm provides a good overview of the handshake process:
I don’t plan to implement TLS or the cryptographic algorithms ;-). Instead, I was looking for an open source library I could use. There are different vendors providing encryption middleware. For my project with MQTT, lwip and the FRDM-K64F I have found the following:
- OpenSSL (https://www.openssl.org/): very complete and capable open source implementation with good documentation. More targeting desktop and Linux machines, and less smaller embedded devices. I has a permissive license and is moving to Apache license version. But because of the general overhead I don’t consider it to use with the FRDM-K64F.
- wolfSSL (https://www.wolfssl.com/wolfSSL/Home.html), formerly CyaSSL: Targeting embedded devices, it would fit on the FRDM-K64F. The free Open Source (GPLv2 and GPLv3) version is restrictive, and the commercial one outside of my budget 😦
- CycloneSSL (https://www.oryx-embedded.com/cyclone_ssl.html): good features, but same as wolfSSL: GPL license and commercial version only.
- mbedTLS (https://tls.mbed.org/), formerly PolarSSL: owned by ARM, good documentation, and its Apache 2.0 license allows me to use it in both commercial and open source projects for free. And it seems to be used with lwip too (more about this later).
The mbedTLS has been the most versatile and open library I have found, and this is why I have started using it in my project. More about it in a next article.
To use a secure data transport, I have to use encryption. Cryptographic algorithms are provided with several open source libraries, where the mbedTLS library seems to fit my needs best. Key (sic!) to encryption is the distribution and handling of keys and certificates. TLS (or Transport Layer Security) is a protocol which manages key verification and distribution which is provided in the mbedTLS library.
In a next article I cover the topic how to enable TLS between a MQTT Mosquitto broker and the MQTT client, which is a lot about creating keys and certificates :-).
Happy Transporting 🙂
- Wikipedia: https://en.wikipedia.org/wiki/Transport_Layer_Security
- SLL for secure MQTT: http://rockingdlabs.dunmire.org/exercises-experiments/ssl-client-certs-to-secure-mqtt
- Behind the Scenes of SSL Cryptography: https://www.digicert.com/ssl-cryptography.htm
- ARM mbed TLS library: https://tls.mbed.org/