Add encryption and SSL/TLS into your IoT project

This is post 5 of the series/tutorial. Here are the other posts, in case you need them: Post #1, Post #2, Post #3 and Post #4.

Before we get soaked in, let me remind you that in case you are looking for a post on the best practices for encryption, SSL, TLS, DTLS or general informational security, this is not the post for you. I am not an expert in any of these fields. If you need such kind of information, Google is a better place to find an answer.

Now we get to what this post is about.

First, SSL has since been succeeded and superseded by TLS and in the rest of this post, I do not use SSL but instead TLS. However, TLS was built on top of SSL and as such the two are used interchangeably.

As pointed out, I am not an expert in informational security so I have to use a built library (or set of APIs) for performing these security operations. But even using libraries or APIs is not an easy task. This is especially the case for security-related ones. Even if they are documented, they tend to have a lot of elements in them that you may get lost in the abbreviations, acronyms, internet standards, etc. The SSL/TLS libraries are no exception. The libraries get complicated because the need to support several features due to possible scenarios such as:

  1. The server supports more functionality than the client, say when the client is an old browser accessing a web page on a more recent server. The server side will need a strong and capable engine to support both legacy and newer protocols.
  2. The client supports more functionality than the server, say a new client accessing an old server that has not been updated for years. The client-side will need a strong and capable engine.

In the TLS handshake process, the server and client will agree on a cipher to use depending on the capabilities of both. As such the TLS library supports several of them.

When choosing a library to use, I look out for documentation and clean work. This is only when I have options and this case happens to be one. To support TLS on an IoT device we can use OpenSSL, WolfSSL (formerly CyaSSL), CycloneSSL, or mbedTLS (formerly PolarSSL). These are just the common ones. There might be more.

A̶ ̶q̶u̶i̶c̶k̶ ̶n̶o̶t̶e̶,̶ ̶a̶s̶ ̶o̶f̶ ̶t̶h̶e̶ ̶t̶i̶m̶e̶ ̶o̶f̶ ̶w̶r̶i̶t̶i̶n̶g̶ ̶t̶h̶i̶s̶ ̶a̶r̶t̶i̶c̶l̶e̶,̶ ̶C̶y̶c̶l̶o̶n̶e̶S̶S̶L̶ ̶d̶o̶e̶s̶ ̶n̶o̶t̶ ̶e̶v̶e̶n̶ ̶u̶s̶e̶ ̶a̶ ̶c̶o̶r̶r̶e̶c̶t̶ ̶S̶S̶L̶ ̶c̶e̶r̶t̶i̶f̶i̶c̶a̶t̶e̶ ̶o̶n̶ ̶t̶h̶e̶i̶r̶ ̶w̶e̶b̶s̶i̶t̶e̶,̶ ̶i̶f̶ ̶y̶o̶u̶ ̶t̶r̶y̶ ̶t̶o̶ ̶l̶o̶a̶d̶ ̶t̶h̶e̶ ̶h̶t̶t̶p̶s̶ ̶v̶e̶r̶s̶i̶o̶n̶ ̶o̶f̶ ̶i̶t̶.̶ ̶F̶o̶r̶ ̶m̶e̶,̶ ̶t̶h̶i̶s̶ ̶d̶o̶e̶s̶ ̶n̶o̶t̶ ̶m̶a̶k̶e̶ ̶a̶ ̶v̶i̶a̶b̶l̶e̶ ̶c̶h̶o̶i̶c̶e̶. On March 8, 2017, a representative of Orynx Embedded which owns CycloneSSL reached out clarifying that the CycloneSSL website does not use encrypted communication and this explains the SSL certificate error.

A few weeks ago, Keil MDK5 added a pack for mbedTLS making all the SSL/TLS libraries mentioned above available for your Keil Project as is evident below.

Initially, I had to add the source manually before configuring it. The final choice would only depend on the ease of use, documentation, and cleanness of code. Sometimes you want to know why something is failing and you need to dig into the library code.

I choose to use mbedTLS. It is not the most widely used but I found it to be the cleanest and the one that requires the least memory footprint in my code. Furthermore, it supports TLSv12 which WolfSSL did not. TLS version 1.2 is the latest as version 1.3 is still draft as of this writing.

The real choice comes when you decide to use a library and you need to test it first. The WolfSSL library required me to know a lot of compile-time options to get it to compile and even after compiling it did not work on a real network stream. In general, it took too much time with no concrete results compared to mbedTLS. It does not mean that it does not work. In fact, it seems more common than mbedTLS as even Microsoft uses it in its IoT client libraries.

The main disadvantage of using mbedTLS is that there are a lot of configurable options in its configuration file and you may need to understand all of them which is overwhelming. But this also happens to be an advantage because, by making the right choice, it can work on any platform or environment, from Windows to Linux to Embedded. It does not rely on specific compiler functions like time(), gmtime() unless you explicitly opt-in that support using MBEDTLS_HAVE_TIME or MBEDTLS_HAVE_TIME_DATE options.

The configuration of the library is never an easy step but with the correct background information on the protocols, it is a very easy step. This background information may either come as a cost in money or time. Fortunately, the mbedTLS documentation, though not as much as I would have wished, comes to the rescue.

ADDING MBEDTLS TO KEIL PROJECT

First, ensure that the pack is installed as in the image above. You only need the pack labeled ARM::mbedTLS.

Before adding, make sure your project compiles properly without errors or warnings. Otherwise, they may blur you when configuring the TLS library.

Next, add mbedTLS to your project through the Manage Run-Time Environment dialog accessible on the same toolbar where you find the build buttons. The image below shows what checkbox to tick.

add-mbed-tls

Afterward, you will get a new node in your project named Security, with a green diamond. Ensure that your project builds.

Within the Security node, open a file named mbedTLS_config.h and you will find all options are commented out. This means that the mbedTLS code is not included in the build despite all the required C files being present. There are 145 options available for your configuration options; maybe more. In case you fail to include a required feature, check_config.h will help you get it right by printing out error messages. I cannot go through each of the available options here because there is a better place for that.

RUNNING

To get things right for a start, copy from the sample located at

{your-keil-install-directory}\ARM\Pack\mbedTLS{the-version-downloaded}\MDK\examples\ssl_client1.

In my case it is C:\Keil\_v5\ARM\Pack\ARM\mbedTLS\1.0.0\MDK\examples\ssl_client1. If you are using the same processor as in the example, you need not change anything. But for different processors, you may need to do a new project and stepwise addition as above. You should copy the contents of mbedTLS_config.h from the sample for an easy experience for the first time.

The sample should run but you will get a few errors printed in your debug window which we will look at in the next post.

NOTES

The ssl_client1 example will access tcp/tls.mbed.org/443 which is equivalent to https://tls.mbed.org. It may fail to make a connection to the host at first but try more than once. When it makes a connection, you will see the HTTP page printed on your debug window.

SSL/TLS secure internet traffic and thus you need the network component correctly configured in your project and a working internet connection. I suggest using Ethernet for this test as PPP (Modems) normally takes more time to make a connection or it may fail to connect. When testing you should not be worried about the internet connection.