DTLS example using CyaSSL 2.7.0 and x509 certs. Doesn't work at present due to DTLS handshake failure. Debugging.

Dependencies:   NTPClient VodafoneUSBModem cyassl-lib mbed-rtos mbed-src

Revision:
0:35b690909566
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Sep 05 15:56:41 2013 +0000
@@ -0,0 +1,366 @@
+#define __DEBUG__ 4 //Maximum verbosity
+#ifndef __MODULE__
+#define __MODULE__ "main.cpp"
+#endif
+
+#define DEBUG_CYASSL 1
+#include "bsd_socket.h"
+#include "mbed.h"
+#include "rtos.h"
+#include "dbg.h"
+#include "cyassl/ssl.h"
+#include "VodafoneUSBModem.h"
+//#include "EthernetInterface.h"
+#include "NTPClient.h"
+
+#include "logging.h"
+
+#define APN_GDSP
+
+#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
+
+#include "certs/device_certificate.h"
+#include "certs/device_private_key.h"
+#include "certs/root_certificate.h"
+
+#include <cyassl/ctaocrypt/types.h>
+
+
+static INLINE unsigned int my_psk_client_cb(CYASSL* ssl, const char* hint,
+        char* identity, unsigned int id_max_len, unsigned char* key,
+        unsigned int key_max_len)
+{
+    (void)ssl;
+    (void)hint;
+    (void)key_max_len;
+    
+    DBG("PSK client callback callled.");
+    
+    // identity is OpenSSL testing default for openssl s_client, keep same
+    strncpy(identity, "Client_identity", id_max_len);
+
+
+    // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
+    //   unsigned binary
+    key[0] = 26;
+    key[1] = 43;
+    key[2] = 60;
+    key[3] = 77;
+
+    return 4;   // length of key in octets or 0 for error
+}
+/*
+
+static INLINE unsigned int my_psk_server_cb(CYASSL* ssl, const char* identity,
+        unsigned char* key, unsigned int key_max_len)
+{
+    (void)ssl;
+    (void)key_max_len;
+
+
+    DBG("PSK server callback called.");
+
+    // identity is OpenSSL testing default for openssl s_client, keep same
+    if (strncmp(identity, "Client_identity", 15) != 0)
+        return 0;
+
+    // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
+    // unsigned binary
+    key[0] = 26;
+    key[1] = 43;
+    key[2] = 60;
+    key[3] = 77;
+
+    return 4;   // length of key in octets or 0 for error
+}
+*/
+
+sockaddr_in bindAddr,serverAddress;
+
+bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
+  *sockfd = -1;
+  // create the socket
+  if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
+     DBG("Error opening socket");
+     return false;
+  }
+  socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
+   
+  // bind socket to 11111
+  memset(&bindAddr,  0x00, sockAddrInLen);
+  bindAddr.sin_family = AF_INET; // IP family
+  bindAddr.sin_port = htons(11111);
+  bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
+  // call bind
+  if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
+     DBG("Error binding socket");
+     perror(NULL);
+  }
+
+  INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
+         
+  // create the socket address
+
+  memset(&serverAddress, 0x00, 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) {
+     shutdown(*sockfd,SHUT_RDWR);
+     close(*sockfd);
+     DBG("Could not connect");
+     return false;
+  }
+  return true;
+}
+
+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) {
+     shutdown(*sockfd,SHUT_RDWR);
+     close(*sockfd);
+     DBG("Could not connect");
+     return false;
+  }
+  return true;
+}
+/*
+int handshakeCallback(HandShakeInfo* hinfo) {
+   DBG("Handshake callback called");
+}
+int timeoutCallback(TimeoutInfo *tinfo) {
+   DBG("Timeout callback called");
+}
+*/
+
+
+DigitalOut myled(LED1);
+//#define INTERFACE EthernetInterface
+#define INTERFACE VodafoneUSBModem
+
+void printError(CYASSL *ssl, int resultCode) {
+   int err = CyaSSL_get_error(ssl, resultCode);
+   char errorString[80];
+   CyaSSL_ERR_error_string(err, errorString);
+   DBG("Error: CyaSSL_write %s", errorString);
+}
+
+void debugCallback(const int logLevel,const char *const logMessage) {
+   DBG(logMessage);
+}
+
+
+int main() {
+   DBG_INIT();
+   DBG_SET_SPEED(115200);
+   DBG_SET_NEWLINE("\r\n");
+   DBG("\r\n\r\n\r\n\r\n");
+   
+   int ret = 0;
+   
+   // init modem
+   INTERFACE modem;
+   // connnect modem to cellular network
+   DBG("connecting to network interface");
+   if(modem.connect(APN,APN_USERNAME,APN_PASSWORD)!=0) {
+      DBG("Error connecting to mobile network");
+   }
+   /*
+   modem.init();
+   if(modem.connect(10000)) {
+      DBG("Error initialising ethernet interface");
+   }
+   */
+   DBG("Connected to network interface");
+   
+   //DBG("IP: %s",modem.getIPAddress());
+    
+   // need to set the time before doing anything else
+   NTPClient ntp;
+   time_t currentTime = time(NULL);
+   int obtainedTimeSuccessfully = false;
+   // try 100 times and then just force a watchdog reboot
+   for(int i=0; i<100; i++) {
+      obtainedTimeSuccessfully = false;
+   
+      if(ntp.setTime("0.pool.ntp.org")==0) {
+         // there is a bug from somewhere which results in a negative timestamp
+         currentTime = time(NULL);
+         if(currentTime>0) {
+            obtainedTimeSuccessfully = true;
+            INFO("Time set successfully, time is now (UTC): %s", ctime(&currentTime));
+         }
+      }
+      if(obtainedTimeSuccessfully) {
+         break;
+      }
+   }
+   
+    
+   // set SSL method to SSL v3 (TLS v1.2)
+   //CyaSSLv23_client_method();
+     
+   CyaSSL_Init();// Initialize CyaSSL
+   if(CyaSSL_Debugging_ON()==0) {
+      DBG("CyaSSL debugging enabled");
+   } else {
+      DBG("CyaSSL debugging not compiled in");
+   }
+   
+   CyaSSL_SetLoggingCb(&debugCallback);
+
+   
+
+   // set client method
+   
+   // TLS
+   //CYASSL_CTX* ctx = CyaSSL_CTX_new(CyaSSLv23_client_method());
+   
+   // DTLS
+   CYASSL_METHOD* method = CyaDTLSv1_2_client_method();
+   if(method == NULL) {
+      // unable to get method
+   }
+   CYASSL_CTX* ctx;
+   ctx = CyaSSL_CTX_new(method);
+   if(ctx == NULL){
+      DBG("CyaSSL_CTX_new error.\n");
+      exit(EXIT_FAILURE);
+   }
+   
+   DBG("Setup SSL context");
+   
+   
+
+   
+   // use pre-shared keys
+   //CyaSSL_CTX_set_psk_client_callback(ctx,my_psk_client_cb);
+   /*
+   if(CyaSSL_CTX_load_verify_buffer(ctx, serverCert, strlen((const char*)serverCert),SSL_FILETYPE_PEM)==0) {
+   DBG("loaded server cert OK");
+   }*/
+
+   
+   // load certificates for CA and us
+   // load CA cert
+   ret = CyaSSL_CTX_load_verify_buffer(ctx,rootCertificate, rootCertificateLength,SSL_FILETYPE_ASN1);
+   // load device cert
+   ret = CyaSSL_CTX_use_certificate_buffer(ctx, deviceCertificate, deviceCertificateLength, SSL_FILETYPE_ASN1);
+   // load device private key
+   ret = CyaSSL_CTX_use_PrivateKey_buffer(ctx, devicePrivateKey, devicePrivateKeyLength, SSL_FILETYPE_ASN1);
+
+   
+   int sockfd = NULL;
+   //if(!connectToSocketUDP("192.168.1.99", 11111, &sockfd)) {
+   if(!connectToSocketUDP("95.47.118.120", 11111, &sockfd)) {
+      DBG("Error connecting to socket");
+   }
+   
+  /*
+   // connect to SSL enabled webserver
+   int sockfd = NULL;
+   if(!connectToSocket("95.47.118.120", 11111, &sockfd)) {
+      DBG("Error connecting to socket");
+   }
+   DBG("Connected to non-SSL socket");
+   */
+   
+   // hook into SSL
+   // Create CYASSL object
+   CYASSL* ssl;
+   ssl = CyaSSL_new(ctx);
+   if(ssl == NULL) {
+      DBG("CyaSSL_new error.");
+      exit(EXIT_FAILURE);
+   }
+   DBG("CyaSSL_new OK");
+   
+   // setup callbacks for handshake failure
+   /*
+   Timeval timeout;
+   timeout.tv_sec  = 5;
+   timeout.tv_usec = 0;
+   ret = CyaSSL_connect_ex(ssl, handshakeCallback, timeoutCallback, timeout);
+   */
+   
+   // attach to socket
+   DBG("Attaching CyaSSL to socket");
+   CyaSSL_set_fd(ssl, sockfd);
+   DBG("Attached CyaSSL to socket");
+   
+   // DTLS stuff
+   ret = CyaSSL_dtls_set_peer(ssl, &serverAddress, sizeof(serverAddress));
+   if(ret != SSL_SUCCESS) {
+      // failed to set DTLS peer
+      DBG("Failed to set DTLS peer");
+   }
+   
+   ret = CyaSSL_dtls(ssl);
+   if(ret) {
+      // SSL session has been configured to use DTLS
+      DBG("DTLS configured");
+   } else {
+      DBG("DTLS not configured");
+   }
+   
+   
+   
+   DBG("Issuing CyaSSL_connect");
+   int result = CyaSSL_connect(ssl);
+   if(result!=SSL_SUCCESS) {
+      DBG("CyaSSL_connect failed");
+      printError(ssl,result);
+   }
+   DBG("CyaSSL_connect OK");
+   
+   result = CyaSSL_write(ssl,"onion",5);
+   DBG("Wrote %d things",result);
+   if(result<0) {
+      printError(ssl,result);
+   }
+   
+    char buffer[200];
+    int d =0;
+    if((d=CyaSSL_read(ssl, &buffer, 200))>0) {
+       DBG("Received %d bytes: %s",d,buffer);
+    }
+   
+   // clean up
+   CyaSSL_CTX_free(ctx);
+   CyaSSL_Cleanup();  
+   
+} 
\ No newline at end of file