Simple TLS Client with wolfSSL

Dependencies:   wolfSSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers client-tls.cpp Source File

client-tls.cpp

00001 /* client-tcp.c
00002  *
00003  * Copyright (C) 2006-2017 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL. (formerly known as CyaSSL)
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include    "mbed.h"
00023 
00024 #include    <stdio.h>
00025 #include    <stdlib.h>
00026 #include    <string.h>
00027 
00028 #include    <wolfssl/ssl.h>          /* wolfSSL security library */
00029 #include    <wolfssl/wolfcrypt/error-crypt.h>
00030 #include    <wolfssl/certs_test.h>   /* memory image test certs */
00031 #include    <user_settings.h>
00032 
00033 #define MAXDATASIZE (1024*4)
00034 
00035 static int SocketReceive(WOLFSSL* ssl, char *buf, int sz, void *sock)
00036 {
00037     int recvd;
00038     
00039     recvd = ((TCPSocket *)sock)->recv(buf, sz) ;
00040     if(recvd > 0)return recvd;
00041     else if (recvd == 0) {
00042         return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00043     }
00044     else if (recvd == EWOULDBLOCK) /* for non-blocing */
00045         return WOLFSSL_CBIO_ERR_WANT_READ;
00046     else
00047         return WOLFSSL_CBIO_ERR_GENERAL;
00048 }
00049 
00050 static int SocketSend(WOLFSSL* ssl, char *buf, int sz, void *sock)
00051 {
00052     int sent;
00053     sent = ((TCPSocket *)sock)->send(buf, sz);
00054 
00055     if(sent > 0)return sent;
00056     else if (sent == 0) {
00057         return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00058     }
00059     else if (sent == EWOULDBLOCK) /* for non-blocing */
00060         return WOLFSSL_CBIO_ERR_WANT_WRITE;
00061     else
00062         return WOLFSSL_CBIO_ERR_GENERAL;
00063 }
00064 
00065 
00066 
00067 static int getline(char *prompt, char *buff, int size)
00068 {
00069     int sz ;
00070 
00071     printf("%s", prompt) ;
00072     for(sz = 0 ;  (sz < size) && ((*buff = getchar()) != '\r'); sz++, buff++) {
00073         putchar(*buff) ;
00074         if(*buff == '\\') {
00075             if(++sz >= size)break ;
00076             *buff = getchar() ;
00077             putchar(*buff) ;
00078             switch(*buff) {
00079                 case 'n' :
00080                     *buff = '\n' ;
00081                     break ;
00082                 case 'r' :
00083                     *buff = '\r' ;
00084                     break ;
00085                 case 't' :
00086                     *buff = '\t' ;
00087                     break ;
00088                 case '\\':
00089                     *buff = '\\' ;
00090                     break ;
00091                 default:
00092                     buff[1] = buff[0] ;
00093                     buff[0] = '\\' ;
00094                     buff++ ;
00095             }
00096         } else if(*buff == '\b') {
00097             if(sz >= 2) {
00098                 buff-=2 ;
00099                 sz-=2;
00100             }
00101         }
00102     } ;
00103     putchar('\n') ;
00104     *buff = '\0' ;
00105     return sz ;
00106 }
00107 
00108 /*
00109  *  clients initial contact with server. Socket to connect to: sock
00110  */
00111 int ClientGreet(TCPSocket *socket, WOLFSSL *ssl)
00112 {
00113     /* data to send to the server, data recieved from the server */
00114     char    sendBuff[MAXDATASIZE], rcvBuff[MAXDATASIZE] = {0};
00115     int     ret ;
00116 
00117     ret = getline("Message for server: ", sendBuff, MAXDATASIZE);
00118     printf("Send[%d]:\n%s\n", ret, sendBuff) ;
00119     if (wolfSSL_write(ssl, sendBuff, strlen(sendBuff)) < 0) {
00120         /* the message is not able to send, or error trying */
00121         ret = wolfSSL_get_error(ssl, 0);
00122         printf("Write error[%d]\n", ret, wc_GetErrorString(ret));
00123         return EXIT_FAILURE;
00124     }
00125 
00126     if ((ret = wolfSSL_read(ssl, rcvBuff, sizeof(rcvBuff)-1)) < 0) {
00127         /* the server failed to send data, or error trying */
00128         ret = wolfSSL_get_error(ssl, 0);
00129         printf("Read error[%d], %s\n", ret, wc_GetErrorString(ret));
00130         return EXIT_FAILURE;
00131     }
00132     rcvBuff[ret] = '\0' ; 
00133     printf("Recieved: %s\n", rcvBuff);
00134 
00135     return ret;
00136 }
00137 
00138 
00139 /*
00140  * applies TLS 1.2 security layer to data being sent.
00141  */
00142 int Security(TCPSocket *socket)
00143 {
00144     WOLFSSL_METHOD*  method  = 0;
00145     WOLFSSL_CTX* ctx = 0;
00146     WOLFSSL*     ssl = 0;    /* create WOLFSSL object */
00147     int          ret = 0;
00148     
00149     const unsigned char *cert  = ca_cert_der_2048;
00150     int sizeof_cert = sizeof_ca_cert_der_2048;
00151     
00152     #ifdef WOLFSSL_TLS13
00153     char tls_version[2];
00154     int  tlsVer = 0 ;
00155 
00156     while((tlsVer != 2) && (tlsVer != 3)){
00157         getline("TLS ver(2/3): ", tls_version, sizeof(tls_version)) ;
00158         tlsVer = atoi(tls_version);
00159     }
00160     if(tlsVer == 3)method = wolfTLSv1_3_client_method();
00161     else           method = wolfTLSv1_2_client_method();
00162     #else
00163     method = wolfTLSv1_2_client_method();
00164     #endif
00165     
00166     /* create and initiLize WOLFSSL_CTX structure */
00167     if ((ctx = wolfSSL_CTX_new(method)) == NULL) {
00168         printf("SSL_CTX_new error.\n");
00169         return EXIT_FAILURE;
00170     }
00171     wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, 0);
00172     wolfSSL_SetIORecv(ctx, SocketReceive) ;
00173     wolfSSL_SetIOSend(ctx, SocketSend) ;
00174     if ((ret = wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048,
00175         sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1))!= WOLFSSL_SUCCESS){
00176         printf("can't load buffer ca file(%d)\n", ret);
00177         return EXIT_FAILURE;
00178     }
00179     if ((ssl = wolfSSL_new(ctx)) == NULL) {
00180         printf("wolfSSL_new error.\n");
00181         return EXIT_FAILURE;
00182     }
00183 
00184     wolfSSL_SetIOReadCtx(ssl, (void *)socket) ;
00185     wolfSSL_SetIOWriteCtx(ssl, (void *)socket) ;
00186 
00187     ret = wolfSSL_connect(ssl);
00188     if (ret == SSL_SUCCESS) {
00189         printf("TLS Connected\n") ;
00190         ret = ClientGreet(socket, ssl);
00191     } else {
00192         ret = wolfSSL_get_error(ssl, 0);
00193         printf("TLS Connect error[%d], %s\n", ret, wc_GetErrorString(ret));
00194         return EXIT_FAILURE;
00195     }
00196     /* frees all data before client termination */
00197     wolfSSL_shutdown(ssl);
00198     wolfSSL_free(ssl);
00199     wolfSSL_CTX_free(ctx);
00200     wolfSSL_Cleanup();
00201 
00202     return ret;
00203 }
00204 
00205 /*
00206  * command line argumentCount and argumentValues
00207  */
00208 void net_main(const void *av)
00209 {
00210     char server_addr[40] ;
00211     char server_port[10] ;
00212     NetworkInterface *net;
00213     SocketAddress a;
00214     TCPSocket socket;
00215     int port;
00216         
00217     printf("Starting TLS Client,...\n") ;
00218     wolfSSL_Init();      /* initialize wolfSSL */
00219     /* wolfSSL_Debugging_ON(); */
00220     net = NetworkInterface::get_default_instance();
00221     if (!net) {
00222         printf("Error! No network inteface found.\n");
00223         return;
00224     }
00225     
00226     while(1) {
00227         if(net->connect() == 0)break;
00228         printf("Retry Init\n") ;
00229     }
00230 
00231     net->get_ip_address(&a);
00232     printf("Client Addr: %s\n", a.get_ip_address() ? a.get_ip_address() : "None");
00233 
00234     getline((char *)"Server Addr: ", server_addr, sizeof(server_addr)) ;
00235     getline((char *)"Server Port: ", server_port, sizeof(server_port)) ;
00236 
00237     if (socket.open(net) != 0) {
00238         printf("Error! socket.open()\n");
00239     }
00240     port = atoi(server_port);
00241     while (socket.connect(server_addr, port) < 0) {
00242         printf("Unable to connect to (%s) on port (%s)\n", server_addr, server_port);
00243         wait(1.0);
00244     }
00245     printf("TCP Connected\n") ;
00246 
00247     Security(&socket);
00248     return ;
00249 }
00250 
00251 int main(void)
00252 {
00253     DigitalOut myled(LED1);
00254 #define STACK_SIZE 24000
00255     Thread t(net_main, NULL, osPriorityNormal, STACK_SIZE);
00256 
00257     while(1){
00258         myled = 1;
00259         wait(0.5) ;
00260         myled = 0;
00261         wait(0.5) ;
00262     }
00263 }