Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Revision:
19:2e0811512ceb
Parent:
15:956c6d205aa7
Child:
21:b92006c5b9ff
--- a/tlsio_wolfssl.c	Fri Jan 13 18:41:15 2017 -0800
+++ b/tlsio_wolfssl.c	Sat Jan 28 09:35:22 2017 -0800
@@ -2,10 +2,6 @@
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
 #include <stdlib.h>
-#ifdef _CRTDBG_MAP_ALLOC
-#include <crtdbg.h>
-#endif
-
 #include "wolfssl/ssl.h"
 #include "wolfssl/error-ssl.h"
 #include <stdio.h>
@@ -136,17 +132,58 @@
 static OPTIONHANDLER_HANDLE tlsio_wolfssl_retrieveoptions(CONCRETE_IO_HANDLE tls_io)
 {
     OPTIONHANDLER_HANDLE result;
-    (void)tls_io;
-
-    result = OptionHandler_Create(tlsio_wolfssl_CloneOption, tlsio_wolfssl_DestroyOption, tlsio_wolfssl_setoption);
-    if (result == NULL)
+    if (tls_io == NULL)
     {
-        /*return as is*/
+        LogError("NULL tls_io parameter");
+        result = NULL;
     }
     else
     {
-        /*insert here work to add the options to "result" handle*/
+        result = OptionHandler_Create(tlsio_wolfssl_CloneOption, tlsio_wolfssl_DestroyOption, tlsio_wolfssl_setoption);
+        if (result == NULL)
+        {
+            LogError("unable to OptionHandler_Create");
+            /*return as is*/
+        }
+        else
+        {
+            /*this layer cares about the certificates and the x509 credentials*/
+            TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
+            if (
+                (tls_io_instance->x509certificate != NULL) &&
+                (OptionHandler_AddOption(result, SU_OPTION_X509_CERT, tls_io_instance->x509certificate) != 0)
+                )
+            {
+                LogError("unable to save x509certificate option");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else if (
+                (tls_io_instance->x509privatekey != NULL) &&
+                (OptionHandler_AddOption(result, SU_OPTION_X509_PRIVATE_KEY, tls_io_instance->x509privatekey) != 0)
+                )
+            {
+                LogError("unable to save x509privatekey option");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else if (
+                (tls_io_instance->x509privatekey != NULL) &&
+                (OptionHandler_AddOption(result, "TrustedCerts", tls_io_instance->certificate) != 0)
+                )
+            {
+                LogError("unable to save TrustedCerts option");
+                OptionHandler_Destroy(result);
+                result = NULL;
+            }
+            else
+            {
+                /*all is fine, all interesting options have been saved*/
+                /*return as is*/
+            }
+        }
     }
+
     return result;
 }
 
@@ -205,6 +242,7 @@
 
     if (open_result != IO_OPEN_OK)
     {
+        LogError("Underlying IO open failed");
         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
         indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
     }
@@ -216,6 +254,7 @@
         res = wolfSSL_connect(tls_io_instance->ssl);
         if (res != SSL_SUCCESS)
         {
+            LogError("WolfSSL connect failed");
             indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
             tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
         }
@@ -229,6 +268,7 @@
     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);
     if (new_socket_io_read_bytes == NULL)
     {
+        LogError("Failed allocating memory for received bytes");
         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
         indicate_error(tls_io_instance);
     }
@@ -247,6 +287,9 @@
     switch (tls_io_instance->tlsio_state)
     {
     default:
+        LogError("Unknown TLS IO WolfSSL state: %d", (int)tls_io_instance->tlsio_state);
+        break;
+
     case TLSIO_STATE_NOT_OPEN:
     case TLSIO_STATE_ERROR:
         break;
@@ -268,7 +311,11 @@
 {
     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
 
-    if (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING)
+    if (tls_io_instance->tlsio_state != TLSIO_STATE_CLOSING)
+    {
+        LogError("on_underlying_io_close_complete called when not in CLOSING state");
+    }
+    else
     {
         if (tls_io_instance->on_io_close_complete != NULL)
         {
@@ -340,6 +387,7 @@
     (void)ssl;
     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)
     {
+        LogError("Failed sending bytes through underlying IO");
         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
         indicate_error(tls_io_instance);
         result = 0;
@@ -356,7 +404,11 @@
 {
     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
     (void)ssl;
-    if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE)
+    if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
+    {
+        LogInfo("on_handshake_done called when not in IN_HANDSHAKE state");
+    }
+    else
     {
         tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
         indicate_open_complete(tls_io_instance, IO_OPEN_OK);
@@ -373,6 +425,7 @@
         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);
         if (res != SSL_SUCCESS)
         {
+            LogError("wolfSSL_CTX_load_verify_buffer failed");
             result = __LINE__;
         }
         else
@@ -402,7 +455,8 @@
         result = __LINE__;
     }
 #ifdef HAVE_SECURE_RENEGOTIATION
-    else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) {
+    else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
+    {
         LogError("unable to enable secure renegotiation");
         result = __LINE__;
     }
@@ -425,7 +479,7 @@
 
     if (add_certificate_to_store(tls_io_instance) != 0)
     {
-        wolfSSL_CTX_free(tls_io_instance->ssl_context);
+        LogError("Failed to add certificates to store");
         result = __LINE__;
     }
     else
@@ -433,7 +487,7 @@
         tls_io_instance->ssl = wolfSSL_new(tls_io_instance->ssl_context);
         if (tls_io_instance->ssl == NULL)
         {
-            wolfSSL_CTX_free(tls_io_instance->ssl_context);
+            LogError("Failed to add certificates to store");
             result = __LINE__;
         }
         /*x509 authentication can only be build before underlying connection is realized*/
@@ -442,13 +496,9 @@
             (x509_wolfssl_add_credentials(tls_io_instance->ssl, tls_io_instance->x509certificate, tls_io_instance->x509privatekey) != 0))
         {
             destroy_wolfssl_instance(tls_io_instance);
-            tls_io_instance->ssl = NULL;
-            wolfSSL_CTX_free(tls_io_instance->ssl_context);
-            tls_io_instance->ssl_context = NULL;
             LogError("unable to use x509 authentication");
             result = __LINE__;
         }
-
         else
         {
             tls_io_instance->socket_io_read_bytes = NULL;
@@ -467,6 +517,7 @@
             result = 0;
         }
     }
+
     return result;
 }
 
@@ -484,80 +535,91 @@
 
 CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters)
 {
-    TLSIO_CONFIG* tls_io_config = io_create_parameters;
     TLS_IO_INSTANCE* result;
 
-    if (tls_io_config == NULL)
+    if (io_create_parameters == NULL)
     {
+        LogError("NULL io_create_parameters");
         result = NULL;
     }
     else
     {
+        TLSIO_CONFIG* tls_io_config = io_create_parameters;
+
         result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
         if (result != NULL)
         {
             memset(result, 0, sizeof(TLS_IO_INSTANCE));
-            mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname);
-            result->port = tls_io_config->port;
-
-            result->socket_io_read_bytes = 0;
-            result->socket_io_read_byte_count = 0;
-            result->socket_io = NULL;
-
-            result->ssl = NULL;
-            result->ssl_context = NULL;
-            result->certificate = NULL;
-            result->x509certificate = NULL;
-            result->x509privatekey = NULL;
-
-            result->on_bytes_received = NULL;
-            result->on_bytes_received_context = NULL;
-
-            result->on_io_open_complete = NULL;
-            result->on_io_open_complete_context = NULL;
-
-            result->on_io_close_complete = NULL;
-            result->on_io_close_complete_context = NULL;
-
-            result->on_io_error = NULL;
-            result->on_io_error_context = NULL;
-
-            result->tlsio_state = TLSIO_STATE_NOT_OPEN;
-
-            result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_client_method());
-            if (result->ssl_context == NULL)
+            if (mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname) != 0)
             {
+                LogError("Cannot copy the hostname");
                 free(result);
                 result = NULL;
             }
             else
             {
-                const IO_INTERFACE_DESCRIPTION* socket_io_interface = socketio_get_interface_description();
-                if (socket_io_interface == NULL)
+                result->port = tls_io_config->port;
+
+                result->socket_io_read_bytes = 0;
+                result->socket_io_read_byte_count = 0;
+                result->socket_io = NULL;
+
+                result->ssl = NULL;
+                result->certificate = NULL;
+                result->x509certificate = NULL;
+                result->x509privatekey = NULL;
+
+                result->on_bytes_received = NULL;
+                result->on_bytes_received_context = NULL;
+
+                result->on_io_open_complete = NULL;
+                result->on_io_open_complete_context = NULL;
+
+                result->on_io_close_complete = NULL;
+                result->on_io_close_complete_context = NULL;
+
+                result->on_io_error = NULL;
+                result->on_io_error_context = NULL;
+
+                result->tlsio_state = TLSIO_STATE_NOT_OPEN;
+
+                result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_client_method());
+                if (result->ssl_context == NULL)
                 {
-                    wolfSSL_CTX_free(result->ssl_context);
+                    LogError("Cannot create the wolfSSL context");
+                    free(result->hostname);
                     free(result);
                     result = NULL;
                 }
                 else
                 {
-                    SOCKETIO_CONFIG socketio_config;
-                    socketio_config.hostname = result->hostname;
-                    socketio_config.port = result->port;
-                    socketio_config.accepted_socket = NULL;
-
-                    result->socket_io = xio_create(socket_io_interface, &socketio_config);
-                    if (result->socket_io == NULL)
+                    const IO_INTERFACE_DESCRIPTION* socket_io_interface = socketio_get_interface_description();
+                    if (socket_io_interface == NULL)
                     {
-                        LogError("Failure connecting to underlying socket_io");
                         wolfSSL_CTX_free(result->ssl_context);
+                        free(result->hostname);
                         free(result);
                         result = NULL;
                     }
+                    else
+                    {
+                        SOCKETIO_CONFIG socketio_config;
+                        socketio_config.hostname = result->hostname;
+                        socketio_config.port = result->port;
+                        socketio_config.accepted_socket = NULL;
+
+                        result->socket_io = xio_create(socket_io_interface, &socketio_config);
+                        if (result->socket_io == NULL)
+                        {
+                            LogError("Failure connecting to underlying socket_io");
+                            wolfSSL_CTX_free(result->ssl_context);
+                            free(result->hostname);
+                            free(result);
+                            result = NULL;
+                        }
+                    }
                 }
             }
