source: azure_iot_hub/trunk/azure_iothub/c-utility/adapters/tlsio_wolfssl.c

Last change on this file was 394, checked in by coas-nagasima, 5 years ago

ハンドシェイク中に受信できなかった場合、1ms待つよう変更

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