Wednesday, February 16, 2011

Keil and non-commercial license

So Keil is trying to develop a non-commercial license.  I don't have any details yet. Just thought I would give a heads up.  If you want more info contact their sales office.  It might also show that there is interest in this.

sales.us (at) keil.com

Tuesday, February 1, 2011

STM32 Discovery: Porting Polar SSL

Well my next step was porting polarSSL to the arm STM32 chip.  I needed this for one of my current project so I am writing how I got it to work.  I will be starting from the buffered usart project.
Setting up PolarSLL
So the first thing you need for this task is polar SSL.  you can get it here.  Copy over the 2 folders: Library and include. Next we will need to add the include folder to our include path.  right click on Target and go to the options. Head over to the C/C++ tab.  hit the "..." button next to the Include path text box.  Then hit the square thing next to the x in the next dialog.  Finlay click the "..." button and go find the include folder you just pasted.


From here I would add a new group and call it pollarssl.  Then I would add all the files that were in the library folder we just copied over.  You will need to add all the C files though to your project.

Building the main

Now we want to copy the main from ssl_client1.c.  you can find it in the source of pollarSSL in the programs\ssl\ folder or here.  You also want to keep the code that is all ready in your main.  like stm32_Init (); and the initialization of the buffer.
Before we make any changes, we will need to add #include "polarssl/ssl.h". Also, I added this dummy function on top of my main.
int notRandom(void* param)
{
    return 0xE3A576DC;
}
I will go threw, later, how to use the ADC and a random signal generator to make this really random

Now the changes we need to do.  First we will not be using havege so we can remove the following lines:
havege_state hs;
    /*
     * 0. Initialize the RNG and the session data
     */
    havege_init( &hs );
    memset( &ssn, 0, sizeof( ssl_session ) );
I also remove the net connect code
printf( "\n  . Connecting to tcp/%s/%4d...", SERVER_NAME,
                                                 SERVER_PORT );
    fflush( stdout );

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

    printf( " ok\n" );

we will also need to change these lines:
ssl_set_rng( &ssl, havege_rand, &hs );
ssl_set_dbg( &ssl, my_debug, stdout );
ssl_set_bio( &ssl, net_recv, &server_fd,net_send, &server_fd );
We will replace net_recv with my_recv and net_send with my_send and havege_rand with notRandom.  the second parameter will be null.  This is what it looks like
ssl_set_rng( &ssl, notRandom, 0 );
    ssl_set_bio( &ssl, my_recv, 0,
                       my_send, 0 );
Finaly, you need to remove this line near the end
net_close( server_fd );


The rest can stay.  with these settings I could connect to all the site I need to you might need to un-comment different ciphersuites depending on the site.

 Making the code Fit

The havege used for random is quite large.  Later we will have to make a hardware random but for now we used our little function called notRandom using the right signature. 
Now we need to head over to config.h.  we will start commenting out everything we don't need
//#define POLARSSL_DEBUG_MSG
//#define POLARSSL_SELF_TEST
//#define POLARSSL_VERSION_C
//#define POLARSSL_GENPRIME
//#define POLARSSL_AES_C  // You might need this one depending on the site you are accessing
//#define POLARSSL_CAMELLIA_C // You might need this one depending on the site you are accessing
//#define POLARSSL_CERTS_C
//#define POLARSSL_DEBUG_C
//#define POLARSSL_DES_C // You might need this one depending on the site you are accessing
//#define POLARSSL_DHM_C
//#define POLARSSL_HAVEGE_C
//#define POLARSSL_NET_C
//#define POLARSSL_PADLOCK_C
//#define POLARSSL_SHA2_C
//#define POLARSSL_SHA4_C
//#define POLARSSL_SSL_SRV_C
//#define POLARSSL_TIMING_C
//#define POLARSSL_X509_WRITE_C
//#define POLARSSL_XTEA_C
So I will show you how to add some compiler optimization on your code  with keil that will remove allot of the unused code.  Unfortunately, it would require allot of #ifdef code to do this manually.  First off, open you project settings. on the target Tab check use microLIB and Use Link-Time Code Generation.  The last one will make it a little longer to compile but will save you around 4k in program space.

Next click on the C/C++ tab and set optimization to 3.  Also check the on ELF Section per Function.  this will remove all unused functions from your code.  Setting optimization to level 3 will make it harder to debug but will get your code under 32k


Now with MicroLib, you will not be able to compile.  The reason for that is the time function is not coded so we need to code one our self.  Simply create and a file and add a empty function like this
#include <time.h>
time_t time ( time_t * timer )
{
    return 0;
}
Pollar SSL uses the Time function to determine if the session has expired and if we can  reuse past session keys.  Making the time function all ways return 0, will force to renegotiate the keys and cause it to take more time.  we will have to deal with that for now.  I will later change it to return the right time but for now it's not a priority.


That is it. using the application created in the previous blog you can send https request or posts.
There are other ways to connecting to the internet thought.  you can use different modules like the network shield they have for the arduino http://www.sparkfun.com/products/9026 or one like this http://www.sparkfun.com/products/9473 that supports sockets or a wifi one like this http://www.sparkfun.com/products/10050.

I want to get this code working with the last one.  I will post my changes once I get the part.

Forwarding the serial port to the net

This section will discus reading the serial port and forwarding the content to a socket and vise versa in C++.  I will be using specific api from win32 so it will not build in linux.  If I ever see interest on getting it working on linux, I will write one for linux.  I will only cover briefly the socket information since there are so many in depth tutorials out there.

