Getting mbedTLS to work with your Keil project

This is post 6 of the series/tutorial. In case you have not gone through the other posts, you can do so now.

In the previous post (post #5), we added mbedTLS to the project and agreed that we would follow the sample that comes with the mbedTLS pack. If you followed everything correctly you should see an output such as the one below. There are several additional steps but I discuss them below the dump.

. Seeding the random number generator... ok
  . Loading the CA root certificate ... ok (0 skipped)
  . Connecting to tcp/tls.mbed.org/443... ok
  . Setting up the SSL/TLS structure... ok
  . Performing the SSL/TLS handshake... C:\\Keil_v5\\ARM\\PACK\\ARM\\mbedTLS\\1.0.0\\library\\ssl_tls.c:4353: x509_verify_cert() returned -9984 (-0x2700)
 ok
  . Verifying peer X.509 certificate... failed
  ! The certificate Common Name (CN) does not match with the expected CN
  ! The certificate is not correctly signed by the trusted CA > Write to server: 18 bytes writtenGET / HTTP/1.0 < Read from server: 165 bytes readHTTP/1.0 200 OK
Date: Sun, 28 Feb 2016 04:37:14 GMT
Connection: close
Content-Type: text/html
Last-Modified: Tue, 19 Jan 2016 14:17:43 GMT
Content-Length: 0C:\\Keil_v5\\ARM\\PACK\\ARM\\mbedTLS\\1.0.0\\library\\ssl_tls.c:6421: mbedtls_ssl_read_record() returned -30848 (-0x7880)
C:\\Keil_v5\\ARM\\PACK\\ARM\\mbedTLS\\1.0.0\\library\\ssl_tls.c:2838: mbedtls_ssl_flush_output() returned -80 (-0x0050)
C:\\Keil_v5\\ARM\\PACK\\ARM\\mbedTLS\\1.0.0\\library\\ssl_tls.c:3944: mbedtls_ssl_write_record() returned -80 (-0x0050)
C:\\Keil_v5\\ARM\\PACK\\ARM\\mbedTLS\\1.0.0\\library\\ssl_tls.c:6761: mbedtls_ssl_send_alert_message() returned -80 (-0x0050) Last error was: -30848 - SSL - The peer notified us that the connection is going to be closed

You realize we are having secure communication because the HTTP request was served on HTTPS (port 443). You can try with as many other sites as you like. Unfortunately, some will fail because of memory requirements enforced by the servers. Such as google.com (in my case). Such issues I will leave for you to sort out. In this post let us look at a few elements of code that if you fail to set up correctly, will result in failure. In case I do not get to handle one of interest to you, feel free to reach me in the comments section or via email.

Memory Allocations

The TLS protocol involves negotiation between the server and the client. We cannot decide the algorithms used for secure communication in advance, because we do not know which ones the server support and if they will be supported forever. As such, mbedTLS (and similar libraries) do a lot of runtime memory allocations. The malloc, calloc and free functions are used. This memory required will not show up when you build. In fact, when I build I get Program Size: Code=226812 RO-data=68688 RW-data=352 ZI-data=108764 but the real used RAM is more. The processors I have been using for this tutorial (LPC4337) has three memory regions for RAM as per the datasheet.

0x1000 0000 - 0x1000 8000 (0x0000 8000 = 32kB local SRAM)
0x1008 0000 - 0x1008 A000 (0x0000 A000 = 32kB+8kB local SRAM)
0x2000 0000 - 0x2001 0000 (0x0001 0000 = 4*16kB AHB SRAM)

Add these sections in your project configuration dialog in Keil as shown below and in commit 4d07dfa

config-mbed-tls-ram

These memory allocations done at runtime are drawn from a heap that needs to be configured in the assembler or linker file. By default, Keil adds a heap size of the size 0x400 (1kB). For the TLS client to work, I increased the heap to 0x0001 0000 (64kB). See commit 40cd137. If the memory configuration is not done, you will probably see an error message saying “Not enough memory …” for each symbol that could not fit in the allocated memory.

Note: If you are using an STM32F2/3/4 micro-controller, the RAM is normally in one place and you need not make any changes in the project configuration dialog but only in the startup file (assembly).

STACK CONFIGURATION

The TLS library makes most of its decision at runtime meaning that you cannot determine the specific size of the stack. If we were not running an RTOS, we’d need to change the stack size in the startup file from the default 0x200. In the repo we are using, we had already setup Keil RTX which is an RTOS. I created a separate thread to handle the TLS sample. I could have used the existing communication thread but I wanted to separate them for anyone looking specifically for the PPP communication in the previous posts. The TLS thread, as shown in commit 38d6897, has a 6kB stack size. I decided this out of trial and error and observing the OS Support window in Keil that would show you stack usage and when there is an overflow.

TESTING TLS CLIENT OR LIBRARY

To do the testing of TLS I switched from accessing the internet via PPP as per previous posts to using Ethernet because it is way faster. (I explained why in post #5). At the same time, the initialization of the network stack needs to be done once and as such you will see the use of compiler directives (commit 6619b07). The network stack is initialized by mbedTLS in a file named net.c yet the stack does not allow calling the initialize function more than once.

At this point, your output should be the same as the one dumped at the beginning of this post.

NOTES

  1. Take caution of the pins used for ethernet in case you are using a different board from the one I am using. I used the RMII interface whose pins are configured in RTE_Device.h
  2. The X.509 issue in the log will be solved in the next post here