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

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

WolfSLLのハンドシェイクで受信がないときタイムアウトするよう変更

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 29.4 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 = 30000; // 30,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 }
368 }
369
370 result = tls_io_instance->socket_io_read_byte_count;
371 if (result > sz)
372 {
373 result = sz;
374 }
375
376 if (result > 0)
377 {
378 (void)memcpy(buf, tls_io_instance->socket_io_read_bytes, result);
379 (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);
380 tls_io_instance->socket_io_read_byte_count -= result;
381 if (tls_io_instance->socket_io_read_byte_count > 0)
382 {
383 new_socket_io_read_bytes = (unsigned char*)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count);
384 if (new_socket_io_read_bytes != NULL)
385 {
386 tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
387 }
388 }
389 else
390 {
391 free(tls_io_instance->socket_io_read_bytes);
392 tls_io_instance->socket_io_read_bytes = NULL;
393 }
394 }
395
396 if (tls_io_instance->tlsio_state == TLSIO_STATE_ERROR)
397 {
398 result = WOLFSSL_CBIO_ERR_GENERAL;
399 }
400 else if ( (result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN))
401 {
402 result = WOLFSSL_CBIO_ERR_WANT_READ;
403 }
404 else if ((result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING || tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN))
405 {
406 result = WOLFSSL_CBIO_ERR_CONN_CLOSE;
407 }
408 }
409 else
410 {
411 result = WOLFSSL_CBIO_ERR_GENERAL;
412 }
413 return result;
414}
415
416static int on_io_send(WOLFSSL *ssl, char *buf, int sz, void *context)
417{
418 int result;
419 AZURE_UNREFERENCED_PARAMETER(ssl);
420
421 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
422
423 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)
424 {
425 LogError("Failed sending bytes through underlying IO");
426 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
427 indicate_error(tls_io_instance);
428 result = -1;
429 }
430 else
431 {
432 result = sz;
433 }
434
435 return result;
436}
437
438static int on_handshake_done(WOLFSSL* ssl, void* context)
439{
440 AZURE_UNREFERENCED_PARAMETER(ssl);
441 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
442 if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN) {
443 }
444 else if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
445 {
446 LogInfo("on_handshake_done called when not in IN_HANDSHAKE state");
447 }
448 else
449 {
450 tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
451 indicate_open_complete(tls_io_instance, IO_OPEN_OK);
452 }
453
454 return 0;
455}
456
457static int add_certificate_to_store(TLS_IO_INSTANCE* tls_io_instance)
458{
459 int result;
460 if (tls_io_instance->certificate != NULL)
461 {
462 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);
463 if (res != SSL_SUCCESS)
464 {
465 LogError("wolfSSL_CTX_load_verify_buffer failed");
466 result = MU_FAILURE;
467 }
468 else
469 {
470 result = 0;
471 }
472 }
473 else
474 {
475 result = 0;
476 }
477 return result;
478}
479
480static int x509_wolfssl_add_credentials(WOLFSSL* ssl, char* x509certificate, char* x509privatekey) {
481
482 int result;
483
484 if (wolfSSL_use_certificate_chain_buffer(ssl, (unsigned char*)x509certificate, strlen(x509certificate)) != SSL_SUCCESS)
485 {
486 LogError("unable to load x509 client certificate");
487 result = MU_FAILURE;
488 }
489 else if (wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)x509privatekey, strlen(x509privatekey), SSL_FILETYPE_PEM) != SSL_SUCCESS)
490 {
491 LogError("unable to load x509 client private key");
492 result = MU_FAILURE;
493 }
494#ifdef HAVE_SECURE_RENEGOTIATION
495 else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
496 {
497 LogError("unable to enable secure renegotiation");
498 result = MU_FAILURE;
499 }
500#endif
501 else
502 {
503 result = 0;
504 }
505 return result;
506}
507
508static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
509{
510 wolfSSL_free(tls_io_instance->ssl);
511 tls_io_instance->ssl = NULL;
512}
513
514static int create_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
515{
516 int result;
517 tls_io_instance->ssl = wolfSSL_new(tls_io_instance->ssl_context);
518 if (tls_io_instance->ssl == NULL)
519 {
520 LogError("Failed to add certificates to store");
521 result = MU_FAILURE;
522 }
523 else
524 {
525 tls_io_instance->socket_io_read_bytes = NULL;
526 tls_io_instance->socket_io_read_byte_count = 0;
527 tls_io_instance->on_send_complete = NULL;
528 tls_io_instance->on_send_complete_callback_context = NULL;
529#ifdef INVALID_DEVID
530 tls_io_instance->wolfssl_device_id = INVALID_DEVID;
531#endif
532
533 wolfSSL_set_using_nonblock(tls_io_instance->ssl, 1);
534 wolfSSL_SetHsDoneCb(tls_io_instance->ssl, on_handshake_done, tls_io_instance);
535 wolfSSL_SetIOWriteCtx(tls_io_instance->ssl, tls_io_instance);
536 wolfSSL_SetIOReadCtx(tls_io_instance->ssl, tls_io_instance);
537
538 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
539 result = 0;
540 }
541 return result;
542}
543
544static int prepare_wolfssl_open(TLS_IO_INSTANCE* tls_io_instance)
545{
546 int result;
547 if (add_certificate_to_store(tls_io_instance) != 0)
548 {
549 LogError("Failed to add certificates to store");
550 result = MU_FAILURE;
551 }
552 /*x509 authentication can only be build before underlying connection is realized*/
553 else if ((tls_io_instance->x509certificate != NULL) &&
554 (tls_io_instance->x509privatekey != NULL) &&
555 (x509_wolfssl_add_credentials(tls_io_instance->ssl, tls_io_instance->x509certificate, tls_io_instance->x509privatekey) != 0))
556 {
557 destroy_wolfssl_instance(tls_io_instance);
558 LogError("unable to use x509 authentication");
559 result = MU_FAILURE;
560 }
561#ifdef INVALID_DEVID
562 else if (tls_io_instance->wolfssl_device_id != INVALID_DEVID && wolfSSL_SetDevId(tls_io_instance->ssl, tls_io_instance->wolfssl_device_id) != WOLFSSL_SUCCESS)
563 {
564 LogError("Failure setting device id");
565 result = MU_FAILURE;
566 }
567#endif
568 else
569 {
570 result = 0;
571 }
572 return result;
573}
574
575int tlsio_wolfssl_init(void)
576{
577 (void)wolfSSL_library_init();
578 wolfSSL_load_error_strings();
579
580 return 0;
581}
582
583void tlsio_wolfssl_deinit(void)
584{
585}
586
587CONCRETE_IO_HANDLE tlsio_wolfssl_create(void* io_create_parameters)
588{
589 TLS_IO_INSTANCE* result;
590
591 if (io_create_parameters == NULL)
592 {
593 LogError("NULL io_create_parameters");
594 result = NULL;
595 }
596 else
597 {
598 TLSIO_CONFIG* tls_io_config = io_create_parameters;
599
600 result = (TLS_IO_INSTANCE*)malloc(sizeof(TLS_IO_INSTANCE));
601 if (result == NULL)
602 {
603 LogError("Failed allocating memory for the TLS IO instance.");
604 }
605 else
606 {
607 (void)memset(result, 0, sizeof(TLS_IO_INSTANCE));
608 result->tlsio_state = TLSIO_STATE_NOT_OPEN;
609
610 result->ssl_context = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
611 if (result->ssl_context == NULL)
612 {
613 LogError("Cannot create the wolfSSL context");
614 free(result);
615 result = NULL;
616 }
617 else
618 {
619 // Set the recv and send function on the wolfssl context object
620 wolfSSL_SetIOSend(result->ssl_context, on_io_send);
621 wolfSSL_SetIORecv(result->ssl_context, on_io_recv);
622
623 SOCKETIO_CONFIG socketio_config;
624 const IO_INTERFACE_DESCRIPTION* underlying_io_interface;
625 void* io_interface_parameters;
626
627 if (tls_io_config->underlying_io_interface != NULL)
628 {
629 underlying_io_interface = tls_io_config->underlying_io_interface;
630 io_interface_parameters = tls_io_config->underlying_io_parameters;
631 }
632 else
633 {
634 socketio_config.hostname = tls_io_config->hostname;
635 socketio_config.port = tls_io_config->port;
636 socketio_config.accepted_socket = NULL;
637
638 underlying_io_interface = socketio_get_interface_description();
639 io_interface_parameters = &socketio_config;
640 }
641
642 if (underlying_io_interface == NULL)
643 {
644 LogError("Failed getting socket IO interface description.");
645 wolfSSL_CTX_free(result->ssl_context);
646 free(result);
647 result = NULL;
648 }
649 else
650 {
651 result->socket_io = xio_create(underlying_io_interface, io_interface_parameters);
652 if (result->socket_io == NULL)
653 {
654 LogError("Failure connecting to underlying socket_io");
655 wolfSSL_CTX_free(result->ssl_context);
656 free(result);
657 result = NULL;
658 }
659 else if (create_wolfssl_instance(result) != 0)
660 {
661 LogError("Failure connecting to underlying socket_io");
662 wolfSSL_CTX_free(result->ssl_context);
663 free(result);
664 result = NULL;
665 }
666 }
667 }
668 }
669 }
670
671 return result;
672}
673
674void tlsio_wolfssl_destroy(CONCRETE_IO_HANDLE tls_io)
675{
676 if (tls_io != NULL)
677 {
678 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
679 if (tls_io_instance->socket_io_read_bytes != NULL)
680 {
681 free(tls_io_instance->socket_io_read_bytes);
682 tls_io_instance->socket_io_read_bytes = NULL;
683 }
684 if (tls_io_instance->certificate != NULL)
685 {
686 free(tls_io_instance->certificate);
687 tls_io_instance->certificate = NULL;
688 }
689 if (tls_io_instance->x509certificate != NULL)
690 {
691 free(tls_io_instance->x509certificate);
692 tls_io_instance->x509certificate = NULL;
693 }
694 if (tls_io_instance->x509privatekey != NULL)
695 {
696 free(tls_io_instance->x509privatekey);
697 tls_io_instance->x509privatekey = NULL;
698 }
699 destroy_wolfssl_instance(tls_io_instance);
700
701 wolfSSL_CTX_free(tls_io_instance->ssl_context);
702 tls_io_instance->ssl_context = NULL;
703
704 xio_destroy(tls_io_instance->socket_io);
705 free(tls_io);
706 }
707}
708
709int 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)
710{
711 int result;
712
713 if (tls_io == NULL)
714 {
715 LogError("NULL tls_io instance");
716 result = MU_FAILURE;
717 }
718 else
719 {
720 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
721
722 if (tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN)
723 {
724 LogError("Invalid state encountered.");
725 result = MU_FAILURE;
726 }
727 else
728 {
729 tls_io_instance->on_bytes_received = on_bytes_received;
730 tls_io_instance->on_bytes_received_context = on_bytes_received_context;
731
732 tls_io_instance->on_io_open_complete = on_io_open_complete;
733 tls_io_instance->on_io_open_complete_context = on_io_open_complete_context;
734
735 tls_io_instance->on_io_error = on_io_error;
736 tls_io_instance->on_io_error_context = on_io_error_context;
737
738 tls_io_instance->tlsio_state = TLSIO_STATE_OPENING_UNDERLYING_IO;
739
740 if (prepare_wolfssl_open(tls_io_instance) != 0)
741 {
742 LogError("Cannot create wolfssl instance.");
743 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
744 result = MU_FAILURE;
745 }
746 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)
747 {
748 LogError("Cannot open the underlying IO.");
749 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
750 result = MU_FAILURE;
751 }
752 else
753 {
754 result = 0;
755 }
756 }
757 }
758
759 return result;
760}
761
762int tlsio_wolfssl_close(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
763{
764 int result = 0;
765
766 if (tls_io == NULL)
767 {
768 LogError("NULL tls_io handle.");
769 result = MU_FAILURE;
770 }
771 else
772 {
773 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
774
775 if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) ||
776 (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING))
777 {
778 LogError("Close called while not open.");
779 result = MU_FAILURE;
780 }
781 else
782 {
783 tls_io_instance->tlsio_state = TLSIO_STATE_CLOSING;
784 tls_io_instance->on_io_close_complete = on_io_close_complete;
785 tls_io_instance->on_io_close_complete_context = callback_context;
786
787 if (xio_close(tls_io_instance->socket_io, on_underlying_io_close_complete, tls_io_instance) != 0)
788 {
789 LogError("xio_close failed.");
790 result = MU_FAILURE;
791 }
792 else
793 {
794 result = 0;
795 }
796 }
797 }
798
799 return result;
800}
801
802int tlsio_wolfssl_send(CONCRETE_IO_HANDLE tls_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
803{
804 int result;
805
806 if (tls_io == NULL || buffer == NULL || size == 0)
807 {
808 LogError("Invalid parameter specified tls_io: %p, buffer: %p, size: %ul", tls_io, buffer, (unsigned int)size);
809 result = MU_FAILURE;
810 }
811 else
812 {
813 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
814
815 if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
816 {
817 LogError("send called while not open");
818 result = MU_FAILURE;
819 }
820 else
821 {
822 tls_io_instance->on_send_complete = on_send_complete;
823 tls_io_instance->on_send_complete_callback_context = callback_context;
824
825 int res = wolfSSL_write(tls_io_instance->ssl, buffer, size);
826 if ((res < 0) || ((size_t)res != size)) // Best way I can think of to safely compare an int to a size_t
827 {
828 LogError("Error writing data through WolfSSL");
829 result = MU_FAILURE;
830 }
831 else
832 {
833 result = 0;
834 }
835 tls_io_instance->on_send_complete = NULL;
836 tls_io_instance->on_send_complete_callback_context = NULL;
837 }
838 }
839
840 return result;
841}
842
843void tlsio_wolfssl_dowork(CONCRETE_IO_HANDLE tls_io)
844{
845 if (tls_io == NULL)
846 {
847 LogError("NULL tls_io");
848 }
849 else
850 {
851 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
852
853 if ((tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN) &&
854 (tls_io_instance->tlsio_state != TLSIO_STATE_ERROR))
855 {
856 if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO)
857 decode_ssl_received_bytes(tls_io_instance);
858 xio_dowork(tls_io_instance->socket_io);
859 }
860 }
861}
862
863
864static int process_option(char** destination, const char* name, const char* value)
865{
866 int result;
867 if (*destination != NULL)
868 {
869 free(*destination);
870 *destination = NULL;
871 }
872 if (mallocAndStrcpy_s(destination, value) != 0)
873 {
874 LogError("unable to process option %s",name);
875 result = MU_FAILURE;
876 }
877 else
878 {
879 result = 0;
880 }
881 return result;
882}
883
884int tlsio_wolfssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
885{
886 int result;
887
888 if (tls_io == NULL || optionName == NULL)
889 {
890 LogError("Bad arguments, tls_io = %p, optionName = %p", tls_io, optionName);
891 result = MU_FAILURE;
892 }
893 else
894 {
895 TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
896
897 if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
898 {
899 result = process_option(&tls_io_instance->certificate, optionName, value);
900 }
901 else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
902 {
903 result = process_option(&tls_io_instance->x509certificate, optionName, value);
904 }
905 else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
906 {
907 result = process_option(&tls_io_instance->x509privatekey, optionName, value);
908 }
909#ifdef INVALID_DEVID
910 else if (strcmp(OPTION_WOLFSSL_SET_DEVICE_ID, optionName) == 0)
911 {
912 int device_id = *((int *)value);
913 if (tls_io_instance->ssl != NULL)
914 {
915 if (tls_io_instance->ssl != NULL && wolfSSL_SetDevId(tls_io_instance->ssl, device_id) != WOLFSSL_SUCCESS)
916 {
917 LogError("Failure setting device id on ssl");
918 result = MU_FAILURE;
919 }
920 else
921 {
922 result = 0;
923 }
924 }
925 else
926 {
927 // Save the id till we create the ssl object
928 tls_io_instance->wolfssl_device_id = device_id;
929 result = 0;
930 }
931 }
932#endif
933 else
934 {
935 if (tls_io_instance->socket_io == NULL)
936 {
937 LogError("NULL underlying IO handle");
938 result = MU_FAILURE;
939 }
940 else
941 {
942 result = xio_setoption(tls_io_instance->socket_io, optionName, value);
943 }
944 }
945 }
946
947 return result;
948}
949const IO_INTERFACE_DESCRIPTION* tlsio_wolfssl_get_interface_description(void)
950{
951 return &tlsio_wolfssl_interface_description;
952}
Note: See TracBrowser for help on using the repository browser.