mbedTLS on mbed?

10 Sep 2015

ARM recently announced mbed TLS 2.1.0 which is available at https://tls.mbed.org/

Since I'm new to mbed I cannot figure out on how to use this library to send data to a HTTPS server (using PUT). Can anyone please explain to me how to use the library from within the mbed online compiler? I'm using a u-blox C027 platform.

Thanks for any help, Christoph

15 Sep 2015

I partly figured out how it works: following the information posted at https://tls.mbed.org/discussions/platform-specific/import-onto-the-mbed-lpc1768-platform I could get the library compile in mbed. I then followed the mbedtls tutorial at https://tls.mbed.org/kb/how-to/mbedtls-tutorial but get stuck when calling the function 'mbedtls_net_init()' which makes sense since I disabled the "#define MBEDTLS_NET_C" in the library's config.h file.

However, I'm stuck at this point and do not know how to proceed - any help is appreciated.

15 Sep 2015

You should use mbed's Socket class as a replacement for the mbed TLS net module (which only works on Unix and Windows).

The mbed TLS tutorial shows how to replace an unencrypted connection using the BSD sockets API with an encrypted connection using mbed TLS (on top of BSD sockets). Here you could use something like this TCP example client as a starting point instead of the example in the mbed TLS tutorial.

16 Sep 2015

I now followed the tutorial from the mbedTLS website and managed to compile the code (see code below). However, the function mbedtls_entropy_init() fails. Any idea on how to get entropy?

main,.cpp

#include "mbed.h"
#include "MDM.h"

#define SIMPIN      "0000"
#define APN         "gprs.swisscom.ch"
#define USERNAME    NULL
#define PASSWORD    NULL 
//------------------------------------------------------------------------------------

const char* SERVER_ADDRESS = "httpbin.org";
const int SERVER_PORT = 443;

#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"

#define GET_REQUEST "POST /post HTTP/1.0\r\nContent-Type: text/plain\r\nContent-Length: 11\r\n\r\nHello World\r\n"

struct MDMSocketConnection {
    MDMSerial* mdm;
    int socket;
} ;

int sendWrapper(void* mdmSockConPtr, const unsigned char* buf, size_t length) {
    MDMSocketConnection* mdmSockCon = (MDMSocketConnection *) mdmSockConPtr;
    return mdmSockCon->mdm->socketSend(mdmSockCon->socket, (const char *)buf, (int) length);
}

int recvWrapper(void* mdmSockConPtr, unsigned char* buf, size_t length) {
    MDMSocketConnection* mdmSockCon = (MDMSocketConnection *) mdmSockConPtr;
    return mdmSockCon->mdm->socketRecv(mdmSockCon->socket, (char *)buf, (int) length);
}

static void my_debug( void *ctx, int level,
                      const char *filename, int line, const char *msg )
{
    printf("%s:%04d: %s", filename, line, msg );
}

