Rough and ready demo of axTLS with 3G modem

Dependencies:   VodafoneUSBModem_bleedingedge axTLS mbed-rtos mbed

main.cpp

Committer:
ashleymills
Date:
2013-05-28
Revision:
1:db88ff473b1a
Parent:
0:795bb54e1ee8

File content as of revision 1:db88ff473b1a:

#define __DEBUG__ 4 //Maximum verbosity
#ifndef __MODULE__
#define __MODULE__ "main.cpp"
#endif

#include "mbed.h"
#include "rtos.h"
#include "VodafoneUSBModem.h"
#include "ssl.h"
#include "socket.h"
#include "cert.h"

#define APN_PAYG

#ifdef APN_GDSP
   #define APN "ppinternetd.gdsp" 
   #define APN_USERNAME ""
   #define APN_PASSWORD ""
#endif

#ifdef APN_CONTRACT
   #define APN "internet" 
   #define APN_USERNAME "web"
   #define APN_PASSWORD "web"
#endif

#ifdef APN_PAYG
   #define APN "smart" 
   #define APN_USERNAME "web"
   #define APN_PASSWORD "web"
#endif

DigitalOut myled(LED1);

static void display_cipher(SSL *ssl)
{
    printf("CIPHER is ");
    switch (ssl_get_cipher_id(ssl))
    {
        case SSL_AES128_SHA:
            printf("AES128-SHA");
            break;

        case SSL_AES256_SHA:
            printf("AES256-SHA");
            break;

        case SSL_RC4_128_SHA:
            printf("RC4-SHA");
            break;

        case SSL_RC4_128_MD5:
            printf("RC4-MD5");
            break;

        default:
            printf("Unknown - %d", ssl_get_cipher_id(ssl));
            break;
    }

    printf("\r\n");
}


bool connectToSocket(char *ipAddress, int port, int *sockfd) {
  *sockfd = -1;
  // create the socket
  if((*sockfd=socket(AF_INET,SOCK_STREAM,0))<0) {
     DBG("Error opening socket");
     return false;
  }
         
  // create the socket address
  sockaddr_in serverAddress;
  std::memset(&serverAddress, 0, sizeof(struct sockaddr_in));
  serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
  serverAddress.sin_family = AF_INET;
  serverAddress.sin_port = htons(port);

  // do socket connect
  //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
  if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
     ::close(*sockfd);
     DBG("Could not connect");
     return false;
  }
  return true;
}

void finishOnError() {
   DigitalOut l1(LED1);
   while(1) {
      Thread::wait(1000);
      l1 = !l1;
   }
}

void finishOnOK() {
   DigitalOut l(LED2);
   while(1) {
      Thread::wait(1000);
      l = !l;
   }
}

int main() {
   DBG_INIT();
   DBG_SET_SPEED(115200);
   DBG_SET_NEWLINE("\r\n");
   
   set_time(1368461860);
   
   // init modem
   VodafoneUSBModem modem;
   
   // SSL stuff
   uint32_t sslOptions = SSL_DISPLAY_CERTS|SSL_DISPLAY_STATES|SSL_SERVER_VERIFY_LATER;
   SSL_CTX *ssl_ctx;
   SSL *ssl = NULL;
   /*
   char **ca_cert, **cert;
   int cert_size, ca_cert_size;
   cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
   ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
   ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
   cert = (char **)calloc(1, sizeof(char *)*cert_size);
   */
   uint8_t session_id[SSL_SESSION_ID_SIZE];
   int res;
   
   if((ssl_ctx = ssl_ctx_new(sslOptions, SSL_DEFAULT_CLNT_SESS)) == NULL) {
      DBG("Error: Client context is invalid");
      finishOnError();
   }
   
  if((res = ssl_obj_memory_load(ssl_ctx,SSL_OBJ_X509_CACERT, default_certificate, default_certificate_len,NULL)) != SSL_OK) {
     DBG("Error loading CA cert\r\n");
  }

   
   // connnect modem to cellular network
   DBG("connecting to mobile network");
   if(modem.connect(APN,APN_USERNAME,APN_PASSWORD)!=0) {
      DBG("Error connecting to mobile network");
      finishOnError();
   }
   DBG("Connected to mobile network");
   
   
   // connect to socket over which TLS will be spoken
   int sockfd = NULL;
   if(!connectToSocket("95.47.118.120", 4433, &sockfd)) {
      DBG("Error connecting to socket");
      modem.disconnect();
      finishOnError();
   }
   DBG("Connected to non-SSL socket");
   
   ssl = ssl_client_new(ssl_ctx, sockfd, session_id,sizeof(session_id));
   if(ssl==NULL) {
      DBG("SSL client is NULL");
      modem.disconnect();
      finishOnError();
   }
   if((res = ssl_handshake_status(ssl)) != SSL_OK) {
      DBG("Error conecting ssl client");
      modem.disconnect();
      finishOnError();
   }
   const char *common_name = ssl_get_cert_dn(ssl,SSL_X509_CERT_COMMON_NAME);
   if(common_name) {
      printf("Server Common Name: %s\r\n", common_name);
   }

   display_cipher(ssl);


   
   DBG("SSL connected ok");
   // verify cert
   if((res=ssl_verify_cert(ssl))!= SSL_OK) {
      DBG("Failed to verify certifcate\r\n");
      ssl_display_error(res);
      modem.disconnect();
      finishOnError();
   }
   
   DBG("Server certificate verified\r\n");

   ssl_write(ssl,"hello\r\n",7);

   // dump responses
   uint8_t *read_buffer = NULL;
   while(1) {
      int bytesRead = ssl_read(ssl,&read_buffer);
      if(bytesRead>0) {
         DBG("GOT(%d): \"%s\"",bytesRead,read_buffer);
      } else if(bytesRead==0) {
         DBG("WARNING: TLS handshake incomplete");
      } else {
         break;
      }
      Thread::wait(300);
   }

   modem.disconnect();
   finishOnOK();
}