For starters we will need to create a new visual studio console application project.  This is pretty basic and could be different from version so I will assume you can do this on your own. I will be using visual studio 2010
Now that we have our applications, we need to include the following.
#include <stdio.h>
#include <winsock.h>
#include <Windows.h>
I read that some people have trouble with the linker depending on the order of the include.  This order worked for me.  I also put the includes in my precompiled header (stdafx.h).

we also need to include the lib file so the linker knows where to get the functions from.
simply add #pragma comment(lib, "Ws2_32.lib") after all your includes

Setting up the the socket
the first thing we need to add before using any winsoc, is WSAStartup.  It takes a version number as a parameter (we are using version 2) and a struct that will be use by its internals.
read more

WSAData wsaData;
if ( WSAStartup(MAKEWORD(2,0), &wsaData))
{
    printf("could not load WSAStratup");
    return -1;
}
Now we need to prepare our connection information.  We will use the sockaddr_in to store all the information needed for the socket.  There are a couple different types of sockaddr but for IPv4 sockaddr_in is the one we use. 
read more
The inet_addr function converts an IP string to a long used by winsock.
read more
and the htons converts the windows byte order to the network byte order as some system have different byte orders.
read more

SOCKET hSocket;
sockaddr_in addrInfo;
memset(&addrInfo,0,sizeof(sockaddr_in));

addrInfo.sin_family = AF_INET;
addrInfo.sin_port = htons(80);  /http port
addrInfo.sin_addr.S_un.S_addr = inet_addr("74.125.226.81");  //Google's IP adress


Now that we have all our information we need to create the socket and connect it.
we create the socket with the socket function. This function takes 3 parameters.
First we specify that the address is a IPv4 adress,  we what stream socket (goes in hand with tcp) as opposed to a data gram and we want to use TCP protocol.
read more
The connect takes the newly created socket and the addrInfo we created just 1 step before.

hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (hSocket==INVALID_SOCKET)
{
        EXIT("can't create Socket\n");
}
 if (connect(hSocket, (sockaddr*)(&addrInfo), sizeof(addrInfo))!=0)
 {
        EXIT("can't connect\n");
 }

Finaly I added this line so that when I read from the socket it does not block untill data is received
ioctlsocket(hSocket,FIONBIO,&timeout);

Setting up the Serial port
We will open the serialport using the function CreateFile.  The file that we will use is COM# where the # is the number of the comport.  For now I will use COM1.  We will also be using a struct called DCB.  This struct contains information about the serial port configurations that we will use.  Note that these settings must match with those used with you STM32 Discovery
read more
We will also use the function SetCommState.  This function simply applies the new settings.
read more

HANDLE hSerial;
hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
//Comm settings
DCB serialInfo = {0};
serialInfo.DCBlength=sizeof(serialInfo);
serialInfo.BaudRate=CBR_14400;
serialInfo.ByteSize=8;
serialInfo.StopBits=ONESTOPBIT;
serialInfo.Parity=NOPARITY;
SetCommState(hSerial, &serialInfo);

The Loop
Now we simply need to read from the serial port and send it to the net and then read from the net and send it to the serial port.  We will use ReadFile and WriteFile to read an write to the serial port. We will pass the following parameter. the handle to the Serial port, the pointer to the buffer, the size of the buffer or the content and the address to a variable that will contain the number of bytes sent or read.  we set the last parameter to null since it only used if you need to share access to the file and we don't.

We will be using recv and send to read and write to our socket.  These functions take similar parameters except instead of passing the adress to a variable to know how many byte were read or sent, it is return.

here is my loop
char* readbuffer = new char[READ_BUFFER_SIZE];
char* writebuffer = new char[BUFFER_2_SIZE];
DWORD readlen = 0, bytesLeft = READ_BUFFER_SIZE;
int writelen = 0;
do
{
    //reset the variables
    readlen = 0;
    writelen = 0;
   
    //read data from serial port
    ReadFile(hSerial,readbuffer,READ_BUFFER_SIZE,&readlen,0);
    //was there actual data read?
    if(readlen)
    {
        //send the bytes to the serial port
        bytesLeft = readlen;
        while(bytesLeft)
        {
            //did we send all the byte?
            bytesLeft -= send(hSocket,readbuffer+(readlen - bytesLeft),bytesLeft,0);
        }
    }
   
    //read the data from the net
    writelen = recv(hSocket,writebuffer,WRITE_BUFFER_SIZE,0);
   
    //did we receive any thing?
    if(writelen>0)
    {
        bytesLeft = writelen;
        while(bytesLeft)  //did we send every thing to the serial port?
        {
            DWORD byteSent = 0;
            //send to the serial port
            WriteFile(hSerial,writebuffer + (writelen - bytesLeft),bytesLeft,&byteSent,0);
            bytesLeft -= byteSent;
        }
    }
    else if(writelen < 0)
    {
        //we go an error we can ignore it if err == WSAEWOULDBLOCK
        long err = WSAGetLastError ();

    }
    if(writelen > 0 && readlen == 0)
    {
        Sleep(100);
    }       
}while(writelen); // the socket is closed

now if you run this and you run your STM32 Dsicovery,  what ever you send to serial will then be sent to (google in this example) the net.  Try doing a http get and get this page?

Next I will be posting on how to get HTTPS working on the stm32 Discover using this as your connection.
I will also discuss what else you can use to connect to the internet