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

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

ビルドが通るよう更新

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