source: azure_iot_hub_riscv/trunk/azure_iot_sdk/c-utility/adapters/tlsio_wolfssl.c@ 453

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

ファイルを追加

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