source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/adapters/tlsio_wolfssl.c@ 464

Last change on this file since 464 was 464, checked in by coas-nagasima, 3 years ago

WolfSSLとAzure IoT SDKを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 31.5 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include <stdlib.h>
5#define WOLFSSL_OPTIONS_IGNORE_SYS
6#include "wolfssl/options.h"
7#include "wolfssl/ssl.h"
8#include "wolfssl/error-ssl.h"
9#include "wolfssl/wolfcrypt/types.h"
10#include <stdio.h>
11#include <stdbool.h>
12#include <string.h>
13#include "azure_c_shared_utility/gballoc.h"
14#include "azure_c_shared_utility/tlsio.h"
15#include "azure_c_shared_utility/tlsio_wolfssl.h"
16#include "azure_c_shared_utility/socketio.h"
17#include "azure_c_shared_utility/crt_abstractions.h"
18#include "azure_c_shared_utility/optimize_size.h"
19#include "azure_c_shared_utility/xlogging.h"
20#include "azure_c_shared_utility/shared_util_options.h"
21
22typedef enum TLSIO_STATE_ENUM_TAG
23{
24 TLSIO_STATE_NOT_OPEN,
25 TLSIO_STATE_OPENING_UNDERLYING_IO,
26 TLSIO_STATE_IN_HANDSHAKE,
27 TLSIO_STATE_OPEN,
28 TLSIO_STATE_CLOSING,
29 TLSIO_STATE_ERROR
30} TLSIO_STATE_ENUM;
31
32typedef struct TLS_IO_INSTANCE_TAG
33{
34 XIO_HANDLE socket_io;
35 ON_BYTES_RECEIVED on_bytes_received;
36 ON_IO_OPEN_COMPLETE on_io_open_complete;
37 ON_IO_CLOSE_COMPLETE on_io_close_complete;
38 ON_IO_ERROR on_io_error;
39 void* on_bytes_received_context;
40 void* on_io_open_complete_context;
41 void* on_io_close_complete_context;
42 void* on_io_error_context;
43 WOLFSSL* ssl;
44 WOLFSSL_CTX* ssl_context;
45 TLSIO_STATE_ENUM tlsio_state;
46 unsigned char* socket_io_read_bytes;
47 size_t socket_io_read_byte_count;
48 ON_SEND_COMPLETE on_send_complete;
49 void* on_send_complete_callback_context;
50 char* certificate;
51 char* x509certificate;
52 char* x509privatekey;
53 int wolfssl_device_id;
54 char* hostname;
55 bool ignore_host_name_check;
56} TLS_IO_INSTANCE;
57
58STATIC_VAR_UNUSED const char* const OPTION_WOLFSSL_SET_DEVICE_ID = "SetDeviceId";
59static const size_t SOCKET_READ_LIMIT = 5;
60
61/*this function will clone an option given by name and value*/
62static void* tlsio_wolfssl_CloneOption(const char* name, const void* value)
63{
64 void* result;
65 if ((name == NULL) || (value == NULL))
66 {
67 LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
68 result = NULL;
69 }
70 else
71 {
72 if (strcmp(name, OPTION_TRUSTED_CERT) == 0)
73 {
74 if (mallocAndStrcpy_s((char**)&result, value) != 0)
75 {
76 LogError("unable to mallocAndStrcpy_s TrustedCerts value");
77 result = NULL;
78 }
79 else
80 {
81 /*return as is*/
82 }
83 }
84 else if (strcmp(name, SU_OPTION_X509_CERT) == 0)
85 {
86 if (mallocAndStrcpy_s((char**)&result, value) != 0)
87 {
88 LogError("unable to mallocAndStrcpy_s x509certificate value");
89 result = NULL;
90 }
91 else
92 {
93 /*return as is*/
94 }
95 }
96 else if (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0)
97 {
98 if (mallocAndStrcpy_s((char**)&result, value) != 0)
99 {
100 LogError("unable to mallocAndStrcpy_s x509privatekey value");
101 result = NULL;
102 }
103 else
104 {
105 /*return as is*/
106 }
107 }
108 #ifdef INVALID_DEVID
109 else if(strcmp(name, OPTION_WOLFSSL_SET_DEVICE_ID) == 0 )
110 {
111 int* value_clone;
112
113 if ((value_clone = malloc(sizeof(int))) == NULL)
114 {
115 LogError("unable to clone device id option");
116 }
117 else
118 {
119 *value_clone = *(int*)value;
120 }
121
122 result = value_clone;
123 }
124 #endif
125 else
126 {
127 LogError("not handled option : %s", name);
128 result = NULL;
129 }
130 }
131 return result;
132}
133
134/*this function destroys an option previously created*/
135static void tlsio_wolfssl_DestroyOption(const char* name, const void* value)
136{
137 /*since all options for this layer are actually string copies., disposing of one is just calling free*/
138 if ((name == NULL) || (value == NULL))
139 {
140 LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
141 }
142 else
143 {
144 if ((strcmp(name, OPTION_TRUSTED_CERT) == 0) ||
145 (strcmp(name, SU_OPTION_X509_CERT) == 0) ||
146 (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0) ||
147 (strcmp(name, OPTION_WOLFSSL_SET_DEVICE_ID) == 0))
148 {
149 free((void*)value);
150 }
151 else
152 {
153 LogError("not handled option : %s", name);
154 }
155 }
156}
157
158static OPTIONHANDLER_HANDLE tlsio_wolfssl_retrieveoptions(CONCRETE_IO_HANDLE tls_io)
159{
160 OPTIONHANDLER_HANDLE result;
161 if (tls_io == NULL)
162 {
163 LogError("NULL tls_io parameter");
164 result = NULL;
165 }
166 else
167 {
168 result = OptionHandler_Create(tlsio_wolfssl_CloneOption, tlsio_wolfssl_DestroyOption, tlsio_wolfssl_setoption);
169 if (result == NULL)
170 {
171 LogError("unable to OptionHandler_Create");
172 /*return as is*/
173 }
174 else
175 {
176 /*this layer cares about the certificates and the x509 credentials*/
177 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
178 if (
179 (tls_io_instance->x509certificate != NULL) &&
180 (OptionHandler_AddOption(result, SU_OPTION_X509_CERT, tls_io_instance->x509certificate) != OPTIONHANDLER_OK)
181 )
182 {
183 LogError("unable to save x509certificate option");
184 OptionHandler_Destroy(result);
185 result = NULL;
186 }
187 else if (
188 (tls_io_instance->x509privatekey != NULL) &&
189 (OptionHandler_AddOption(result, SU_OPTION_X509_PRIVATE_KEY, tls_io_instance->x509privatekey) != OPTIONHANDLER_OK)
190 )
191 {
192 LogError("unable to save x509privatekey option");
193 OptionHandler_Destroy(result);
194 result = NULL;
195 }
196 else if (
197 (tls_io_instance->certificate != NULL) &&
198 (OptionHandler_AddOption(result, OPTION_TRUSTED_CERT, tls_io_instance->certificate) != OPTIONHANDLER_OK)
199 )
200 {
201 LogError("unable to save TrustedCerts option");
202 OptionHandler_Destroy(result);
203 result = NULL;
204 }
205 #ifdef INVALID_DEVID
206 else if (
207 (tls_io_instance->wolfssl_device_id != INVALID_DEVID) &&
208 (OptionHandler_AddOption(result, OPTION_WOLFSSL_SET_DEVICE_ID, &tls_io_instance->wolfssl_device_id) != OPTIONHANDLER_OK)
209 )
210 {
211 LogError("unable to save deviceid option");
212 OptionHandler_Destroy(result);
213 result = NULL;
214 }
215 #endif
216 else
217 {
218 /*all is fine, all interesting options have been saved*/
219 /*return as is*/
220 }
221 }
222 }
223
224 return result;
225}
226
227static const IO_INTERFACE_DESCRIPTION tlsio_wolfssl_interface_description =
228{
229 tlsio_wolfssl_retrieveoptions,
230 tlsio_wolfssl_create,
231 tlsio_wolfssl_destroy,
232 tlsio_wolfssl_open,
233 tlsio_wolfssl_close,
234 tlsio_wolfssl_send,
235 tlsio_wolfssl_dowork,
236 tlsio_wolfssl_setoption
237};
238
239static void indicate_error(TLS_IO_INSTANCE* tls_io_instance)
240{
241 if (tls_io_instance->on_io_error != NULL)
242 {
243 tls_io_instance->on_io_error(tls_io_instance->on_io_error_context);
244 }
245}
246
247static void indicate_open_complete(TLS_IO_INSTANCE* tls_io_instance, IO_OPEN_RESULT open_result)
248{
249 if (tls_io_instance->on_io_open_complete != NULL)
250 {
251 tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, open_result);
252 }
253}
254
255static int decode_ssl_received_bytes(TLS_IO_INSTANCE* tls_io_instance)
256{
257 int result = 0;
258 unsigned char buffer[64];
259
260 int rcv_bytes = 0;
261 do
262 {
263 rcv_bytes = wolfSSL_read(tls_io_instance->ssl, buffer, sizeof(buffer));
264 if (rcv_bytes > 0)
265 {
266 if (tls_io_instance->on_bytes_received != NULL)
267 {
268 tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, buffer, rcv_bytes);
269 }
270 }
271 } while (rcv_bytes > 0);
272 return result;
273}
274
275static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
276{
277 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
278
279 if (open_result != IO_OPEN_OK)
280 {
281 LogError("Underlying IO open failed");
282 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
283 indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
284 }
285 else
286 {
287 int res;
288 tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
289
290 res = wolfSSL_connect(tls_io_instance->ssl);
291 if (res != SSL_SUCCESS)
292 {
293 // Error codes explained in https://www.wolfssl.com/docs/wolfssl-manual/appendix-c/
294 LogError("WolfSSL connect failed (%d)", wolfSSL_get_error(tls_io_instance->ssl, res));
295 indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
296 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
297 }
298 }
299}
300
301static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
302{
303 if (context != NULL)
304 {
305 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
306
307 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);
308 if (new_socket_io_read_bytes == NULL)
309 {
310 LogError("Failed allocating memory for received bytes");
311 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
312 indicate_error(tls_io_instance);
313 }
314 else
315 {
316 tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
317 (void)memcpy(tls_io_instance->socket_io_read_bytes + tls_io_instance->socket_io_read_byte_count, buffer, size);
318 tls_io_instance->socket_io_read_byte_count += size;
319 }
320 }
321 else
322 {
323 LogInfo("Supplied context is NULL on bytes_received");
324 }
325}
326
327static void on_underlying_io_error(void* context)
328{
329 if (context != NULL)
330 {
331 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
332
333 switch (tls_io_instance->tlsio_state)
334 {
335 default:
336 LogError("Unknown TLS IO WolfSSL state: %d", (int)tls_io_instance->tlsio_state);
337 break;
338
339 case TLSIO_STATE_NOT_OPEN:
340 case TLSIO_STATE_ERROR:
341 break;
342
343 case TLSIO_STATE_OPENING_UNDERLYING_IO:
344 case TLSIO_STATE_IN_HANDSHAKE:
345 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
346 indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
347 break;
348
349 case TLSIO_STATE_OPEN:
350 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
351 indicate_error(tls_io_instance);
352 break;
353 }
354 }
355 else
356 {
357 LogInfo("Supplied context is NULL on io_error");
358 }
359}
360
361static void on_underlying_io_close_complete(void* context)
362{
363 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
364
365 if (tls_io_instance->tlsio_state != TLSIO_STATE_CLOSING)
366 {
367 LogError("on_underlying_io_close_complete called when not in CLOSING state");
368 }
369 else
370 {
371 if (tls_io_instance->on_io_close_complete != NULL)
372 {
373 tls_io_instance->on_io_close_complete(tls_io_instance->on_io_close_complete_context);
374 }
375 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
376 }
377}
378
379static int on_io_recv(WOLFSSL *ssl, char *buf, int sz, void *context)
380{
381 int result;
382 if (context != NULL)
383 {
384 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
385 unsigned char* new_socket_io_read_bytes;
386 size_t socket_reads = 0;
387
388 AZURE_UNREFERENCED_PARAMETER(ssl);
389 while (tls_io_instance->socket_io_read_byte_count == 0 && socket_reads < SOCKET_READ_LIMIT)
390 {
391 xio_dowork(tls_io_instance->socket_io);
392 if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
393 {
394 break;
395 }
396 socket_reads++;
397 }
398
399 result = tls_io_instance->socket_io_read_byte_count;
400 if (result > sz)
401 {
402 result = sz;
403 }
404
405 if (result > 0)
406 {
407 (void)memcpy(buf, tls_io_instance->socket_io_read_bytes, result);
408 (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);
409 tls_io_instance->socket_io_read_byte_count -= result;
410 if (tls_io_instance->socket_io_read_byte_count > 0)
411 {
412 new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count);
413 if (new_socket_io_read_bytes != NULL)
414 {
415 tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
416 }
417 }
418 else
419 {
420 free(tls_io_instance->socket_io_read_bytes);
421 tls_io_instance->socket_io_read_bytes = NULL;
422 }
423 }
424
425 if (tls_io_instance->tlsio_state == TLSIO_STATE_ERROR)
426 {
427 result = WOLFSSL_CBIO_ERR_GENERAL;
428 }
429 else if ( (result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN))
430 {
431 result = WOLFSSL_CBIO_ERR_WANT_READ;
432 }
433 else if ((result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING || tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN))
434 {
435 result = WOLFSSL_CBIO_ERR_CONN_CLOSE;
436 }
437 }
438 else
439 {
440 result = WOLFSSL_CBIO_ERR_GENERAL;
441 }
442 return result;
443}
444
445static int on_io_send(WOLFSSL *ssl, char *buf, int sz, void *context)
446{
447 int result;
448 AZURE_UNREFERENCED_PARAMETER(ssl);
449
450 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
451
452 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)
453 {
454 LogError("Failed sending bytes through underlying IO");
455 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
456 indicate_error(tls_io_instance);
457 result = WOLFSSL_CBIO_ERR_GENERAL;
458 }
459 else
460 {
461 result = sz;
462 }
463
464 return result;
465}
466
467static int on_handshake_done(WOLFSSL* ssl, void* context)
468{
469 AZURE_UNREFERENCED_PARAMETER(ssl);
470 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
471 if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
472 {
473 LogInfo("on_handshake_done called when not in IN_HANDSHAKE state");
474 }
475 else
476 {
477 tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
478 indicate_open_complete(tls_io_instance, IO_OPEN_OK);
479 }
480
481 return 0;
482}
483
484static int add_certificate_to_store(TLS_IO_INSTANCE* tls_io_instance)
485{
486 int result;
487 if (tls_io_instance->certificate != NULL)
488 {
489 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);
490 if (res != SSL_SUCCESS)
491 {
492 LogError("wolfSSL_CTX_load_verify_buffer failed");
493 result = MU_FAILURE;
494 }
495 else
496 {
497 result = 0;
498 }
499 }
500 else
501 {
502 result = 0;
503 }
504 return result;
505}
506
507static int x509_wolfssl_add_credentials(WOLFSSL* ssl, char* x509certificate, char* x509privatekey) {
508
509 int result;
510
511 if (wolfSSL_use_certificate_chain_buffer(ssl, (unsigned char*)x509certificate, strlen(x509certificate)) != SSL_SUCCESS)
512 {
513 LogError("unable to load x509 client certificate");
514 result = MU_FAILURE;
515 }
516 else if (wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)x509privatekey, strlen(x509privatekey), SSL_FILETYPE_PEM) != SSL_SUCCESS)
517 {
518 LogError("unable to load x509 client private key");
519 result = MU_FAILURE;
520 }
521#ifdef HAVE_SECURE_RENEGOTIATION
522 else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
523 {
524 LogError("unable to enable secure renegotiation");
525 result = MU_FAILURE;
526 }
527#endif
528 else
529 {
530 result = 0;
531 }
532 return result;
533}
534
535static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
536{
537 wolfSSL_free(tls_io_instance->ssl);
538 tls_io_instance->ssl = NULL;
539}
540
541static int create_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
542{
543 int result;
544 tls_io_instance->ssl = wolfSSL_new(tls_io_instance->ssl_context);
545 if (tls_io_instance->ssl == NULL)
546 {
547 LogError("Failed to add certificates to store");
548 result = MU_FAILURE;
549 }
550 else
551 {
552 tls_io_instance->socket_io_read_bytes = NULL;
553 tls_io_instance->socket_io_read_byte_count = 0;
554 tls_io_instance->on_send_complete = NULL;
555 tls_io_instance->on_send_complete_callback_context = NULL;
556#ifdef INVALID_DEVID
557 tls_io_instance->wolfssl_device_id = INVALID_DEVID;
558#endif
559
560 wolfSSL_set_using_nonblock(tls_io_instance->ssl, 1);
561 wolfSSL_SetHsDoneCb(tls_io_instance->ssl, on_handshake_done, tls_io_instance);
562 wolfSSL_SetIOWriteCtx(tls_io_instance->ssl, tls_io_instance);
563 wolfSSL_SetIOReadCtx(tls_io_instance->ssl, tls_io_instance);
564
565 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
566 result = 0;
567 }
568 return result;
569}
570
571static int enable_domain_check(TLS_IO_INSTANCE* tls_io_instance)
572{
573 int result = 0;
574
575 if (!tls_io_instance->ignore_host_name_check)
576 {
577 if (wolfSSL_check_domain_name(tls_io_instance->ssl, tls_io_instance->hostname) != WOLFSSL_SUCCESS)
578 {
579 result = MU_FAILURE;
580 }
581 }
582
583 return result;
584}
585
586static int prepare_wolfssl_open(TLS_IO_INSTANCE* tls_io_instance)
587{
588 int result;
589
590 if (enable_domain_check(tls_io_instance))
591 {
592 LogError("Failed to configure domain name verification");
593 result = MU_FAILURE;
594 }
595 else if (add_certificate_to_store(tls_io_instance) != 0)
596 {
597 LogError("Failed to add certificates to store");
598 result = MU_FAILURE;
599 }
600 /*x509 authentication can only be build before underlying connection is realized*/
601 else if ((tls_io_instance->x509certificate != NULL) &&
602 (tls_io_instance->x509privatekey != NULL) &&
603 (x509_wolfssl_add_credentials(tls_io_instance->ssl, tls_io_instance->x509certificate, tls_io_instance->x509privatekey) != 0))
604 {
605 destroy_wolfssl_instance(tls_io_instance);
606 LogError("unable to use x509 authentication");
607 result = MU_FAILURE;
608 }
609 else
610 {
611 result = 0;
612 }
613 return result;
614}
615
616int tlsio_wolfssl_init(void)
617{
618 (void)wolfSSL_library_init();
619 wolfSSL_load_error_strings();
620
621 return 0;
622}
623
624void tlsio_wolfssl_deinit(void)
625{
626}
627
628CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters)
629{
630 TLS_IO_INSTANCE* result;
631
632 if (io_create_parameters == NULL)
633 {
634 LogError("NULL io_create_parameters");
635 result = NULL;
636 }
637 else
638 {
639 TLSIO_CONFIG* tls_io_config = io_create_parameters;
640
641 result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
642 if (result == NULL)
643 {
644 LogError("Failed allocating memory for the TLS IO instance.");
645 }
646 else
647 {
648 (void)memset(result, 0, sizeof(TLS_IO_INSTANCE));
649 result->tlsio_state = TLSIO_STATE_NOT_OPEN;
650
651 result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
652 if (result->ssl_context == NULL)
653 {
654 LogError("Cannot create the wolfSSL context");
655 free(result);
656 result = NULL;
657 }
658 else if (mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname) != 0)
659 {
660 LogError("Failed copying the target hostname.");
661 free(result);
662 result = NULL;
663 }
664 else
665 {
666 // Set the recv and send function on the wolfssl context object
667 wolfSSL_SetIOSend(result->ssl_context, on_io_send);
668 wolfSSL_SetIORecv(result->ssl_context, on_io_recv);
669
670 SOCKETIO_CONFIG socketio_config;
671 const IO_INTERFACE_DESCRIPTION* underlying_io_interface;
672 void* io_interface_parameters;
673
674 if (tls_io_config->underlying_io_interface != NULL)
675 {
676 underlying_io_interface = tls_io_config->underlying_io_interface;
677 io_interface_parameters = tls_io_config->underlying_io_parameters;
678 }
679 else
680 {
681 socketio_config.hostname = tls_io_config->hostname;
682 socketio_config.port = tls_io_config->port;
683 socketio_config.accepted_socket = NULL;
684
685 underlying_io_interface = socketio_get_interface_description();
686 io_interface_parameters = &socketio_config;
687 }
688
689 if (underlying_io_interface == NULL)
690 {
691 LogError("Failed getting socket IO interface description.");
692 wolfSSL_CTX_free(result->ssl_context);
693 free(result->hostname);
694 free(result);
695 result = NULL;
696 }
697 else
698 {
699 result->socket_io = xio_create(underlying_io_interface, io_interface_parameters);
700 if (result->socket_io == NULL)
701 {
702 LogError("Failure connecting to underlying socket_io");
703 wolfSSL_CTX_free(result->ssl_context);
704 free(result->hostname);
705 free(result);
706 result = NULL;
707 }
708 else if (create_wolfssl_instance(result) != 0)
709 {
710 LogError("Failure connecting to underlying socket_io");
711 wolfSSL_CTX_free(result->ssl_context);
712 free(result->hostname);
713 free(result);
714 result = NULL;
715 }
716 }
717 }
718 }
719 }
720
721 return result;
722}
723
724void tlsio_wolfssl_destroy(CONCRETE_IO_HANDLE tls_io)
725{
726 if (tls_io != NULL)
727 {
728 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
729 if (tls_io_instance->socket_io_read_bytes != NULL)
730 {
731 free(tls_io_instance->socket_io_read_bytes);
732 tls_io_instance->socket_io_read_bytes = NULL;
733 }
734 if (tls_io_instance->certificate != NULL)
735 {
736 free(tls_io_instance->certificate);
737 tls_io_instance->certificate = NULL;
738 }
739 if (tls_io_instance->x509certificate != NULL)
740 {
741 free(tls_io_instance->x509certificate);
742 tls_io_instance->x509certificate = NULL;
743 }
744 if (tls_io_instance->x509privatekey != NULL)
745 {
746 free(tls_io_instance->x509privatekey);
747 tls_io_instance->x509privatekey = NULL;
748 }
749 destroy_wolfssl_instance(tls_io_instance);
750
751 wolfSSL_CTX_free(tls_io_instance->ssl_context);
752 tls_io_instance->ssl_context = NULL;
753
754 xio_destroy(tls_io_instance->socket_io);
755 free(tls_io_instance->hostname);
756 free(tls_io);
757 }
758}
759
760int 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)
761{
762 int result;
763
764 if (tls_io == NULL)
765 {
766 LogError("NULL tls_io instance");
767 result = MU_FAILURE;
768 }
769 else
770 {
771 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
772
773 if (tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN)
774 {
775 LogError("Invalid state encountered.");
776 result = MU_FAILURE;
777 }
778 else
779 {
780 tls_io_instance->on_bytes_received = on_bytes_received;
781 tls_io_instance->on_bytes_received_context = on_bytes_received_context;
782
783 tls_io_instance->on_io_open_complete = on_io_open_complete;
784 tls_io_instance->on_io_open_complete_context = on_io_open_complete_context;
785
786 tls_io_instance->on_io_error = on_io_error;
787 tls_io_instance->on_io_error_context = on_io_error_context;
788
789 tls_io_instance->tlsio_state = TLSIO_STATE_OPENING_UNDERLYING_IO;
790
791 if (prepare_wolfssl_open(tls_io_instance) != 0)
792 {
793 LogError("Cannot create wolfssl instance.");
794 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
795 result = MU_FAILURE;
796 }
797 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)
798 {
799 LogError("Cannot open the underlying IO.");
800 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
801 result = MU_FAILURE;
802 }
803 else
804 {
805 // The state can get changed in the on_underlying_io_open_complete
806 if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
807 {
808 LogError("Failed to connect to server. The certificates may not be correct.");
809 result = MU_FAILURE;
810 }
811 else
812 {
813 result = 0;
814 }
815 }
816 }
817 }
818
819 return result;
820}
821
822int tlsio_wolfssl_close(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
823{
824 int result = 0;
825
826 if (tls_io == NULL)
827 {
828 LogError("NULL tls_io handle.");
829 result = MU_FAILURE;
830 }
831 else
832 {
833 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
834
835 if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) ||
836 (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING))
837 {
838 LogError("Close called while not open.");
839 result = MU_FAILURE;
840 }
841 else
842 {
843 tls_io_instance->tlsio_state = TLSIO_STATE_CLOSING;
844 tls_io_instance->on_io_close_complete = on_io_close_complete;
845 tls_io_instance->on_io_close_complete_context = callback_context;
846
847 if (xio_close(tls_io_instance->socket_io, on_underlying_io_close_complete, tls_io_instance) != 0)
848 {
849 LogError("xio_close failed.");
850 result = MU_FAILURE;
851 }
852 else
853 {
854 result = 0;
855 }
856 }
857 }
858
859 return result;
860}
861
862int tlsio_wolfssl_send(CONCRETE_IO_HANDLE tls_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
863{
864 int result;
865
866 if (tls_io == NULL || buffer == NULL || size == 0)
867 {
868 LogError("Invalid parameter specified tls_io: %p, buffer: %p, size: %ul", tls_io, buffer, (unsigned int)size);
869 result = MU_FAILURE;
870 }
871 else
872 {
873 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
874
875 if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
876 {
877 LogError("send called while not open");
878 result = MU_FAILURE;
879 }
880 else
881 {
882 tls_io_instance->on_send_complete = on_send_complete;
883 tls_io_instance->on_send_complete_callback_context = callback_context;
884
885 int res = wolfSSL_write(tls_io_instance->ssl, buffer, size);
886 if ((res < 0) || ((size_t)res != size)) // Best way I can think of to safely compare an int to a size_t
887 {
888 LogError("Error writing data through WolfSSL");
889 result = MU_FAILURE;
890 }
891 else
892 {
893 result = 0;
894 }
895 }
896 }
897
898 return result;
899}
900
901void tlsio_wolfssl_dowork(CONCRETE_IO_HANDLE tls_io)
902{
903 if (tls_io == NULL)
904 {
905 LogError("NULL tls_io");
906 }
907 else
908 {
909 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
910
911 if ((tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN) &&
912 (tls_io_instance->tlsio_state != TLSIO_STATE_ERROR))
913 {
914 decode_ssl_received_bytes(tls_io_instance);
915 xio_dowork(tls_io_instance->socket_io);
916 }
917 }
918}
919
920
921static int process_option(char** destination, const char* name, const char* value)
922{
923
924 (void) name;
925
926 int result;
927 if (*destination != NULL)
928 {
929 free(*destination);
930 *destination = NULL;
931 }
932 if (mallocAndStrcpy_s(destination, value) != 0)
933 {
934 LogError("unable to process option %s",name);
935 result = MU_FAILURE;
936 }
937 else
938 {
939 result = 0;
940 }
941 return result;
942}
943
944int tlsio_wolfssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
945{
946 int result;
947
948 if (tls_io == NULL || optionName == NULL)
949 {
950 LogError("Bad arguments, tls_io = %p, optionName = %p", tls_io, optionName);
951 result = MU_FAILURE;
952 }
953 else
954 {
955 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
956
957 if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
958 {
959 result = process_option(&tls_io_instance->certificate, optionName, value);
960 }
961 else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
962 {
963 result = process_option(&tls_io_instance->x509certificate, optionName, value);
964 }
965 else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
966 {
967 result = process_option(&tls_io_instance->x509privatekey, optionName, value);
968 }
969 else if (strcmp(optionName, OPTION_SET_TLS_RENEGOTIATION) == 0)
970 {
971 // No need to do anything for WolfSSL
972 result = 0;
973 }
974#ifdef INVALID_DEVID
975 else if (strcmp(OPTION_WOLFSSL_SET_DEVICE_ID, optionName) == 0)
976 {
977 int device_id = *((int *)value);
978 if (tls_io_instance->ssl != NULL && wolfSSL_SetDevId(tls_io_instance->ssl, device_id) != WOLFSSL_SUCCESS)
979 {
980 LogError("Failure setting device id on ssl");
981 result = MU_FAILURE;
982 }
983 else
984 {
985 // Save the device Id even if ssl object not yet created.
986 tls_io_instance->wolfssl_device_id = device_id;
987 result = 0;
988 }
989 }
990#endif
991 else if (strcmp("ignore_host_name_check", optionName) == 0)
992 {
993 bool* server_name_check = (bool*)value;
994 tls_io_instance->ignore_host_name_check = *server_name_check;
995 result = 0;
996 }
997 else
998 {
999 if (tls_io_instance->socket_io == NULL)
1000 {
1001 LogError("NULL underlying IO handle");
1002 result = MU_FAILURE;
1003 }
1004 else
1005 {
1006 result = xio_setoption(tls_io_instance->socket_io, optionName, value);
1007 }
1008 }
1009 }
1010
1011 return result;
1012}
1013const IO_INTERFACE_DESCRIPTION* tlsio_wolfssl_get_interface_description(void)
1014{
1015 return &tlsio_wolfssl_interface_description;
1016}
Note: See TracBrowser for help on using the repository browser.