Mark Radbourne / Mbed 2 deprecated FXOS8700CQ_To_Azure_IoT

Dependencies:   azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tlsio_wolfssl.c Source File

tlsio_wolfssl.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #ifdef _CRTDBG_MAP_ALLOC
00006 #include <crtdbg.h>
00007 #endif
00008 
00009 #include "wolfssl/ssl.h"
00010 #include "wolfssl/error-ssl.h"
00011 #include <stdio.h>
00012 #include <stdbool.h>
00013 #include <string.h>
00014 #include "azure_c_shared_utility/tlsio.h"
00015 #include "azure_c_shared_utility/tlsio_wolfssl.h"
00016 #include "azure_c_shared_utility/socketio.h"
00017 #include "azure_c_shared_utility/crt_abstractions.h"
00018 #include "azure_c_shared_utility/xlogging.h"
00019 #include "azure_c_shared_utility/shared_util_options.h"
00020 
00021 
00022 typedef enum TLSIO_STATE_ENUM_TAG
00023 {
00024     TLSIO_STATE_NOT_OPEN,
00025     TLSIO_STATE_OPENING_UNDERLYING_IO,
00026     TLSIO_STATE_IN_HANDSHAKE,
00027     TLSIO_STATE_OPEN,
00028     TLSIO_STATE_CLOSING,
00029     TLSIO_STATE_ERROR
00030 } TLSIO_STATE_ENUM;
00031 
00032 typedef struct TLS_IO_INSTANCE_TAG
00033 {
00034     XIO_HANDLE socket_io;
00035     ON_BYTES_RECEIVED on_bytes_received;
00036     ON_IO_OPEN_COMPLETE on_io_open_complete;
00037     ON_IO_CLOSE_COMPLETE on_io_close_complete;
00038     ON_IO_ERROR on_io_error;
00039     void* on_bytes_received_context;
00040     void* on_io_open_complete_context;
00041     void* on_io_close_complete_context;
00042     void* on_io_error_context;
00043     WOLFSSL* ssl;
00044     WOLFSSL_CTX* ssl_context;
00045     TLSIO_STATE_ENUM tlsio_state;
00046     unsigned char* socket_io_read_bytes;
00047     size_t socket_io_read_byte_count;
00048     ON_SEND_COMPLETE on_send_complete;
00049     void* on_send_complete_callback_context;
00050     char* certificate;
00051     char* x509certificate;
00052     char* x509privatekey;
00053     char* hostname;
00054     int port;
00055 } TLS_IO_INSTANCE;
00056 
00057 /*this function will clone an option given by name and value*/
00058 static void* tlsio_wolfssl_CloneOption(const char* name, const void* value)
00059 {
00060     void* result;
00061     if ((name == NULL) || (value == NULL))
00062     {
00063         LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
00064         result = NULL;
00065     }
00066     else
00067     {
00068         if (strcmp(name, "TrustedCerts") == 0)
00069         {
00070             if (mallocAndStrcpy_s((char**)&result, value) != 0)
00071             {
00072                 LogError("unable to mallocAndStrcpy_s TrustedCerts value");
00073                 result = NULL;
00074             }
00075             else
00076             {
00077                 /*return as is*/
00078             }
00079         }
00080         else if (strcmp(name, SU_OPTION_X509_CERT) == 0)
00081         {
00082             if (mallocAndStrcpy_s((char**)&result, value) != 0)
00083             {
00084                 LogError("unable to mallocAndStrcpy_s x509certificate value");
00085                 result = NULL;
00086             }
00087             else
00088             {
00089                 /*return as is*/
00090             }
00091         }
00092         else if (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0)
00093         {
00094             if (mallocAndStrcpy_s((char**)&result, value) != 0)
00095             {
00096                 LogError("unable to mallocAndStrcpy_s x509privatekey value");
00097                 result = NULL;
00098             }
00099             else
00100             {
00101                 /*return as is*/
00102             }
00103         }
00104         else
00105         {
00106             LogError("not handled option : %s", name);
00107             result = NULL;
00108         }
00109     }
00110     return result;
00111 }
00112 
00113 /*this function destroys an option previously created*/
00114 static void tlsio_wolfssl_DestroyOption(const char* name, const void* value)
00115 {
00116     /*since all options for this layer are actually string copies., disposing of one is just calling free*/
00117     if ((name == NULL) || (value == NULL))
00118     {
00119         LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
00120     }
00121     else
00122     {
00123         if ((strcmp(name, "TrustedCerts") == 0) ||
00124             (strcmp(name, SU_OPTION_X509_CERT) == 0) ||
00125             (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0))
00126         {
00127             free((void*)value);
00128         }
00129         else
00130         {
00131             LogError("not handled option : %s", name);
00132         }
00133     }
00134 }
00135 
00136 static OPTIONHANDLER_HANDLE tlsio_wolfssl_retrieveoptions(CONCRETE_IO_HANDLE tls_io)
00137 {
00138     OPTIONHANDLER_HANDLE result;
00139     (void)tls_io;
00140 
00141     result = OptionHandler_Create(tlsio_wolfssl_CloneOption, tlsio_wolfssl_DestroyOption, tlsio_wolfssl_setoption);
00142     if (result == NULL)
00143     {
00144         /*return as is*/
00145     }
00146     else
00147     {
00148         /*insert here work to add the options to "result" handle*/
00149     }
00150     return result;
00151 }
00152 
00153 static const IO_INTERFACE_DESCRIPTION tlsio_wolfssl_interface_description =
00154 {
00155     tlsio_wolfssl_retrieveoptions,
00156     tlsio_wolfssl_create,
00157     tlsio_wolfssl_destroy,
00158     tlsio_wolfssl_open,
00159     tlsio_wolfssl_close,
00160     tlsio_wolfssl_send,
00161     tlsio_wolfssl_dowork,
00162     tlsio_wolfssl_setoption
00163 };
00164 
00165 static void indicate_error(TLS_IO_INSTANCE* tls_io_instance)
00166 {
00167     if (tls_io_instance->on_io_error != NULL)
00168     {
00169         tls_io_instance->on_io_error(tls_io_instance->on_io_error_context);
00170     }
00171 }
00172 
00173 static void indicate_open_complete(TLS_IO_INSTANCE* tls_io_instance, IO_OPEN_RESULT open_result)
00174 {
00175     if (tls_io_instance->on_io_open_complete != NULL)
00176     {
00177         tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, open_result);
00178     }
00179 }
00180 
00181 static int decode_ssl_received_bytes(TLS_IO_INSTANCE* tls_io_instance)
00182 {
00183     int result = 0;
00184     unsigned char buffer[64];
00185 
00186     int rcv_bytes = 1;
00187     while (rcv_bytes > 0)
00188     {
00189         rcv_bytes = wolfSSL_read(tls_io_instance->ssl, buffer, sizeof(buffer));
00190         if (rcv_bytes > 0)
00191         {
00192             if (tls_io_instance->on_bytes_received != NULL)
00193             {
00194                 tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, buffer, rcv_bytes);
00195             }
00196         }
00197     }
00198 
00199     return result;
00200 }
00201 
00202 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
00203 {
00204     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00205 
00206     if (open_result != IO_OPEN_OK)
00207     {
00208         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
00209         indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
00210     }
00211     else
00212     {
00213         int res;
00214         tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
00215 
00216         res = wolfSSL_connect(tls_io_instance->ssl);
00217         if (res != SSL_SUCCESS)
00218         {
00219             indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
00220             tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
00221         }
00222     }
00223 }
00224 
00225 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
00226 {
00227     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00228 
00229     unsigned char* new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count + size);
00230     if (new_socket_io_read_bytes == NULL)
00231     {
00232         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
00233         indicate_error(tls_io_instance);
00234     }
00235     else
00236     {
00237         tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
00238         (void)memcpy(tls_io_instance->socket_io_read_bytes + tls_io_instance->socket_io_read_byte_count, buffer, size);
00239         tls_io_instance->socket_io_read_byte_count += size;
00240     }
00241 }
00242 
00243 static void on_underlying_io_error(void* context)
00244 {
00245     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00246 
00247     switch (tls_io_instance->tlsio_state)
00248     {
00249     default:
00250     case TLSIO_STATE_NOT_OPEN:
00251     case TLSIO_STATE_ERROR:
00252         break;
00253 
00254     case TLSIO_STATE_OPENING_UNDERLYING_IO:
00255     case TLSIO_STATE_IN_HANDSHAKE:
00256         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
00257         indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
00258         break;
00259 
00260     case TLSIO_STATE_OPEN:
00261         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
00262         indicate_error(tls_io_instance);
00263         break;
00264     }
00265 }
00266 
00267 static void on_underlying_io_close_complete(void* context)
00268 {
00269     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00270 
00271     if (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING)
00272     {
00273         if (tls_io_instance->on_io_close_complete != NULL)
00274         {
00275             tls_io_instance->on_io_close_complete(tls_io_instance->on_io_close_complete_context);
00276         }
00277         tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
00278     }
00279 }
00280 
00281 static int on_io_recv(WOLFSSL *ssl, char *buf, int sz, void *context)
00282 {
00283     int result;
00284     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00285     unsigned char* new_socket_io_read_bytes;
00286 
00287     (void)ssl;
00288     while (tls_io_instance->socket_io_read_byte_count == 0)
00289     {
00290         xio_dowork(tls_io_instance->socket_io);
00291         if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
00292         {
00293             break;
00294         }
00295     }
00296 
00297     result = tls_io_instance->socket_io_read_byte_count;
00298     if (result > sz)
00299     {
00300         result = sz;
00301     }
00302 
00303     if (result > 0)
00304     {
00305         (void)memcpy(buf, tls_io_instance->socket_io_read_bytes, result);
00306         (void)memmove(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_bytes + result, tls_io_instance->socket_io_read_byte_count - result);
00307         tls_io_instance->socket_io_read_byte_count -= result;
00308         if (tls_io_instance->socket_io_read_byte_count > 0)
00309         {
00310             new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count);
00311             if (new_socket_io_read_bytes != NULL)
00312             {
00313                 tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
00314             }
00315         }
00316         else
00317         {
00318             free(tls_io_instance->socket_io_read_bytes);
00319             tls_io_instance->socket_io_read_bytes = NULL;
00320         }
00321     }
00322 
00323     if ((result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN))
00324     {
00325         result = WOLFSSL_CBIO_ERR_WANT_READ;
00326     }
00327     else if ((result == 0) && tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING)
00328     {
00329         result = WOLFSSL_CBIO_ERR_CONN_CLOSE;
00330     }
00331 
00332     return result;
00333 }
00334 
00335 static int on_io_send(WOLFSSL *ssl, char *buf, int sz, void *context)
00336 {
00337     int result;
00338     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00339 
00340     (void)ssl;
00341     if (xio_send(tls_io_instance->socket_io, buf, sz, tls_io_instance->on_send_complete, tls_io_instance->on_send_complete_callback_context) != 0)
00342     {
00343         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
00344         indicate_error(tls_io_instance);
00345         result = 0;
00346     }
00347     else
00348     {
00349         result = sz;
00350     }
00351 
00352     return result;
00353 }
00354 
00355 static int on_handshake_done(WOLFSSL* ssl, void* context)
00356 {
00357     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
00358     (void)ssl;
00359     if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE)
00360     {
00361         tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
00362         indicate_open_complete(tls_io_instance, IO_OPEN_OK);
00363     }
00364 
00365     return 0;
00366 }
00367 
00368 static int add_certificate_to_store(TLS_IO_INSTANCE* tls_io_instance)
00369 {
00370     int result;
00371     if (tls_io_instance->certificate != NULL)
00372     {
00373         int res = wolfSSL_CTX_load_verify_buffer(tls_io_instance->ssl_context, (const unsigned char*)tls_io_instance->certificate, strlen(tls_io_instance->certificate) + 1, SSL_FILETYPE_PEM);
00374         if (res != SSL_SUCCESS)
00375         {
00376             result = __LINE__;
00377         }
00378         else
00379         {
00380             result = 0;
00381         }
00382     }
00383     else
00384     {
00385         result = 0;
00386     }
00387     return result;
00388 }
00389 
00390 static int x509_wolfssl_add_credentials(WOLFSSL* ssl, char* x509certificate, char* x509privatekey) {
00391 
00392     int result;
00393 
00394     if (wolfSSL_use_certificate_buffer(ssl, (unsigned char*)x509certificate, strlen(x509certificate) + 1, SSL_FILETYPE_PEM) != SSL_SUCCESS)
00395     {
00396         LogError("unable to load x509 client certificate");
00397         result = __LINE__;
00398     }
00399     else if (wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)x509privatekey, strlen(x509privatekey) + 1, SSL_FILETYPE_PEM) != SSL_SUCCESS)
00400     {
00401         LogError("unable to load x509 client private key");
00402         result = __LINE__;
00403     }
00404 #ifdef HAVE_SECURE_RENEGOTIATION
00405     else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) {
00406         LogError("unable to enable secure renegotiation");
00407         result = __LINE__;
00408     }
00409 #endif 
00410     else
00411     {
00412         result = 0;
00413     }
00414     return result;
00415 }
00416 
00417 static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
00418 {
00419     wolfSSL_free(tls_io_instance->ssl);
00420 }
00421 
00422 static int create_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
00423 {
00424     int result;
00425 
00426     if (add_certificate_to_store(tls_io_instance) != 0)
00427     {
00428         wolfSSL_CTX_free(tls_io_instance->ssl_context);
00429         result = __LINE__;
00430     }
00431     else
00432     {
00433         tls_io_instance->ssl = wolfSSL_new(tls_io_instance->ssl_context);
00434         if (tls_io_instance->ssl == NULL)
00435         {
00436             wolfSSL_CTX_free(tls_io_instance->ssl_context);
00437             result = __LINE__;
00438         }
00439         /*x509 authentication can only be build before underlying connection is realized*/
00440         else if ((tls_io_instance->x509certificate != NULL) &&
00441             (tls_io_instance->x509privatekey != NULL) &&
00442             (x509_wolfssl_add_credentials(tls_io_instance->ssl, tls_io_instance->x509certificate, tls_io_instance->x509privatekey) != 0))
00443         {
00444             destroy_wolfssl_instance(tls_io_instance);
00445             tls_io_instance->ssl = NULL;
00446             wolfSSL_CTX_free(tls_io_instance->ssl_context);
00447             tls_io_instance->ssl_context = NULL;
00448             LogError("unable to use x509 authentication");
00449             result = __LINE__;
00450         }
00451 
00452         else
00453         {
00454             tls_io_instance->socket_io_read_bytes = NULL;
00455             tls_io_instance->socket_io_read_byte_count = 0;
00456             tls_io_instance->on_send_complete = NULL;
00457             tls_io_instance->on_send_complete_callback_context = NULL;
00458 
00459             wolfSSL_set_using_nonblock(tls_io_instance->ssl, 1);
00460             wolfSSL_SetIOSend(tls_io_instance->ssl_context, on_io_send);
00461             wolfSSL_SetIORecv(tls_io_instance->ssl_context, on_io_recv);
00462             wolfSSL_SetHsDoneCb(tls_io_instance->ssl, on_handshake_done, tls_io_instance);
00463             wolfSSL_SetIOWriteCtx(tls_io_instance->ssl, tls_io_instance);
00464             wolfSSL_SetIOReadCtx(tls_io_instance->ssl, tls_io_instance);
00465 
00466             tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
00467             result = 0;
00468         }
00469     }
00470     return result;
00471 }
00472 
00473 int tlsio_wolfssl_init(void)
00474 {
00475     (void)wolfSSL_library_init();
00476     wolfSSL_load_error_strings();
00477 
00478     return 0;
00479 }
00480 
00481 void tlsio_wolfssl_deinit(void)
00482 {
00483 }
00484 
00485 CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters)
00486 {
00487     TLSIO_CONFIG* tls_io_config = io_create_parameters;
00488     TLS_IO_INSTANCE* result;
00489 
00490     if (tls_io_config == NULL)
00491     {
00492         result = NULL;
00493     }
00494     else
00495     {
00496         result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
00497         if (result != NULL)
00498         {
00499             memset(result, 0, sizeof(TLS_IO_INSTANCE));
00500             mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname);
00501             result->port = tls_io_config->port;
00502 
00503             result->socket_io_read_bytes = 0;
00504             result->socket_io_read_byte_count = 0;
00505             result->socket_io = NULL;
00506 
00507             result->ssl = NULL;
00508             result->ssl_context = NULL;
00509             result->certificate = NULL;
00510             result->x509certificate = NULL;
00511             result->x509privatekey = NULL;
00512 
00513             result->on_bytes_received = NULL;
00514             result->on_bytes_received_context = NULL;
00515 
00516             result->on_io_open_complete = NULL;
00517             result->on_io_open_complete_context = NULL;
00518 
00519             result->on_io_close_complete = NULL;
00520             result->on_io_close_complete_context = NULL;
00521 
00522             result->on_io_error = NULL;
00523             result->on_io_error_context = NULL;
00524 
00525             result->tlsio_state = TLSIO_STATE_NOT_OPEN;
00526 
00527             result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_client_method());
00528             if (result->ssl_context == NULL)
00529             {
00530                 free(result);
00531                 result = NULL;
00532             }
00533             else
00534             {
00535                 const IO_INTERFACE_DESCRIPTION* socket_io_interface = socketio_get_interface_description();
00536                 if (socket_io_interface == NULL)
00537                 {
00538                     wolfSSL_CTX_free(result->ssl_context);
00539                     free(result);
00540                     result = NULL;
00541                 }
00542                 else
00543                 {
00544                     SOCKETIO_CONFIG socketio_config;
00545                     socketio_config.hostname = result->hostname;
00546                     socketio_config.port = result->port;
00547                     socketio_config.accepted_socket = NULL;
00548 
00549                     result->socket_io = xio_create(socket_io_interface, &socketio_config);
00550                     if (result->socket_io == NULL)
00551                     {
00552                         LogError("Failure connecting to underlying socket_io");
00553                         wolfSSL_CTX_free(result->ssl_context);
00554                         free(result);
00555                         result = NULL;
00556                     }
00557                 }
00558             }
00559 
00560 
00561         }
00562     }
00563 
00564     return result;
00565 }
00566 
00567 void tlsio_wolfssl_destroy(CONCRETE_IO_HANDLE tls_io)
00568 {
00569     if (tls_io != NULL)
00570     {
00571         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
00572         if (tls_io_instance->socket_io_read_bytes != NULL)
00573         {
00574             free(tls_io_instance->socket_io_read_bytes);
00575         }
00576 
00577         if (tls_io_instance->certificate != NULL)
00578         {
00579             free(tls_io_instance->certificate);
00580             tls_io_instance->certificate = NULL;
00581         }
00582         if (tls_io_instance->x509certificate != NULL)
00583         {
00584             free(tls_io_instance->x509certificate);
00585             tls_io_instance->x509certificate = NULL;
00586         }
00587         if (tls_io_instance->x509privatekey != NULL)
00588         {
00589             free(tls_io_instance->x509privatekey);
00590             tls_io_instance->x509privatekey = NULL;
00591         }
00592         wolfSSL_CTX_free(tls_io_instance->ssl_context);
00593         xio_destroy(tls_io_instance->socket_io);
00594         free(tls_io);
00595     }
00596 }
00597 
00598 int tlsio_wolfssl_open(CONCRETE_IO_HANDLE tls_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
00599 {
00600     int result;
00601 
00602     if (tls_io == NULL)
00603     {
00604         result = __LINE__;
00605     }
00606     else
00607     {
00608         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
00609 
00610         if (tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN)
00611         {
00612             LogError("Invalid state encountered.");
00613             result = __LINE__;
00614         }
00615         else
00616         {
00617             tls_io_instance->on_bytes_received = on_bytes_received;
00618             tls_io_instance->on_bytes_received_context = on_bytes_received_context;
00619 
00620             tls_io_instance->on_io_open_complete = on_io_open_complete;
00621             tls_io_instance->on_io_open_complete_context = on_io_open_complete_context;
00622 
00623             tls_io_instance->on_io_error = on_io_error;
00624             tls_io_instance->on_io_error_context = on_io_error_context;
00625 
00626             tls_io_instance->tlsio_state = TLSIO_STATE_OPENING_UNDERLYING_IO;
00627 
00628             if (create_wolfssl_instance(tls_io_instance) != 0)
00629             {
00630                 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
00631                 result = __LINE__;
00632             }
00633             else if (xio_open(tls_io_instance->socket_io, on_underlying_io_open_complete, tls_io_instance, on_underlying_io_bytes_received, tls_io_instance, on_underlying_io_error, tls_io_instance) != 0)
00634             {
00635                 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
00636                 result = __LINE__;
00637             }
00638             else
00639             {
00640                 // The state can get changed in the on_underlying_io_open_complete
00641                 if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
00642                 {
00643                     LogError("Failed to connect to server.  The certificates may not be correct.");
00644                     result = __LINE__;
00645                 }
00646                 else
00647                 {
00648                     result = 0;
00649                 }
00650             }
00651         }
00652     }
00653 
00654     return result;
00655 }
00656 
00657 int tlsio_wolfssl_close(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
00658 {
00659     int result = 0;
00660 
00661     if (tls_io == NULL)
00662     {
00663         result = __LINE__;
00664     }
00665     else
00666     {
00667         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
00668 
00669         if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) ||
00670             (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING))
00671         {
00672             result = __LINE__;
00673         }
00674         else
00675         {
00676             tls_io_instance->tlsio_state = TLSIO_STATE_CLOSING;
00677             tls_io_instance->on_io_close_complete = on_io_close_complete;
00678             tls_io_instance->on_io_close_complete_context = callback_context;
00679 
00680             if (xio_close(tls_io_instance->socket_io, on_underlying_io_close_complete, tls_io_instance) != 0)
00681             {
00682                 result = __LINE__;
00683             }
00684             else
00685             {
00686                 destroy_wolfssl_instance(tls_io_instance);
00687                 result = 0;
00688             }
00689         }
00690     }
00691 
00692     return result;
00693 }
00694 
00695 int tlsio_wolfssl_send(CONCRETE_IO_HANDLE tls_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
00696 {
00697     int result;
00698 
00699     if (tls_io == NULL)
00700     {
00701         result = __LINE__;
00702     }
00703     else
00704     {
00705         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
00706 
00707         if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
00708         {
00709             result = __LINE__;
00710         }
00711         else
00712         {
00713             tls_io_instance->on_send_complete = on_send_complete;
00714             tls_io_instance->on_send_complete_callback_context = callback_context;
00715 
00716             int res = wolfSSL_write(tls_io_instance->ssl, buffer, size);
00717             if ((res < 0) || ((size_t)res != size)) // Best way I can think of to safely compare an int to a size_t
00718             {
00719                 result = __LINE__;
00720             }
00721             else
00722             {
00723                 result = 0;
00724             }
00725         }
00726     }
00727 
00728     return result;
00729 }
00730 
00731 void tlsio_wolfssl_dowork(CONCRETE_IO_HANDLE tls_io)
00732 {
00733     if (tls_io != NULL)
00734     {
00735         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
00736 
00737         if ((tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN) &&
00738             (tls_io_instance->tlsio_state != TLSIO_STATE_ERROR))
00739         {
00740             decode_ssl_received_bytes(tls_io_instance);
00741             xio_dowork(tls_io_instance->socket_io);
00742         }
00743     }
00744 }
00745 
00746 const IO_INTERFACE_DESCRIPTION* tlsio_wolfssl_get_interface_description(void)
00747 {
00748     return &tlsio_wolfssl_interface_description;
00749 }
00750 
00751 static int process_option(char** destination, const char* name, const char* value)
00752 {
00753     int result;
00754     if (*destination != NULL)
00755     {
00756         free(*destination);
00757         *destination = NULL;
00758     }
00759     if (mallocAndStrcpy_s(destination, value) != 0)
00760     {
00761         LogError("unable to process option %s",name);
00762         result = __LINE__;
00763     }
00764     else
00765     {
00766         result = 0;
00767     }
00768     return result;
00769 
00770 }
00771 int tlsio_wolfssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
00772 {
00773     int result;
00774 
00775     if (tls_io == NULL || optionName == NULL)
00776     {
00777         result = __LINE__;
00778     }
00779     else
00780     {
00781         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
00782 
00783         if (strcmp("TrustedCerts", optionName) == 0)
00784         {
00785             result  = process_option(&tls_io_instance->certificate, optionName, value);
00786         }
00787         else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
00788         {
00789             result = process_option(&tls_io_instance->x509certificate, optionName, value);
00790         }
00791         else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
00792         {
00793             result = process_option(&tls_io_instance->x509privatekey, optionName, value);
00794         }
00795         else
00796         {
00797             if (tls_io_instance->socket_io == NULL)
00798             {
00799                 result = __LINE__;
00800             }
00801             else
00802             {
00803                 result = xio_setoption(tls_io_instance->socket_io, optionName, value);
00804             }
00805         }
00806     }
00807 
00808     return result;
00809 }