1. Introduction

This tutorial will show how to get started with the PolarSSL cryptography library in a Windows environment, using Microsoft Visual Studio 2010 Express Edition. We will be using the sample client application (from this tutorial). This simple application sends a http request to read an html page from a server. We will be using PolarSSL to enable encrypting our communication with the server with SSL.

In this step-by-step tutorial we will show you how to setup Visual Studio for PolarSSL and the sample application. Only assumption is that you have already installed Visual Studio Express Edition for C++ (or the Professional Edition).

To keep things simple, the sample application is a command line program, written in C. PolarSSL can be integrated just as easily in any C/C++ application, with or without a (graphical) user interface.

2. Download PolarSSL

The first thing we need to do is get the PolarSSL source code. Download 'polarssl-<version>-gpl.tgz' from: here. To unpack this file you can use a tool like 7-zip.

The default installation of Visual Studio should have created folder: My Documents\Visual Studio 2010\Projects. Extract the contents of the .tgz file to this location. Make sure to extract the second occurrence of the polarssl- folder. Otherwise the paths given later on in this tutorial won't match.

3. Open the visual studio solution

You should now have a folder: My Documents\Visual Studio 2010\Projects\polarssl-<version>\visualc\VS2010.

In this folder you will find the file 'PolarSSL.sln'. This is a Visual Studio 'solution' file, which holds all the components PolarSSL consist of and the rules to build the PolarSSL library.

Double click the .sln file to open Visual Studio.

PolarSSL-Tutorial-VS2010-1.png

4. Build

When Visual Studio opens it shows all the components of the PolarSSL source code. We are only interested in the 'PolarSSL' project (shown in bold to indicate that it is the default project) which builds the PolarSSL library file. Later on we will link to this library file from our sample application.

Now we can build the library. Since we won't be debugging PolarSSL we will build the 'Release' version. Select the 'release' configuration in the icon bar. Then press F7 to start the building process.

PolarSSL-Tutorial-VS2010-2.png

PolarSSL-Tutorial-VS2010-3.png

Not all components may have been built successfully. This does not matter as long as the PolarSSL project was built !
Check this by looking in folder: My Documents\Visual Studio 2010\Projects\polarssl-\visualc\VS2010\Release. The file 'PolarSSL.lib' should be present.

PolarSSL-Tutorial-VS2010-4.png

5. Set up a new project

Now we are ready to setup the sample project. Close the current solution by clicking on 'Close solution' in the file menu.

PolarSSL-Tutorial-VS2010-5.png

Create a new project by selecting the menu command: File / New / Project (or use the 'New' icon).

PolarSSL-Tutorial-VS2010-6.png

Visual Studio will then ask what kind of project you would like to create. Choose 'Empty project'. Type the name of the project, for instance 'polar_client_demo'. Check that the 'My Documents\Visual Studio 2010\Projects' folder has been selected as the location (the same base path as used for PolarSSL). Leave the 'create directory for solution' flag enabled. After clicking the OK button you will end up with a new, empty, project.

PolarSSL-Tutorial-VS2010-7.png

6. Copy sample application

To create an application we must add a source file. In the solution explorer, right click on 'Source files' and select Add / New item.

PolarSSL-Tutorial-VS2010-8.png

Visual Studio will ask what kind of item you would like to create. Select 'C++ file'. Enter a name for the file, for example 'client.c'. Click on 'Add'.

PolarSSL-Tutorial-VS2010-9.png

Copy and paste this piece of code to the new file and save it.

#include <sys/types.h>

#ifdef _WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

#include <string.h>
#include <stdio.h>

#define SERVER_PORT 80
#define SERVER_NAME "www.google.com"
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"

