Mark Radbourne / Mbed 2 deprecated iothub_client_sample_amqp

Dependencies:   EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed

Fork of iothub_client_sample_amqp by Azure IoT

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