Aaron Ardiri
[Valid RSS] RSS/XML feed
198 entries available (show all)


Internet of Things (IoT)

RIoT Secure AB


While children of the world stay awake waiting for Santa, I work on µTLS (micro TLS).

In my previous entry I made a promise that I would update my weather station to utilize µTLS (micro TLS) so that it could securely post weather information from its location to my own server. I will soon be returning home from my time in Europe, so it is the perfect time to relocate my sensor array and give it a nice upgrade it at the same time. I have made some nice structural improvements to the code - to make it easier to integrate into your projects.

I have posted the µTLS (micro TLS) driver code below - but let's take a closer look at it.

    const uint8_t SERVER[]     PROGMEM = { xxx, xxx, xxx, xxx }; 
    #define SERVER_NAME        "xxx.xxxxxxxx.xxx"
    #define SERVER_URI         "/xxx/index.php"
    #define CLIENT_GUID        "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    #define CLIENT_INTERVAL    60 // 1 minute

It is important to define information on the server where the client needs to report to - a few basic requirements such as the IP address, hostname and the URI where the requests are to be made. We also need to define a GUID for the client and how often it needs to check into the server.

    const uint8_t aes_shared_key[] PROGMEM = 
      0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 
      0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX  // must exist on server
    #include "microTLS-module-aes128.h"
    #define SESS_SECURITY "aes-128"
    #define PING_SECURITY "aes-128"

To keep the code simple; all we need to provide are two #define constants that define the level of security we want the client to use, in addition we simply need to #include that module for use. We have two levels of security; one for key exchange and one for ongoing communication.

For the weather station; I decided to use aes-128 as the exclusive security protocol - to be used for both session creation and session updates. A pre-shared key is defined that will establish trust with the server and exchange a new AES key for ongoing communication. The TLS specification does state that using pre-shared keys is a permitted method of key exchange, so all good there.

    typedef struct xGlobals
      uint8_t  aeskey[AES_KEYLEN];
      // https://github.com/ControlEverythingCommunity/SI7020-A20
      float    humidity;
      float    temperature;
      // https://github.com/ControlEverythingCommunity/CPS120
        double visible;
        double ir;
        double uv;
      } light;
      // https://github.com/ControlEverythingCommunity/SI1132 
      float    pressure;
    } xGlobals;
    xGlobals gx;

We define some additional attributes in our xGlobals structure to store the values that we read from our sensor array - these will be used to populate a message in JSON that our server will receive and store every time a session update is performed.

    void microTLS_setup()

Our µTLS (micro TLS) driver is actually an extension to an existing sketch - so we must allow for additional initialization modes to occur within the program. We have a number of sensors, using the Wire interface that need to be configured - this is where we do these operations. A Serial interface is already created for debugging, so no additional system level calls are required.

The brains of the operation happen within the following functions:

    void microTLS_sess_prepare()
    void microTLS_sess_process()
    void microTLS_ping_prepare()
    void microTLS_ping_process()

Using the defined security protocols - we must make sure that all the necessary operations are performed so that the server received what it expects. This involves deciding what message needs to be sent, generating an integrity hash and encrypting the message as intended. The same operations in reverse are needed when data is received from the server.

The good news is; we'll have templates for all circumstances, so you wont need to worry about it.

    // JSON message structure
    // '{"temperature":-99.99,"humidity":99.99,"pressure":99.99,"light":999}'
    const char JSON_TAG_TMP[] PROGMEM = "\"temperature\":";
    const char JSON_TAG_HUM[] PROGMEM = "\"humidity\":";
    const char JSON_TAG_PRS[] PROGMEM = "\"pressure\":";
    const char JSON_TAG_LGT[] PROGMEM = "\"light\":";
    // we need to read the sensors

Our server will be expecting a JSON buffer for the data from the sensor array; an example of what it expects is shown. We need to define some constants to assist in building the buffer - but more importantly, we need to read the sensors to populate the xGlobals structure.