int main() {
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_x509_crt caCert;
    int ret;
    
    // Initialize the modem
    MDMSocketConnection mdmSockCon;
    MDMSerial mdm;
    mdmSockCon.mdm = &mdm;
    MDMParser::DevStatus devStatus = {};
    MDMParser::NetStatus netStatus = {};
    bool mdmOk = mdm.init(SIMPIN, &devStatus);
    mdm.dumpDevStatus(&devStatus);
    mdmOk = mdm.registerNet(&netStatus);
    mdm.dumpNetStatus(&netStatus);
    MDMParser::IP ip = mdm.join(APN,USERNAME,PASSWORD);
    int socket = mdm.socketSocket(MDMParser::IPPROTO_TCP);
    mdmSockCon.socket = socket;    
    mdm.dumpIp(ip);
    
    // Connect to Server
    while (mdm.socketConnect(socket, SERVER_ADDRESS, SERVER_PORT) == false) {
        printf("Unable to connect to %s:%d\n", SERVER_ADDRESS, SERVER_PORT);
        wait(1);
    }
    printf("Connected to Server at %s:%d\n",SERVER_ADDRESS, SERVER_PORT);
    
    // Configure SSL/TLS
    mbedtls_ssl_init( &ssl );
    mbedtls_ssl_config_init( &conf );
    mbedtls_x509_crt_init( &caCert );
    mbedtls_ctr_drbg_init( &ctr_drbg );

    mbedtls_entropy_init( &entropy );
    if ( ( ret = mbedtls_entropy_self_test(1)) != 0) {
            printf("Error: mbedtls_entropy_self_test failed!\n");
            return 0;
    }
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                               NULL,
                               0 ) ) != 0 )
    {
        printf( "Error: mbedtls_ctr_drbg_seed returned %d\n", ret );
        return 0;
    }

    if( ( ret = mbedtls_ssl_config_defaults( &conf,
                MBEDTLS_SSL_IS_CLIENT,
                MBEDTLS_SSL_TRANSPORT_STREAM,
                MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
        printf( "Error: mbedtls_ssl_config_defaults returned %d\n", ret );
        return 0;
    }
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); // TODO: add certificate checking
    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
    mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
    if( ( ret = mbedtls_ssl_set_hostname( &ssl, "mbed TLS Server 1" ) ) != 0 )
    {
        printf( "Error: mbedtls_ssl_set_hostname returned %d\n", ret );
        return 0;
    }
    mbedtls_ssl_set_bio( &ssl, &mdmSockCon, sendWrapper, recvWrapper, NULL );
    if ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
        printf( "Error: mbedtls_ssl_handshake returned %d\n", ret );
        return 0;
    }
    
    
    // Send message to server
    const unsigned char hello[] = "POST /post HTTP/1.0\r\nContent-Type: text/plain\r\nContent-Length: 11\r\n\r\nHello World\r\n";
    printf("Sending  message to Server : '%s' (%d bytes)...",hello, sizeof(hello)-1);
    ret = mbedtls_ssl_write(&ssl, hello, sizeof(hello)-1);
    printf("done. Sent %d bytes.\r\n", ret);
    
    // Receive message from server
    int bufLen = 1024;
    unsigned char buf[bufLen];
    printf("Receiving message from server (up to %d bytes)...\r\n", bufLen);
    ret = mbedtls_ssl_read(&ssl, buf, bufLen);
    buf[ret] = '\0';
    printf("Received message from server: '%s' (%d bytes read)\r\n", buf, ret);
    
    // Clean up
    mbedtls_ssl_close_notify(&ssl);
    mdm.socketClose(socket);
    mbedtls_ssl_free( &ssl );
    mbedtls_ssl_config_free( &conf );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );
    mdm.socketFree(socket);
    mdm.disconnect();
}
16 Sep 2015

How to get good quality entropy is a non-trivial and very platform-dependant question. Obviously the best case is when your platform has a hardware RNG. If that isn't the case, you can try using floating inputs, concurrent clocks, and/or timing form external events. In any case, some care is needed. I seem to remember people posting detailed explanations (maybe even code) about some strategies, but I can't find the links right now, I'll post them when I find them.

As a matter of fact, entropy sources are the main technical reason why we don't offer an official mbed TLS package on mbed v2. We do have plans for making things work out-of-the-box in a secure way (ie, have good default entropy sources on all platforms) for mbed OS, but it's a non-trivial effort.

17 Sep 2015

I found this ocde which seems promising: https://developer.mbed.org/users/Remco/code/EntropySource/ I will give it a try to make this work with mbedtls

01 Apr 2016

Christoph W, can you please provide your config.h file for mbedtls? How did you go about to provide your own (i.e. mbed's) timer and networking functionality? I'm reading through the configuration file and I am a little unsure as to which defines to include/exclude.

Thank you in advance :)

06 Apr 2016

There are builds available for mbed OS at https://github.com/ARMmbed/mbedtls, so there the timers should have been replaced as well. I assume you could check the yotta specific parts and see how that was done.

08 Jan 2017

Hi, Has anyone gets tls working? especially for tls server. thanks.