-
-
         }
     }
 
@@ -577,18 +639,20 @@
         if (tls_io_instance->certificate != NULL)
         {
             free(tls_io_instance->certificate);
-            tls_io_instance->certificate = NULL;
         }
         if (tls_io_instance->x509certificate != NULL)
         {
             free(tls_io_instance->x509certificate);
-            tls_io_instance->x509certificate = NULL;
         }
         if (tls_io_instance->x509privatekey != NULL)
         {
             free(tls_io_instance->x509privatekey);
-            tls_io_instance->x509privatekey = NULL;
         }
+        if (tls_io_instance->hostname != NULL)
+        {
+            free(tls_io_instance->hostname);
+        }
+
         wolfSSL_CTX_free(tls_io_instance->ssl_context);
         xio_destroy(tls_io_instance->socket_io);
         free(tls_io);
@@ -601,6 +665,7 @@
 
     if (tls_io == NULL)
     {
+        LogError("NULL tls_io instance");
         result = __LINE__;
     }
     else
@@ -627,11 +692,13 @@
 
             if (create_wolfssl_instance(tls_io_instance) != 0)
             {
+                LogError("Cannot create wolfssl instance.");
                 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
                 result = __LINE__;
             }
             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)
             {
+                LogError("Cannot open the underlying IO.");
                 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
                 result = __LINE__;
             }
