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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #define __DEBUG__ 4 //Maximum verbosity
00002 #ifndef __MODULE__
00003 #define __MODULE__ "main.cpp"
00004 #endif
00005 
00006 #define DEBUG_CYASSL 1
00007 #include "bsd_socket.h"
00008 #include "mbed.h"
00009 #include "rtos.h"
00010 #include "dbg.h"
00011 #include "cyassl/ssl.h"
00012 #include "VodafoneUSBModem.h"
00013 //#include "EthernetInterface.h"
00014 #include "NTPClient.h"
00015 
00016 #include "logging.h"
00017 
00018 #define APN_GDSP
00019 
00020 #ifdef APN_GDSP
00021    #define APN "ppinternetd.gdsp" 
00022    #define APN_USERNAME ""
00023    #define APN_PASSWORD ""
00024 #endif
00025 
00026 #ifdef APN_CONTRACT
00027    #define APN "internet" 
00028    #define APN_USERNAME "web"
00029    #define APN_PASSWORD "web"
00030 #endif
00031 
00032 #ifdef APN_PAYG
00033    #define APN "smart" 
00034    #define APN_USERNAME "web"
00035    #define APN_PASSWORD "web"
00036 #endif
00037 
00038 #include "certs/device_certificate.h"
00039 #include "certs/device_private_key.h"
00040 #include "certs/root_certificate.h"
00041 
00042 #include <cyassl/ctaocrypt/types.h>
00043 
00044 
00045 static INLINE unsigned int my_psk_client_cb(CYASSL* ssl, const char* hint,
00046         char* identity, unsigned int id_max_len, unsigned char* key,
00047         unsigned int key_max_len)
00048 {
00049     (void)ssl;
00050     (void)hint;
00051     (void)key_max_len;
00052     
00053     DBG("PSK client callback callled.");
00054     
00055     // identity is OpenSSL testing default for openssl s_client, keep same
00056     strncpy(identity, "Client_identity", id_max_len);
00057 
00058 
00059     // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
00060     //   unsigned binary
00061     key[0] = 26;
00062     key[1] = 43;
00063     key[2] = 60;
00064     key[3] = 77;
00065 
00066     return 4;   // length of key in octets or 0 for error
00067 }
00068 /*
00069 
00070 static INLINE unsigned int my_psk_server_cb(CYASSL* ssl, const char* identity,
00071         unsigned char* key, unsigned int key_max_len)
00072 {
00073     (void)ssl;
00074     (void)key_max_len;
00075 
00076 
00077     DBG("PSK server callback called.");
00078 
00079     // identity is OpenSSL testing default for openssl s_client, keep same
00080     if (strncmp(identity, "Client_identity", 15) != 0)
00081         return 0;
00082 
00083     // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
00084     // unsigned binary
00085     key[0] = 26;
00086     key[1] = 43;
00087     key[2] = 60;
00088     key[3] = 77;
00089 
00090     return 4;   // length of key in octets or 0 for error
00091 }
00092 */
00093 
00094 sockaddr_in bindAddr,serverAddress;
00095 
00096 bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
00097   *sockfd = -1;
00098   // create the socket
00099   if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
00100      DBG("Error opening socket");
00101      return false;
00102   }
00103   socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
00104    
00105   // bind socket to 11111
00106   memset(&bindAddr,  0x00, sockAddrInLen);
00107   bindAddr.sin_family = AF_INET; // IP family
00108   bindAddr.sin_port = htons(11111);
00109   bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
00110   // call bind
00111   if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
00112      DBG("Error binding socket");
00113      perror(NULL);
00114   }
00115 
00116   INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
00117          
00118   // create the socket address
00119 
00120   memset(&serverAddress, 0x00, sizeof(struct sockaddr_in));
00121   serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
00122   serverAddress.sin_family = AF_INET;
00123   serverAddress.sin_port = htons(port);
00124 
00125   // do socket connect
00126   //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
00127   if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
00128      shutdown(*sockfd,SHUT_RDWR);
00129      close(*sockfd);
00130      DBG("Could not connect");
00131      return false;
00132   }
00133   return true;
00134 }
00135 
00136 bool connectToSocket(char *ipAddress, int port, int *sockfd) {
00137   *sockfd = -1;
00138   // create the socket
00139   if((*sockfd=socket(AF_INET,SOCK_STREAM,0))<0) {
00140      DBG("Error opening socket");
00141      return false;
00142   }
00143          
00144   // create the socket address
00145   sockaddr_in serverAddress;
00146   std::memset(&serverAddress, 0, sizeof(struct sockaddr_in));
00147   serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
00148   serverAddress.sin_family = AF_INET;
00149   serverAddress.sin_port = htons(port);
00150 
00151   // do socket connect
00152   //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
00153   if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
00154      shutdown(*sockfd,SHUT_RDWR);
00155      close(*sockfd);
00156      DBG("Could not connect");
00157      return false;
00158   }
00159   return true;
00160 }
00161 /*
00162 int handshakeCallback(HandShakeInfo* hinfo) {
00163    DBG("Handshake callback called");
00164 }
00165 int timeoutCallback(TimeoutInfo *tinfo) {
00166    DBG("Timeout callback called");
00167 }
00168 */
00169 
00170 
00171 DigitalOut myled(LED1);
00172 //#define INTERFACE EthernetInterface
00173 #define INTERFACE VodafoneUSBModem
00174 
00175 void printError(CYASSL *ssl, int resultCode) {
00176    int err = CyaSSL_get_error(ssl, resultCode);
00177    char errorString[80];
00178    CyaSSL_ERR_error_string(err, errorString);
00179    DBG("Error: CyaSSL_write %s", errorString);
00180 }
00181 
00182 void debugCallback(const int logLevel,const char *const logMessage) {
00183    DBG(logMessage);
00184 }
00185 
00186 
00187 int main() {
00188    DBG_INIT();
00189    DBG_SET_SPEED(115200);
00190    DBG_SET_NEWLINE("\r\n");
00191    DBG("\r\n\r\n\r\n\r\n");
00192    
00193    int ret = 0;
00194    
00195    // init modem
00196    INTERFACE modem;
00197    // connnect modem to cellular network
00198    DBG("connecting to network interface");
00199    if(modem.connect(APN,APN_USERNAME,APN_PASSWORD)!=0) {
00200       DBG("Error connecting to mobile network");
00201    }
00202    /*
00203    modem.init();
00204    if(modem.connect(10000)) {
00205       DBG("Error initialising ethernet interface");
00206    }
00207    */
00208    DBG("Connected to network interface");
00209    
00210    //DBG("IP: %s",modem.getIPAddress());
00211     
00212    // need to set the time before doing anything else
00213    NTPClient ntp;
00214    time_t currentTime = time(NULL);
00215    int obtainedTimeSuccessfully = false;
00216    // try 100 times and then just force a watchdog reboot
00217    for(int i=0; i<100; i++) {
00218       obtainedTimeSuccessfully = false;
00219    
00220       if(ntp.setTime("0.pool.ntp.org")==0) {
00221          // there is a bug from somewhere which results in a negative timestamp
00222          currentTime = time(NULL);
00223          if(currentTime>0) {
00224             obtainedTimeSuccessfully = true;
00225             INFO("Time set successfully, time is now (UTC): %s", ctime(&currentTime));
00226          }
00227       }
00228       if(obtainedTimeSuccessfully) {
00229          break;
00230       }
00231    }
00232    
00233     
00234    // set SSL method to SSL v3 (TLS v1.2)
00235    //CyaSSLv23_client_method();
00236      
00237    CyaSSL_Init();// Initialize CyaSSL
00238    if(CyaSSL_Debugging_ON()==0) {
00239       DBG("CyaSSL debugging enabled");
00240    } else {
00241       DBG("CyaSSL debugging not compiled in");
00242    }
00243    
00244    CyaSSL_SetLoggingCb(&debugCallback);
00245 
00246    
00247 
00248    // set client method
00249    
00250    // TLS
00251    //CYASSL_CTX* ctx = CyaSSL_CTX_new(CyaSSLv23_client_method());
00252    
00253    // DTLS
00254    CYASSL_METHOD* method = CyaDTLSv1_2_client_method();
00255    if(method == NULL) {
00256       // unable to get method
00257    }
00258    CYASSL_CTX* ctx;
00259    ctx = CyaSSL_CTX_new(method);
00260    if(ctx == NULL){
00261       DBG("CyaSSL_CTX_new error.\n");
00262       exit(EXIT_FAILURE);
00263    }
00264    
00265    DBG("Setup SSL context");
00266    
00267    
00268 
00269    
00270    // use pre-shared keys
00271    //CyaSSL_CTX_set_psk_client_callback(ctx,my_psk_client_cb);
00272    /*
00273    if(CyaSSL_CTX_load_verify_buffer(ctx, serverCert, strlen((const char*)serverCert),SSL_FILETYPE_PEM)==0) {
00274    DBG("loaded server cert OK");
00275    }*/
00276 
00277    
00278    // load certificates for CA and us
00279    // load CA cert
00280    ret = CyaSSL_CTX_load_verify_buffer(ctx,rootCertificate, rootCertificateLength,SSL_FILETYPE_ASN1);
00281    // load device cert
00282    ret = CyaSSL_CTX_use_certificate_buffer(ctx, deviceCertificate, deviceCertificateLength, SSL_FILETYPE_ASN1);
00283    // load device private key
00284    ret = CyaSSL_CTX_use_PrivateKey_buffer(ctx, devicePrivateKey, devicePrivateKeyLength, SSL_FILETYPE_ASN1);
00285 
00286    
00287    int sockfd = NULL;
00288    //if(!connectToSocketUDP("192.168.1.99", 11111, &sockfd)) {
00289    if(!connectToSocketUDP("95.47.118.120", 11111, &sockfd)) {
00290       DBG("Error connecting to socket");
00291    }
00292    
00293   /*
00294    // connect to SSL enabled webserver
00295    int sockfd = NULL;
00296    if(!connectToSocket("95.47.118.120", 11111, &sockfd)) {
00297       DBG("Error connecting to socket");
00298    }
00299    DBG("Connected to non-SSL socket");
00300    */
00301    
00302    // hook into SSL
00303    // Create CYASSL object
00304    CYASSL* ssl;
00305    ssl = CyaSSL_new(ctx);
00306    if(ssl == NULL) {
00307       DBG("CyaSSL_new error.");
00308       exit(EXIT_FAILURE);
00309    }
00310    DBG("CyaSSL_new OK");
00311    
00312    // setup callbacks for handshake failure
00313    /*
00314    Timeval timeout;
00315    timeout.tv_sec  = 5;
00316    timeout.tv_usec = 0;
00317    ret = CyaSSL_connect_ex(ssl, handshakeCallback, timeoutCallback, timeout);
00318    */
00319    
00320    // attach to socket
00321    DBG("Attaching CyaSSL to socket");
00322    CyaSSL_set_fd(ssl, sockfd);
00323    DBG("Attached CyaSSL to socket");
00324    
00325    // DTLS stuff
00326    ret = CyaSSL_dtls_set_peer(ssl, &serverAddress, sizeof(serverAddress));
00327    if(ret != SSL_SUCCESS) {
00328       // failed to set DTLS peer
00329       DBG("Failed to set DTLS peer");
00330    }
00331    
00332    ret = CyaSSL_dtls(ssl);
00333    if(ret) {
00334       // SSL session has been configured to use DTLS
00335       DBG("DTLS configured");
00336    } else {
00337       DBG("DTLS not configured");
00338    }
00339    
00340    
00341    
00342    DBG("Issuing CyaSSL_connect");
00343    int result = CyaSSL_connect(ssl);
00344    if(result!=SSL_SUCCESS) {
00345       DBG("CyaSSL_connect failed");
00346       printError(ssl,result);
00347    }
00348    DBG("CyaSSL_connect OK");
00349    
00350    result = CyaSSL_write(ssl,"onion",5);
00351    DBG("Wrote %d things",result);
00352    if(result<0) {
00353       printError(ssl,result);
00354    }
00355    
00356     char buffer[200];
00357     int d =0;
00358     if((d=CyaSSL_read(ssl, &buffer, 200))>0) {
00359        DBG("Received %d bytes: %s",d,buffer);
00360     }
00361    
00362    // clean up
00363    CyaSSL_CTX_free(ctx);
00364    CyaSSL_Cleanup();  
00365    
00366 }