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
main.cpp
- Committer:
- ashleymills
- Date:
- 2013-09-05
- Revision:
- 0:35b690909566
File content as of revision 0:35b690909566:
#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(¤tTime)); } } 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(); }