@@ -660,6 +727,7 @@
 
     if (tls_io == NULL)
     {
+        LogError("NULL tls_io handle.");
         result = __LINE__;
     }
     else
@@ -669,6 +737,7 @@
         if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) ||
             (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING))
         {
+            LogError("Close called while not open.");
             result = __LINE__;
         }
         else
@@ -679,6 +748,7 @@
 
             if (xio_close(tls_io_instance->socket_io, on_underlying_io_close_complete, tls_io_instance) != 0)
             {
+                LogError("xio_close failed.");
                 result = __LINE__;
             }
             else
@@ -698,6 +768,7 @@
 
     if (tls_io == NULL)
     {
+        LogError("NULL tls_io handle");
         result = __LINE__;
     }
     else
@@ -706,6 +777,7 @@
 
         if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
         {
+            LogError("send called while not open");
             result = __LINE__;
         }
         else
@@ -716,6 +788,7 @@
             int res = wolfSSL_write(tls_io_instance->ssl, buffer, size);
             if ((res < 0) || ((size_t)res != size)) // Best way I can think of to safely compare an int to a size_t
             {
+                LogError("Error writing data through WolfSSL");
                 result = __LINE__;
             }
             else
@@ -730,7 +803,11 @@
 
 void tlsio_wolfssl_dowork(CONCRETE_IO_HANDLE tls_io)
 {
-    if (tls_io != NULL)
+    if (tls_io == NULL)
+    {
+        LogError("NULL tls_io");
+    }
+    else
     {
         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
 
@@ -766,14 +843,15 @@
         result = 0;
     }
     return result;
+}
 
-}
 int tlsio_wolfssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
 {
     int result;
 
     if (tls_io == NULL || optionName == NULL)
     {
+        LogError("Bad arguments, tls_io = %p, optionName = %p", tls_io, optionName);
         result = __LINE__;
     }
     else
@@ -796,6 +874,7 @@
         {
             if (tls_io_instance->socket_io == NULL)
             {
+                LogError("NULL underlying IO handle");
                 result = __LINE__;
             }
             else