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