Introduction to Security and TLS
Introduction to Security and TLS
IoT security is always a top concern, so let's see how you can ensure your users are protected with this journey into secure architecture and TLS.
Join the DZone community and get the full member experience.Join For Free
Digi-Key Electronics’ Internet of Things (IoT) Resource Center Inspires the Future: Read More
IoT (Internet of Things) is all about connecting to the internet and even more about security. Without security and encrypted communication, everyone can possibly 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, which I want to use for my MQTT communication (see MQTT with lwip and NXP FRDM-K64F Board).
I'm still learning MQTT, and I'm learning more 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 through the basic principles for secure communication using TLS with MQTT in mind. TLS is the successor of SSL (Secure Sockets Layer), and the two are often 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 that the application uses to communicates with the other side. The same principle applies to running the MQTT Mosquitto broker (or any server) on my host machine.
Unencrypted Communication Stack
MQTT is a special "language" using TCP (Transmission ControlProtocol), and sits between the application and the TCP/IPstack. The application uses the MQTT layer to talk and understand the MQTT language:
Application stack with MQTT
TCP/IP uses "sockets" or "ports." By default, Mosquitto is usingthe port 1883 (see MQTT with lwip and NXP FRDM-K64F Board), which is not using an encryption protocol. That means that everyone can potentially see the exchange of data between the MQTT broker and clients. Having an unencrypted connection is a great with MQTT, as this is a simple and easy way to start exploring MQTT.
Configuring encryption and using an encrypted connection, on the other hand, is much more complex. But once I have things working unencrypted for testing purposes, I definitely want to use encrypted communication. Instead of doing "end-to-end" encryption in the application itself, a better approach is to put an encryption layer on top of the communication stack:
MQTT Application with Encryption
This way the application 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. With encryption, there is the need for "keys:" sequences 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, security depends how securely I can distribute and keep that key.
With asymmetric encryption, I have a pair of mathematically connected keys: a shared green key 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 use 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 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 someone I know, but instead it's a "man in the middle" intercepting all messages, so I have that public key instead.
Here, certificates come into play. Certificates are a kind of passport, provided by a Certification Authority (CA), which testify that the certificate holder is really that person. The certificate itself can be used to encrypt and verify a key, similar to packing a key into a certificate. In our example, 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 several different ways and protocols 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 exchanged using a multi-stage protocol like TLS.
Transport Layer Security (TLS) Protocol
TLS has a few 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) message to the server, asking for an encrypted session.
Server responds with their 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 they have generated to the server.
The server uses its private key to extract the premaster 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.
I don't plan on implementing 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 FRDMK64F board, I have found the following options:
• OpenSSL (openssl.org/): A very complete and capable open source implementation with good documentation. It's mostly targeting desktop and Linux machines, as well as bigger embedded devices. I have a permissive license, and it's and moving to Apache license version. But because of the general overhead, I didn't consider it for use with the FRDM-K64F.
• wolfSSL (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 is outside of my budget.
• CycloneSSL (oryx-embedded.com/cyclone_ssl.html): Good features, but same as wolfSSL: GPL license and commercial version only.
• mbedTLS (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. 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. You can check my site for more information.
To use secure data transport, I have to use encryption. Cryptographic algorithms are provided with several open source libraries, and the mbedTLS library seems to fit my needs best. The key 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.
Opinions expressed by DZone contributors are their own.