CyaSSL example using x509 certs and DTLS over ethernet.

Dependencies:   EthernetInterface NTPClient cyassl-lib mbed-rtos mbed-src CyaSSL_DTLS_Ethernet

Dependents:   CyaSSL_DTLS_Ethernet

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 "EthernetInterface.h"
00013 #include "NTPClient.h"
00014 
00015 #include "logging.h"
00016 
00017 #include "certs/device_certificate.h"
00018 #include "certs/device_private_key.h"
00019 #include "certs/root_certificate.h"
00020 
00021 /* 
00022 // this is how you would setup a client PSK
00023 static INLINE unsigned int my_psk_client_cb(CYASSL* ssl, const char* hint,
00024         char* identity, unsigned int id_max_len, unsigned char* key,
00025         unsigned int key_max_len)
00026 {
00027     (void)ssl;
00028     (void)hint;
00029     (void)key_max_len;
00030     
00031     DBG("PSK client callback callled.");
00032     
00033     // identity is OpenSSL testing default for openssl s_client, keep same
00034     strncpy(identity, "Client_identity", id_max_len);
00035 
00036 
00037     // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
00038     //   unsigned binary
00039     key[0] = 26;
00040     key[1] = 43;
00041     key[2] = 60;
00042     key[3] = 77;
00043 
00044     return 4;   // length of key in octets or 0 for error
00045 }
00046 */
00047 
00048 sockaddr_in bindAddr,serverAddress;
00049 
00050 bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
00051   *sockfd = -1;
00052   // create the socket
00053   if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
00054      DBG("Error opening socket");
00055      return false;
00056   }
00057   socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
00058    
00059   // bind socket to 11111
00060   memset(&bindAddr,  0x00, sockAddrInLen);
00061   bindAddr.sin_family = AF_INET; // IP family
00062   bindAddr.sin_port = htons(11111);
00063   bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
00064   // call bind
00065   if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
00066      DBG("Error binding socket");
00067      perror(NULL);
00068   }
00069 
00070   INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
00071          
00072   // create the socket address
00073 
00074   memset(&serverAddress, 0x00, sizeof(struct sockaddr_in));
00075   serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
00076   serverAddress.sin_family = AF_INET;
00077   serverAddress.sin_port = htons(port);
00078 
00079   // do socket connect
00080   //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
00081   if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
00082      shutdown(*sockfd,SHUT_RDWR);
00083      close(*sockfd);
00084      DBG("Could not connect");
00085      return false;
00086   }
00087   return true;
00088 }
00089 
00090 DigitalOut myled(LED1);
00091 #define INTERFACE EthernetInterface
00092 
00093 void printError(CYASSL *ssl, int resultCode) {
00094    int err = CyaSSL_get_error(ssl, resultCode);
00095    char errorString[80];
00096    CyaSSL_ERR_error_string(err, errorString);
00097    DBG("Error: CyaSSL_write %s", errorString);
00098 }
00099 
00100 void debugCallback(const int logLevel,const char *const logMessage) {
00101    DBG(logMessage);
00102 }
00103 
00104 
00105 int main() {
00106    DBG_INIT();
00107    DBG_SET_SPEED(115200);
00108    DBG_SET_NEWLINE("\r\n");
00109    DBG("\r\n\r\n\r\n\r\n");
00110    
00111    int ret = 0;
00112    
00113    // init ethernet
00114    EthernetInterface ethernet;
00115    // connnect ethernet
00116    DBG("Cnnecting to network interface");
00117    ethernet.init();
00118    if(ethernet.connect(10000)) {
00119       DBG("Error initialising ethernet interface");
00120    }
00121    DBG("Connected to network interface");
00122    
00123    DBG("IP: %s",ethernet.getIPAddress());
00124     
00125    // need to set the time before doing anything else
00126    NTPClient ntp;
00127    time_t currentTime = time(NULL);
00128    int obtainedTimeSuccessfully = false;
00129    // try 100 times and then just force a watchdog reboot
00130    for(int i=0; i<100; i++) {
00131       obtainedTimeSuccessfully = false;
00132    
00133       if(ntp.setTime("0.pool.ntp.org")==0) {
00134          // there is a bug from somewhere which results in a negative timestamp
00135          currentTime = time(NULL);
00136          if(currentTime>0) {
00137             obtainedTimeSuccessfully = true;
00138             INFO("Time set successfully, time is now (UTC): %s", ctime(&currentTime));
00139          }
00140       }
00141       if(obtainedTimeSuccessfully) {
00142          break;
00143       }
00144    }
00145         
00146    CyaSSL_Init();// Initialize CyaSSL
00147    if(CyaSSL_Debugging_ON()==0) {
00148       DBG("CyaSSL debugging enabled");
00149    } else {
00150       DBG("CyaSSL debugging not compiled in");
00151    }
00152    
00153    // use our own debugging system for CyaSSL debugging
00154    CyaSSL_SetLoggingCb(&debugCallback);
00155 
00156    // set client method
00157    
00158    // DTLS
00159    CYASSL_METHOD* method = CyaDTLSv1_2_client_method();
00160    if(method == NULL) {
00161       // unable to get method
00162    }
00163    CYASSL_CTX* ctx;
00164    ctx = CyaSSL_CTX_new(method);
00165    if(ctx == NULL){
00166       DBG("CyaSSL_CTX_new error.\n");
00167       exit(EXIT_FAILURE);
00168    }
00169    
00170    DBG("Setup SSL context");
00171    
00172    // use pre-shared keys
00173    //CyaSSL_CTX_set_psk_client_callback(ctx,my_psk_client_cb);
00174    
00175    // load certificates for CA and us
00176    // load CA cert
00177    ret = CyaSSL_CTX_load_verify_buffer(ctx,rootCertificate, rootCertificateLength,SSL_FILETYPE_ASN1);
00178    // load device cert
00179    ret = CyaSSL_CTX_use_certificate_buffer(ctx, deviceCertificate, deviceCertificateLength, SSL_FILETYPE_ASN1);
00180    // load device private key
00181    ret = CyaSSL_CTX_use_PrivateKey_buffer(ctx, devicePrivateKey, devicePrivateKeyLength, SSL_FILETYPE_ASN1);
00182    
00183    // setup UDP socket
00184    int sockfd = NULL;
00185    if(!connectToSocketUDP("192.168.1.99", 11111, &sockfd)) {
00186       DBG("Error connecting to socket");
00187    }
00188    
00189    DBG("Connected to non-SSL socket");
00190    
00191    // hook into SSL
00192    // Create CYASSL object
00193    CYASSL* ssl;
00194    ssl = CyaSSL_new(ctx);
00195    if(ssl == NULL) {
00196       DBG("CyaSSL_new error.");
00197       exit(EXIT_FAILURE);
00198    }
00199    DBG("CyaSSL_new OK");
00200    
00201    // this is where you set the peer name for the server
00202    // CyaSSL_connect() will return an error which resolves to
00203    // DOMAIN_NAME_MISMATCH via CyaSSL_get_error()
00204    // this is how you ensure that the peer is who you think it is
00205    CyaSSL_check_domain_name(ssl, "DMServer");
00206    
00207    // attach to socket
00208    DBG("Attaching CyaSSL to socket");
00209    CyaSSL_set_fd(ssl, sockfd);
00210    DBG("Attached CyaSSL to socket");
00211    
00212    // DTLS stuff
00213    ret = CyaSSL_dtls_set_peer(ssl, &serverAddress, sizeof(serverAddress));
00214    if(ret != SSL_SUCCESS) {
00215       // failed to set DTLS peer
00216       DBG("Failed to set DTLS peer");
00217    }
00218    
00219    ret = CyaSSL_dtls(ssl);
00220    if(ret) {
00221       // SSL session has been configured to use DTLS
00222       DBG("DTLS configured");
00223    } else {
00224       DBG("DTLS not configured");
00225    }
00226    
00227    DBG("Issuing CyaSSL_connect");
00228    int result = CyaSSL_connect(ssl);
00229    if(result!=SSL_SUCCESS) {
00230       DBG("CyaSSL_connect failed");
00231       printError(ssl,result);
00232    }
00233    DBG("CyaSSL_connect OK");
00234    
00235    result = CyaSSL_write(ssl,"onion",5);
00236    DBG("Wrote %d things",result);
00237    if(result<0) {
00238       printError(ssl,result);
00239    }
00240    
00241     char buffer[200];
00242     int d =0;
00243     if((d=CyaSSL_read(ssl, &buffer, 200))>0) {
00244        DBG("Received %d bytes: %s",d,buffer);
00245     }
00246    
00247    // clean up
00248    CyaSSL_CTX_free(ctx);
00249    CyaSSL_Cleanup();  
00250    
00251 }