PolarSSL Tutorial
Introduction
The PolarSSL library has been designed to easily integrate with existing (embedded) applications and to provide the building blocks for secure communication, cryptography and key management. This tutorial will help you understand the steps to undertake when you want to do so.
PolarSSL is designed to be as loosely coupled as possible, allowing you to only integrate the parts you need without having overhead from the rest. This also results in a very low memory footprint and build footprint for the PolarSSL library. By eliminating parts you don't require in your system you can get build sizes from as low as 30 kB to a more typical 110 kB for more fully featured setups.
PolarSSL has been designed in the portable C language with embedded environments as a main target and runs on targets as broad as embedded platforms like ARM and AVR to PCs and iPads, iPhones and even the XBox. Please let us know your experiences on other platforms as well!
Stack explanation
The aim of this tutorial is to show you how to secure your client and server communication with PolarSSL. Let's start with showing the major components that are involved.
From the bottom up:
- Hardware
- The hardware platform provides the physical processor, storage, memory and network interface.
- Operating System
- The Operating System provides the Ethernet driver and standard services. Depending on the OS, this includes scheduling, thread-safety and a full network stack.
- Network Stack
- Depending on the Operating System, the Network Stack is either fully integrated or is a separate module that provides an abstraction layer from the network interface. Most used are the lwIP TCP/IP stack and the uIP TCP/IP stack.
- PolarSSL SSL/TLS Library
- Building on top of the network interface, PolarSSL provides an abstraction layer for secure communication.
- Client Application
- The Client application uses PolarSSL to abstract the secure communication from itself.
The precise steps to integrate PolarSSL in your application are very dependent on the specific components used above. In this basic tutorial we will assume an Operating System with integrated BSD-like TCP/IP stack.
SSL/TLS explanation
The SSL/TLS part of PolarSSL provides the means to setup and communicate over a secure communication channel using SSL/TLS.
Its basic provisions are:
- Initialize an SSL/TLS context.
- Perform an SSL/TLS handshake.
- Send/receive data.
- Notify a peer that a connection is being closed.
Many aspects of such a channel are set through parameters and callback functions:
- The endpoint role: client or server.
- The authentication mode: whether certificate verification should take place.
- The host-to-host communication channel: send and receive functions.
- The random number generator (RNG) function.
- The ciphers to use for encryption/decryption.
- A certificate verification function.
- Session control: session get and set functions.
- X.509 parameters for certificate-handling and key exchange.
PolarSSL can be used to create an SSL/TLS server and client by providing a framework to setup and communicate through an SSL/TLS communication channel. The SSL/TLS part relies directly on the certificate parsing, symmetric and asymmetric encryption and hashing modules of the library.
A more detailed explanation on how PolarSSL internally handles SSL can be found in the documentation for the SSL/TLS module.
Example Client
So let's assume we have a simple network client that tries to open a connection to an HTTP server an read the default page. That application would probably look something like this:
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <netdb.h> #define SERVER_PORT 80 #define SERVER_NAME "localhost" #define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" int main( void ) { int ret, len, server_fd; unsigned char buf[1024]; struct sockaddr_in server_addr; struct hostent *server_host; /* * Start the connection */ printf( "\n . Connecting to tcp/%s/%4d...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); if( ( server_host = gethostbyname( SERVER_NAME ) ) == NULL ) { printf( " failed\n ! gethostbyname failed\n\n"); goto exit; } if( ( server_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP) ) < 0 ) { printf( " failed\n ! socket returned %d\n\n", server_fd ); goto exit; } memcpy( (void *) &server_addr.sin_addr, (void *) server_host->h_addr, server_host->h_length ); server_addr.sin_family = AF_INET; server_addr.sin_port = htons( SERVER_PORT ); if( ( ret = connect( server_fd, (struct sockaddr *) &server_addr, sizeof( server_addr ) ) ) < 0 ) { printf( " failed\n ! connect returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * Write the GET request */ printf( " > Write to server:" ); fflush( stdout ); len = sprintf( (char *) buf, GET_REQUEST ); while( ( ret = write( server_fd, buf, len ) ) <= 0 ) { if( ret != 0 ) { printf( " failed\n ! write returned %d\n\n", ret ); goto exit; } } len = ret; printf( " %d bytes written\n\n%s", len, (char *) buf ); /* * Read the HTTP response */ printf( " < Read from server:" ); fflush( stdout ); do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = read( server_fd, buf, len ); if( ret <= 0 ) { printf( "failed\n ! ssl_read returned %d\n\n", ret ); break; } len = ret; printf( " %d bytes read\n\n%s", len, (char *) buf ); } while( 1 ); exit: close( server_fd ); #ifdef WIN32 printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
A simple client application that does nothing more than:
- opening a connection on port 80 to a server
- write a standard HTTP GET request for the main page
- read the result until nothing more is sent
Adding Secure Communication
Adding SSL/TLS to an application requires a number of modifications. The main modifications are setup, configuration and teardown of the SSL contexts and structures. Smaller changes are those made to the network functions for connecting to a server, reading and writing data.
Setup
As setup PolarSSL requires a good random number generator and its own SSL context and SSL session store. For random number generation PolarSSL contains the CTR_DRBG random number generator, which is used here as well.
The headers required for PolarSSL:
#include "polarssl/net.h"
#include "polarssl/ssl.h"
#include "polarssl/entropy.h"
#include "polarssl/ctr_drbg.h"
Creation and initialization of the PolarSSL structures looks as follows:
entropy_context entropy; ctr_drbg_context ctr_drbg; ssl_context ssl; ssl_session ssn; char *pers = "ssl_example"; entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (unsigned char *) pers, strlen( pers ) ) ) != 0 ) { printf( " failed\n ! ctr_drbg_init returned %d\n", ret ); goto exit; } memset( &ssn, 0, sizeof( ssl_session ) ); memset( &ssl, 0, sizeof( ssl_context ) );
SSL Connection
In a generic TCP/IP client application, the application handles the socket() and connect() calls. PolarSSL generally abstracts this inside its Network Layer (net.c). Thus the following code gets simplified.
if( ( server_host = gethostbyname( SERVER_NAME ) ) == NULL ) goto exit; if( ( server_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP) ) < 0 ) goto exit; memcpy( (void *) &server_addr.sin_addr, (void *) server_host->h_addr, server_host->h_length ); server_addr.sin_family = AF_INET; server_addr.sin_port = htons( SERVER_PORT ); if( ( ret = connect( server_fd, (struct sockaddr *) &server_addr, sizeof( server_addr ) ) ) < 0 ) goto exit;
Starting the actual connection through PolarSSL is as follows:
if( ( ret = net_connect( &server_fd, SERVER_NAME, SERVER_PORT ) ) != 0 ) { printf( " failed\n ! net_connect returned %d\n\n", ret ); goto exit; }
SSL/TLS Configuration
Now that the low level socket connection is up and running, we should configure the SSL/TLS layer.
First initialize our SSL context.
if( ( ret = ssl_init( &ssl ) ) != 0 ) { printf( " failed\n ! ssl_init returned %d\n\n", ret ); goto exit; }
The endpoint determines if the SSL/TLS layer will act as a server (SSL_IS_SERVER) or a client (SSL_IS_CLIENT).
ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
The authentication mode determines how strict the certificates that are presented are checked.
ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
The library needs to know which random engine to use, which debug function to use as callback and the input and output functions it needs to use for sending out network traffic.
ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg ); ssl_set_dbg( &ssl, my_debug, stdout ); ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );
The SSL/TLS layer needs to know which ciphersuites the application should accept for securing its connection. If the client specifies more than one, the server has the final say in which ciphersuite is used. By default only acceptably strong suites are enabled in the ssl_default_ciphersuites list.
ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites );
You need to set a session cache so the library can resume previously exchanged sessions. This can speed up connection setup times if you are on processing-restricted platforms.
ssl_set_session( &ssl, 1, 600, &ssn );
Reading and writing data
After configuring the SSL/TLS layer we should actually write and read through it.
For writing to the network layer:
while( ( ret = write( server_fd, buf, len ) ) <= 0 )
becomes
while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
For reading from the network layer:
ret = read( server_fd, buf, len );
becomes
ret = ssl_read( &ssl, buf, len );
Teardown
At the exit from the application we should close the SSL/TLS connection cleanly and we should also destroy any SSL/TLS related information.
So:
close( server_fd );
becomes:
net_close( server_fd ); ssl_free( &ssl ); memset( &ssl, 0, sizeof( ssl ) );
Conclusion
After changing SERVER_PORT to 443, compiling this application and linking it to the PolarSSL library, we now have an application that can talk basic HTTPS to a web server. The final code is available as ssl_client1.c in the source code of the library or as ssl_client1.c in the Trac Browser.
Attachments
-
PolarSSL Stack.png
(12.2 KB) -
added by paul 13 months ago.
PolarSSL Application Stack



