Morse Micro IoT SDK  2.9.7
sslclient.c File Reference

Detailed Description

SSL Client example to demonstrate connecting to a HTTPS server, TLS handshake and retrieve data.

Note
It is assumed that you have followed the steps in the Getting Started guide and are therefore familiar with how to build, flash, and monitor an application using the MM-IoT-SDK framework.

sslclient.c is an example application that demonstrates how to use TLS to connect to a HTTPS server. In this example we attempt to connect to https://www.google.com/ on the standard HTTPS port 443 and download the content (In this case the Google Search page).

How it works

In the function app_init we first initialize the Wi-Fi subsystem and wait for a connection to be established.

Once the connection is established we initialize the various TLS modules as follows:

mbedtls_net_init(&server_fd);
mbedtls_ssl_init(&ssl);
mbedtls_ssl_config_init(&conf);
mbedtls_x509_crt_init(&cacert);
mbedtls_x509_crt_init(&clicert);
mbedtls_pk_init(&pkey);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);

Once initialized we generate entropy with a call to:

ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen(pers));

We then load and parse the CA Root certificate, Client certificate and client keys. These certificates and keys are stored in the file default_certs.h. Test certificates have been used in this example, but you may generate and use your own certificates and keys.

printf("Loading the CA root certificate ...");
ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_cas_pem,
mbedtls_test_cas_pem_len);
printf("Loading the client cert...");
ret = mbedtls_x509_crt_parse(&clicert, (const unsigned char *) mbedtls_test_cli_crt,
mbedtls_test_cli_crt_len);
printf("Loading the client key...");
ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *) mbedtls_test_cli_key,
mbedtls_test_cli_key_len, NULL, 0, mbedtls_ctr_drbg_random, &ctr_drbg);

We now initialize the SSL context:

mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
mbedtls_ssl_setup(&ssl, &conf);
mbedtls_ssl_set_hostname(&ssl, "test.morsemicro.com")) != 0)
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, NULL, mbedtls_net_recv_timeout);

mbedtls_ssl_set_bio() passes the network read/write functions to mbedtls to use for reading and writing from the network. We use the blocking version of recv().

Now that the SSL setup is done, we open a TCP/IP connection to the server:

mbedtls_net_connect(&server_fd, sslclient_server, sslclient_port, MBEDTLS_NET_PROTO_TCP);

The above call does a DNS lookup and then attempts to connect to the resolved IP's by one till it succeeds. For this to work we need a DNS server, which is why we need DHCP to be enabled so we can setup the DNS server using DHCP.

Once a connection is setup we perform the TLS handshake to start secure communications:

ret = mbedtls_ssl_handshake(&ssl);

It is possible to communicate in the clear before initiating a TLS handshake. This is commonly done in email clients using the STARTTLS protocol.

Once a handshake is completed, we can verify the server certificates using:

ret = mbedtls_ssl_get_verify_result(&ssl);

If the above call fails, it means the authenticity of the server could not be verified. However, TLS communications are still possible.

We can now write and read data securely using:

ret = mbedtls_ssl_write(&ssl, (const unsigned char *) GET_REQUEST, sizeof(GET_REQUEST) - 1);
ret = mbedtls_ssl_read(&ssl, buf, len);
#define GET_REQUEST
HTTPS get request string.
Definition: sslclient.c:174
char buf[1408]
Statically allocated buffer for HTTP GET request, just under 1 packet size.
Definition: sslclient.c:177

Once done, we can tear down the connection and free memory using:

mbedtls_ssl_close_notify(&ssl);
mbedtls_net_free(&server_fd);
mbedtls_ssl_free(&ssl);
mbedtls_ssl_config_free(&conf);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);

Loading custom settings

Using custom keys and certificates

This example application contains embedded certificates and keys for ease of testing. However, you should generate and load your own certificates and keys for real world applications using the steps below.

Download the Root CA certificate

This application needs a root CA certificate that you can download from a certificate authority such as Verisign or Thawte. Ensure you download the root certificate in PEM file format from the certifying authority and also ensure the encryption protocols required by the certificate are enabled in the mbedtls_config.h file for this application. Out of the box we support RSA x509 root certificates in PEM format.

Note
Using an unsupported encryption protocol in the certificate and keys are will cause the application to fail while loading the certificates and keys.

Generate client certificate and keys

Use the steps below to generate a set of client keys and a self signed client certificate.

  • Generate the client keys and certificate using the commands below:
    openssl genrsa -out sslclient.key 2048
    openssl req -new -x509 -days 365 -key sslclient.key -out sslclient.crt
    Answer the prompts for information (email, country, organization, etc) as requested.

Write the keys and certificates to the device

  • Enter the path for the root certificate you downloaded earlier under the key sslclient.rootca in the config.hjson file in this example folder.
  • Enter the path for the sslclient.key file above under the key sslclient.clientkeys in the config.hjson file in this example folder.
  • Enter the path for the sslclient.crt file above under the key sslclient.clientcert in the config.hjson file in this example folder.
  • Follow the instructions in Programming the config store from a host PC to load the certificates and keys in the config.hjson file to the device.

See Application helper routines for Wireless LAN interface for details of WLAN and IP stack configuration. Additional configuration options for this application can be found in the config.hjson file.

Definition in file sslclient.c.

#include <string.h>
#include "mmosal.h"
#include "mmwlan.h"
#include "mmconfig.h"
#include "mmipal.h"
#include "mbedtls/build_info.h"
#include "mbedtls/platform.h"
#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
#include "mm_app_common.h"
#include "default_certs.h"
Include dependency graph for sslclient.c:

Go to the source code of this file.

Macros

#define DEFAULT_PORT   "443"
 HTTPS port number to connect to. More...
 
#define DEFAULT_SERVER   "www.google.com"
 HTTPS server to connect to. More...
 
#define GET_REQUEST   "GET / HTTP/1.0\r\n\r\n"
 HTTPS get request string. More...
 

Functions

void my_debug (void *ctx, int level, const char *file, int line, const char *str)
 Optional mbedtls debug callback handler. More...
 
void app_init (void)
 Main entry point to the application. More...
 

Variables

char buf [1408]
 Statically allocated buffer for HTTP GET request, just under 1 packet size. More...
 

Macro Definition Documentation

◆ DEFAULT_PORT

#define DEFAULT_PORT   "443"

HTTPS port number to connect to.

Definition at line 170 of file sslclient.c.

◆ DEFAULT_SERVER

#define DEFAULT_SERVER   "www.google.com"

HTTPS server to connect to.

Definition at line 172 of file sslclient.c.

◆ GET_REQUEST

#define GET_REQUEST   "GET / HTTP/1.0\r\n\r\n"

HTTPS get request string.

Definition at line 174 of file sslclient.c.

Function Documentation

◆ app_init()

void app_init ( void  )

Main entry point to the application.

This will be invoked in a thread once operating system and hardware initialization has completed. It may return, but it does not have to.

Definition at line 201 of file sslclient.c.

◆ my_debug()

void my_debug ( void *  ctx,
int  level,
const char *  file,
int  line,
const char *  str 
)

Optional mbedtls debug callback handler.

Parameters
ctx
level
file
line
str

Definition at line 188 of file sslclient.c.

Variable Documentation

◆ buf

char buf[1408]

Statically allocated buffer for HTTP GET request, just under 1 packet size.

Definition at line 177 of file sslclient.c.