int main( void )
{
    int ret = 0, len, server_fd = 0;
    unsigned char buf[1024];
    struct sockaddr_in server_addr;
    struct hostent *server_host;

#ifdef _WIN32
    WSADATA wsaData;
#endif

#ifdef _WIN32
    /*
     * Init WSA
     */
    if( WSAStartup(MAKEWORD(2, 0), &wsaData ) != 0 )
    {
    printf( " WSAStartup() failed\n" );
    goto exit;
    }
#endif

    /*
     * 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 );

#ifdef _WIN32
    while( ( ret = send( server_fd, (char *) buf, len, 0 ) ) <= 0 )
#else
    while( ( ret = write( server_fd, buf, len ) ) <= 0 )
#endif
    {
    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 ) );
#ifdef _WIN32
    ret = recv( server_fd, (char *) buf, len, 0 );
#else
    ret = read( server_fd, buf, len );
#endif

    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:

#ifdef _WIN32
    if( server_fd )
    closesocket( server_fd );
    WSACleanup();
#else
    close( server_fd );
#endif

#ifdef _WIN32
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}

7. Compile and test

Before building the new project we need to add one project setting. In the solution explorer, right click on the project name, in this case 'polar_client_demo' and select 'Properties'.

PolarSSL-Tutorial-VS2010-10.png

In the properties dialog select Linker / Input. Select 'Additional dependencies', click on the down arrow and 'edit'.

PolarSSL-Tutorial-VS2010-11.png

Type 'wsock32.lib' in the dialog and click on OK twice. This library needs to be added to the project since line 4 of the source code includes the 'winsock' header file. Visual Studio needs to know where to find the executable code for this file.

PolarSSL-Tutorial-VS2010-12.png

You can now build the sample application. Press the F7 key. If all goes well Visual Studio will show 'Build: 1 succeeded' in the output screen.

PolarSSL-Tutorial-VS2010-13.png

Start the application by pressing the F5 key. Note that line 16 of the source code states that the application should load the home page of a well-known search engine.

The application shows a command screen, stating that a connection has been made to the server and shows the server's response. Press enter to close the application.

PolarSSL-Tutorial-VS2010-14.png

Now let's assume that we want to connect to the server using https. Change line 15 to:

#define SERVER_PORT 443  

Build (F7) and run (F5) the application again. Not surprisingly the application will show an error. We first need to set up an SSL connection. And that is where PolarSSL comes in !

PolarSSL-Tutorial-VS2010-15.png

8. SSL 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.

9. Modify application to use SSL

How to add PolarSSL to the sample application is described in this tutorial.
For now replace the code in the client.c file by copy and pasting this code over the existing code.

#include <string.h>
#include <stdio.h>

/*
 * Include PolarSSL
 */
#include "polarssl/net.h"
#include "polarssl/ssl.h"
#include "polarssl/entropy.h"
#include "polarssl/ctr_drbg.h"

#define SERVER_PORT 443
#define SERVER_NAME "www.google.com"
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"

#define DEBUG_LEVEL 1

void my_debug( void *ctx, int level, const char *str )
{
    if( level < DEBUG_LEVEL )
    {
    fprintf( (FILE *) ctx, "%s", str );
    fflush(  (FILE *) ctx  );
    }
}

int main( void )
{
    int ret = 0, len, server_fd = 0;
    unsigned char buf[1024];

    /*
     * Init PolarSSL
     */
    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 ) );

    /*
     * Start the connection
     */
    printf( "\n  . Connecting to tcp/%s/%4d...", SERVER_NAME,
                                             SERVER_PORT );
    fflush( stdout );

    /*
     * Connect with PolarSSL
     */
    if( ( ret = net_connect( &server_fd, SERVER_NAME,
                                     SERVER_PORT ) ) != 0 )
    {
    printf( " failed\n  ! net_connect returned %d\n\n", ret );
    goto exit;
    }

    /*
     * Initialize the SSL context
     */
    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
    printf( " failed\n  ! ssl_init returned %d\n\n", ret );
    goto exit;
    }

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

    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 );

    ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites );

    ssl_set_session( &ssl, 1, 600, &ssn );

    printf( " ok\n" );

    /*
     * Write the GET request
     */
    printf( "  > Write to server:" );
    fflush( stdout );

    len = sprintf( (char *) buf, GET_REQUEST );

    while( ( ret = ssl_write( &ssl, 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 = ssl_read( &ssl, 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:

    net_close( server_fd );
    ssl_free( &ssl );
    memset( &ssl, 0, sizeof( ssl ) );

#ifdef _WIN32
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}

Before compiling we need to tell Visual Studio where to find the PolarSSL files. In the solution explorer, right click on the project name 'polar_client_demo' and select 'Properties'.

Under Linker / Input / Additional Dependencies add: 'PolarSSL.lib' (without quotes). You can remove the wsock32.lib entry.

PolarSSL-Tutorial-VS2010-16.png

Under Linker / General / Additional Library Directories add : '....\polarssl-1.1.3\visualc\VS2010\Release'. Again without the quotes. You may need to replace the version number with the one you installed. If you unpacked and compiled PolarSSL in a different location you can enter the full path to the location of the PolarSSL.lib file.

PolarSSL-Tutorial-VS2010-17.png

Under C/C++ / General / Additional Include Directories add: '....\polarssl-1.1.3\include'. Use the same renaming as for the library directory mentioned above.
Click on OK.

PolarSSL-Tutorial-VS2010-18.png

10. Compile and test

You can now build the modified sample application. Press the F7 key. If all goes well Visual Studio will show 'Build: 1 succeeded' in the output screen.

PolarSSL-Tutorial-VS2010-19.png

Start the application by pressing the F5 key. The application shows a command screen, stating that a connection has been made to the server and shows the server's response. But this time we are communicating over a secure SSL connection !

PolarSSL-Tutorial-VS2010-20.png

11. Conclusion

This tutorial showed how to set up a Visual Studio project that uses the PolarSSL cryptography library.

This sample application is very simple. In a larger project you might want to wrap the code to call PolarSSL in functions like: InitializeSSL, OpenSSLConnection, ExecuteSSLRequest, ReadSSLResponse and CloseSSL. Or use a C++ class where the initialize and close functions can be placed in the constructor and destructor.

You also might want to copy the PolarSSL.lib files to the Debug/Release folders of your project to ease the rollout of your application.

Did this help?