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

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

バージョンを上げたときに失われたAzure IoT SDKの変更部分を適用

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