Once we have the sensor data - we need to build a JSON buffer containing them. While some people would go with the option of using sprintf to do this; I personally opted to build the string manually to avoid wasting valuable RAM and program space. Nothing beats using pointers!

    // we'll put our data at the end of scratch
    len = 100; // should be plenty of space
    p = &g.scratch.reserved[CLIENT_SCRATCH_LEN - len - 1];
    // we need to simulate a sprintf() and build the JSON string
    _p = (char *)p;
    *_p++ = '{';
      strcpy_P(_p, JSON_TAG_TMP); _p += strlen(_p);
        // whole number
        val = (int)gx.temperature;
        u32toa(val, _p); _p += strlen(_p);
        // remainder
        *_p++ = '.';
        val = (int)((gx.temperature * 100)) % 100;
        if (val < 10) *_p++ = '0';
        u32toa(val, _p); _p += strlen(_p);
      *_p++ = ',';
      strcpy_P(_p, JSON_TAG_HUM); _p += strlen(_p);
        // whole number
        val = (int)gx.humidity;
        u32toa(val, _p); _p += strlen(_p);
        // remainder
        *_p++ = '.';
        val = (int)((gx.humidity * 100)) % 100;
        if (val < 10) *_p++ = '0';
        u32toa(val, _p); _p += strlen(_p);
      *_p++ = ',';
      strcpy_P(_p, JSON_TAG_PRS); _p += strlen(_p);
        // whole number
        val = (int)gx.pressure;
        u32toa(val, _p); _p += strlen(_p);
        // remainder
        *_p++ = '.';
        val = (int)((gx.pressure * 100)) % 100;
        if (val < 10) *_p++ = '0';
        u32toa(val, _p); _p += strlen(_p);
      *_p++ = ',';
      strcpy_P(_p, JSON_TAG_LGT); _p += strlen(_p);
        // whole number
        val = (int)gx.light.ir;
        u32toa(val, _p); _p += strlen(_p);
        // remainder
        *_p++ = '.';
        val = (int)((gx.light.ir * 100)) % 100;
        if (val < 10) *_p++ = '0';
        u32toa(val, _p); _p += strlen(_p);
    *_p++ = '}';
    *_p = 0; // we must not forget the NULL terminator
    len = strlen((char *)p);

µTLS (micro TLS) provides a few lightweight helper functions for dealing with raw values - but after all of the above; the buffer pointed to by the variable p should have the unencoded message we want to send to the server. We then generate an integrity hash and encode it as required.

When compiled for the Arduino UNO:

    Sketch uses 26,954 bytes (83%) of program storage space. 
    Global variables use 1,202 bytes (58%) of dynamic memory, 
    leaving 846 bytes for local variables. Maximum is 2,048 bytes.

With some minor modifications to the main µTLS (micro TLS) sketch to target the particle.io platform - we can also see the benefits of how lightweight the library is as we also have plenty of program space and RAM available for additional purposes:

    Output of arm-none-eabi-size:
    text   data  bss   dec    hex   |  Flash used  24604 / 110592  22.2 %
    24492  112   2408  27012  6984  |  RAM used    2520  / 20480   12.3 %

Of course there is still room for improvement to make integrating µTLS (micro TLS) into existing micro-controller applications easier - but with this example it should be obvious that it does not require a lot of effort. Over time additional modules will be developed - we have only just explored at the tip of the iceberg when it comes to its potential to help solve the security crisis in IoT.

The weather stations µTLS (micro TLS) driver code (with sensorship) is available:


advertisement (self plug):
need assistance in an IoT project? contact us for a free consultation.


µTLS - defining lightweight security for IoT (part 10)
µTLS - defining lightweight security for IoT (part 8)

All content provided on this blog is for informational purposes only.
All comments are generated by users and moderated for inappropriateness periodically.
The owner will not be liable for any losses, injuries, or damages from the display or use of this information.