It’s been months since I started playing with a STM32 Nucleo + Ethernet shield. One of the objectives that I chase is to build a device for the Internet of Things that implement reasonably secure communications. In an effort to avoid reinventing the wheel (or at least to not reinvent too many wheels) I wanted to see if I could use HTTPS. HTTPS is a secure protocol that is based on TLS, and I specifically tried to integrate in my setup TLS 1.2, which is specified by RFC 5246.
One challenge is to fit the functionality into the STM32F103RB, that has 128KiB of Flash and 32KiB of RAM. The clock speed should not be a problem, I’m not aiming for performance but for functionality. For starting I simply want to create an HTTPS connection to a website, and send an HTTP GET request to retrieve a web page. Note that TLS specifications say that the only mandatory cipher suite is TLS_RSA_WITH_AES_128_CBC_SHA , so I need the program to implement just this.
I am working on a library that implements many POSIX-compliant functionalities, especially TCP and UDP network sockets (the source code is in GitHub nucleo_tests repository). The hope is that existing open source projects implementing TLS are able to compile using these basic functionalities. There are some projects that target small devices, and between those candidates I chose to try WolfSSL and mbed TLS.
I downloaded wolfssl 3.7.0 and tried to compile it with GCC ARM Embedded toolchain and my POSIX header. It just needed a small patch on some OS-dependant code, because I don’t have a real OS but a bare metal library that implements some OS functionality. Then I configured it disabling all I could, reducing the footprint because I needed to stay below the 128KiB of flash that the STM32 contains. I also avoided verifying the site certificates. Unfortunately the resulting program needs still too much RAM to run, in fact when I tried to run the program it crashed on a malloc. From “objdump -h” I notice that it needs 105KiB of flash, 2.5KiB of statically allocated RAM, and evidently needs too much dynamically allocated RAM. I tried to compile wolfssl and the test program on Linux, and the page was successfully retrieved.
mbed TLS has a similar story. I got mbedtls 2.2.0 source code, configured with minimal functionalities and compiled it, also following suggestions from their notes to “Reduce mbed TLS memory and storage footprint“. Unfortunately the program still needs 84KiB of Flash, 2.5KiB of statically allocated RAM, and more than 32KiB of dynamically allocated RAM. From their pages they made me notice that TLS actually requires 16KiB to contain a single fragment, and mbed TLS allocates two buffers, one for outgoing and one for incoming fragments, that are slightly bigger than 16KiB because of some protocol overhead. mbed TLS contains a configuration that allows to reduce this buffer’s dimension, but unfortunately it doesn’t seem to work when retrieving web pages through HTTPS, my interpretation is that the website doesn’t have to implement the functionality that negotiates the maximum fragment size.
I also tried to take OpenSSL 1.0.2e source and compile it, but my impression is that my POSIX library doesn’t have enough functionality yet.
I want to point out that these are the results I managed to obtain in my spare time with my knowledge and abilities, it is entirely possible that these memory requirements can be optimized more. This post is not meant as judgement on the bloat of some open source libraries or on the tiny resources of some hardware. I just explored the possibility that my Nucleo could run some open source TLS implementations, and the result is that I’m not able to run them.
My conclusion is that in order to run an application on TLS, for example an HTTPS client, I need at least 64KiB of RAM and around 256KiB of flash because half of them are occupied by the secure protocol stack. For example the NUCLEO-L476RG, that mounts an STM32 with 1MiB of flash and 128KiB of RAM, and contains also a true random number generator that is useful in order to add entropy to the security procedures.
- Update on POSIX socket library for W5100: client and server for TCP or UDP
- Arduino Ethernet shield on STM32 Nucleo
- STM32 on Linux