source: azure_iot_hub_mbedtls/trunk/azure_iothub/c-utility/adapters/tlsio_mbedtls.c@ 398

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

mbedTLS版Azure IoT Hub接続サンプルのソースコードを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 33.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#include <stdio.h>
6#include <stdint.h>
7#include <stdbool.h>
8#include <string.h>
9
10#include "mbedtls/config.h"
11#include "mbedtls/debug.h"
12#include "mbedtls/ssl.h"
13#include "mbedtls/entropy.h"
14#include "mbedtls/ctr_drbg.h"
15#include "mbedtls/error.h"
16#include "mbedtls/certs.h"
17#include "mbedtls/entropy_poll.h"
18
19#include "azure_c_shared_utility/gballoc.h"
20#include "azure_c_shared_utility/optimize_size.h"
21#include "azure_c_shared_utility/tlsio.h"
22#include "azure_c_shared_utility/tlsio_mbedtls.h"
23#include "azure_c_shared_utility/socketio.h"
24#include "azure_c_shared_utility/crt_abstractions.h"
25#include "azure_c_shared_utility/shared_util_options.h"
26#include "azure_c_shared_utility/threadapi.h"
27
28static const char *const OPTION_UNDERLYING_IO_OPTIONS = "underlying_io_options";
29
30#define HANDSHAKE_TIMEOUT_MS 5000
31#define HANDSHAKE_WAIT_INTERVAL_MS 10
32
33typedef enum TLSIO_STATE_ENUM_TAG
34{
35 TLSIO_STATE_NOT_OPEN,
36 TLSIO_STATE_OPENING_UNDERLYING_IO,
37 TLSIO_STATE_IN_HANDSHAKE,
38 TLSIO_STATE_OPEN,
39 TLSIO_STATE_CLOSING,
40 TLSIO_STATE_ERROR
41} TLSIO_STATE_ENUM;
42
43typedef struct TLS_IO_INSTANCE_TAG
44{
45 XIO_HANDLE socket_io;
46 ON_BYTES_RECEIVED on_bytes_received;
47 ON_IO_OPEN_COMPLETE on_io_open_complete;
48 ON_IO_CLOSE_COMPLETE on_io_close_complete;
49 ON_IO_ERROR on_io_error;
50 void *on_bytes_received_context;
51 void *on_io_open_complete_context;
52 void *on_io_close_complete_context;
53 void *on_io_error_context;
54 TLSIO_STATE_ENUM tlsio_state;
55 unsigned char *socket_io_read_bytes;
56 size_t socket_io_read_byte_count;
57 ON_SEND_COMPLETE on_send_complete;
58 void *on_send_complete_callback_context;
59
60 mbedtls_entropy_context entropy;
61 mbedtls_ctr_drbg_context ctr_drbg;
62 mbedtls_ssl_context ssl;
63 mbedtls_ssl_config config;
64 mbedtls_x509_crt trusted_certificates_parsed;
65 mbedtls_ssl_session ssn;
66 char *trusted_certificates;
67
68 char *hostname;
69 mbedtls_x509_crt owncert;
70 mbedtls_pk_context pKey;
71
72 char* x509_certificate;
73 char* x509_private_key;
74
75 int tls_status;
76} TLS_IO_INSTANCE;
77
78typedef enum TLS_STATE_TAG
79{
80 TLS_STATE_NOT_INITIALIZED,
81 TLS_STATE_INITIALIZED,
82 TLS_STATE_CLOSING,
83} TLS_STATE;
84
85static void indicate_error(TLS_IO_INSTANCE *tls_io_instance)
86{
87 if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) || (tls_io_instance->tlsio_state == TLSIO_STATE_ERROR))
88 {
89 return;
90 }
91 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
92 if (tls_io_instance->on_io_error != NULL)
93 {
94 tls_io_instance->on_io_error(tls_io_instance->on_io_error_context);
95 }
96}
97
98static void indicate_open_complete(TLS_IO_INSTANCE *tls_io_instance, IO_OPEN_RESULT open_result)
99{
100 if (tls_io_instance->on_io_open_complete != NULL)
101 {
102 tls_io_instance->on_io_open_complete(tls_io_instance->on_io_open_complete_context, open_result);
103 }
104}
105
106static int decode_ssl_received_bytes(TLS_IO_INSTANCE *tls_io_instance)
107{
108 int result = 0;
109 unsigned char buffer[64];
110 int rcv_bytes = 1;
111
112 while (rcv_bytes > 0)
113 {
114 rcv_bytes = mbedtls_ssl_read(&tls_io_instance->ssl, buffer, sizeof(buffer));
115 if (rcv_bytes > 0)
116 {
117 if (tls_io_instance->on_bytes_received != NULL)
118 {
119 tls_io_instance->on_bytes_received(tls_io_instance->on_bytes_received_context, buffer, rcv_bytes);
120 }
121 }
122 }
123
124 return result;
125}
126
127static void on_underlying_io_open_complete(void *context, IO_OPEN_RESULT open_result)
128{
129 if (context == NULL)
130 {
131 LogError("Invalid context NULL value passed");
132 }
133 else
134 {
135 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)context;
136 int result = 0;
137
138 if (open_result != IO_OPEN_OK)
139 {
140 xio_close(tls_io_instance->socket_io, NULL, NULL);
141 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
142 indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
143 }
144 else
145 {
146 tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
147
148 do
149 {
150 result = mbedtls_ssl_handshake(&tls_io_instance->ssl);
151 } while (result == MBEDTLS_ERR_SSL_WANT_READ || result == MBEDTLS_ERR_SSL_WANT_WRITE);
152
153 if (result == 0)
154 {
155 tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
156 indicate_open_complete(tls_io_instance, IO_OPEN_OK);
157 }
158 else
159 {
160 xio_close(tls_io_instance->socket_io, NULL, NULL);
161 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
162 indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
163 }
164 }
165 }
166}
167
168static void on_underlying_io_bytes_received(void *context, const unsigned char *buffer, size_t size)
169{
170 if (context != NULL)
171 {
172 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)context;
173
174 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);
175
176 if (new_socket_io_read_bytes == NULL)
177 {
178 tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
179 indicate_error(tls_io_instance);
180 }
181 else
182 {
183 tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
184 (void)memcpy(tls_io_instance->socket_io_read_bytes + tls_io_instance->socket_io_read_byte_count, buffer, size);
185 tls_io_instance->socket_io_read_byte_count += size;
186 }
187 }
188 else
189 {
190 LogError("NULL value passed in context");
191 }
192}
193
194static void on_underlying_io_error(void *context)
195{
196 if (context == NULL)
197 {
198 LogError("Invalid context NULL value passed");
199 }
200 else
201 {
202 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)context;
203
204 switch (tls_io_instance->tlsio_state)
205 {
206 default:
207 case TLSIO_STATE_NOT_OPEN:
208 case TLSIO_STATE_ERROR:
209 break;
210
211 case TLSIO_STATE_OPENING_UNDERLYING_IO:
212 case TLSIO_STATE_IN_HANDSHAKE:
213 // Existing socket impls are all synchronous close, and this
214 // adapter does not yet support async close.
215 xio_close(tls_io_instance->socket_io, NULL, NULL);
216 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
217 indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
218 break;
219
220 case TLSIO_STATE_OPEN:
221 indicate_error(tls_io_instance);
222 break;
223 }
224 }
225}
226
227static void on_underlying_io_close_complete_during_close(void *context)
228{
229 if (context == NULL)
230 {
231 LogError("NULL value passed in context");
232 }
233 else
234 {
235 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)context;
236
237 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
238
239 if (tls_io_instance->on_io_close_complete != NULL)
240 {
241 tls_io_instance->on_io_close_complete(tls_io_instance->on_io_close_complete_context);
242 }
243 }
244}
245
246static int on_io_recv(void *context, unsigned char *buf, size_t sz)
247{
248 int result;
249 if (context == NULL)
250 {
251 LogError("Invalid context NULL value passed");
252 result = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
253 }
254 else
255 {
256 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)context;
257 unsigned char *new_socket_io_read_bytes;
258 int pending = 0;
259
260 while (tls_io_instance->socket_io_read_byte_count == 0)
261 {
262 xio_dowork(tls_io_instance->socket_io);
263
264 if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN)
265 {
266 break;
267 }
268 else if (tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN ||
269 tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING ||
270 tls_io_instance->tlsio_state == TLSIO_STATE_ERROR)
271 {
272 // Underlying io error, exit.
273 return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
274 }
275 else
276 {
277 // Handkshake
278 if (tls_io_instance->socket_io_read_byte_count == 0)
279 {
280 if (pending++ >= HANDSHAKE_TIMEOUT_MS / HANDSHAKE_WAIT_INTERVAL_MS)
281 {
282 // The connection is close from server side and no response.
283 LogError("Tlsio_Failure: encountered unknow connection issue, the connection will be restarted.");
284 indicate_error(tls_io_instance);
285 return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
286 }
287 ThreadAPI_Sleep(HANDSHAKE_WAIT_INTERVAL_MS);
288 }
289 }
290 }
291
292 result = tls_io_instance->socket_io_read_byte_count;
293 if (result > (int)sz)
294 {
295 result = sz;
296 }
297
298 if (result > 0)
299 {
300 (void)memcpy((void *)buf, tls_io_instance->socket_io_read_bytes, result);
301 (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);
302 tls_io_instance->socket_io_read_byte_count -= result;
303 if (tls_io_instance->socket_io_read_byte_count > 0)
304 {
305 new_socket_io_read_bytes = (unsigned char *)realloc(tls_io_instance->socket_io_read_bytes, tls_io_instance->socket_io_read_byte_count);
306 if (new_socket_io_read_bytes != NULL)
307 {
308 tls_io_instance->socket_io_read_bytes = new_socket_io_read_bytes;
309 }
310 }
311 else
312 {
313 free(tls_io_instance->socket_io_read_bytes);
314 tls_io_instance->socket_io_read_bytes = NULL;
315 }
316 }
317
318 if ((result == 0) && (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN))
319 {
320 result = MBEDTLS_ERR_SSL_WANT_READ;
321 }
322 }
323 return result;
324}
325
326static int on_io_send(void *context, const unsigned char *buf, size_t sz)
327{
328 int result;
329 if (context == NULL)
330 {
331 LogError("Invalid context NULL value passed");
332 result = 0;
333 }
334 else
335 {
336 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)context;
337
338 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)
339 {
340 indicate_error(tls_io_instance);
341 result = -1;
342 }
343 else
344 {
345 result = sz;
346 }
347 }
348 return result;
349}
350
351static int tlsio_entropy_poll(void *v, unsigned char *output, size_t len, size_t *olen)
352{
353 (void)v;
354 int result = 0;
355 srand((unsigned int)time(NULL));
356 for (uint16_t i = 0; i < len; i++)
357 {
358 output[i] = rand() % 256;
359 }
360 *olen = len;
361 return result;
362}
363
364// Un-initialize mbedTLS
365static void mbedtls_uninit(TLS_IO_INSTANCE *tls_io_instance)
366{
367 if (tls_io_instance->tls_status != TLS_STATE_NOT_INITIALIZED)
368 {
369 // mbedTLS cleanup...
370 mbedtls_ssl_close_notify(&tls_io_instance->ssl);
371 mbedtls_ssl_free(&tls_io_instance->ssl);
372 mbedtls_ssl_config_free(&tls_io_instance->config);
373 mbedtls_x509_crt_free(&tls_io_instance->trusted_certificates_parsed);
374 mbedtls_ctr_drbg_free(&tls_io_instance->ctr_drbg);
375 mbedtls_entropy_free(&tls_io_instance->entropy);
376
377 tls_io_instance->tls_status = TLS_STATE_NOT_INITIALIZED;
378 }
379 else
380 {
381 LogError("Uninitialzing when not previously initialized");
382 }
383}
384
385static void mbedtls_init(TLS_IO_INSTANCE *tls_io_instance)
386{
387 const char* pers = "azure_iot_client";
388 if (tls_io_instance->tls_status != TLS_STATE_INITIALIZED)
389 {
390 if (tls_io_instance->tls_status == TLS_STATE_CLOSING)
391 {
392 // The underlying connection has been closed, so here un-initialize first
393 mbedtls_uninit(tls_io_instance);
394 }
395
396 // mbedTLS initialize...
397 mbedtls_x509_crt_init(&tls_io_instance->trusted_certificates_parsed);
398
399 mbedtls_entropy_init(&tls_io_instance->entropy);
400 // Add a weak entropy source here,avoid some platform doesn't have strong / hardware entropy
401 mbedtls_entropy_add_source(&tls_io_instance->entropy, tlsio_entropy_poll, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_WEAK);
402
403 mbedtls_ctr_drbg_init(&tls_io_instance->ctr_drbg);
404 mbedtls_ctr_drbg_seed(&tls_io_instance->ctr_drbg, mbedtls_entropy_func, &tls_io_instance->entropy, (const unsigned char *)pers, strlen(pers));
405
406 mbedtls_ssl_config_init(&tls_io_instance->config);
407 mbedtls_ssl_config_defaults(&tls_io_instance->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
408 mbedtls_ssl_conf_rng(&tls_io_instance->config, mbedtls_ctr_drbg_random, &tls_io_instance->ctr_drbg);
409 mbedtls_ssl_conf_authmode(&tls_io_instance->config, MBEDTLS_SSL_VERIFY_REQUIRED);
410 mbedtls_ssl_conf_min_version(&tls_io_instance->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); // v1.2
411#if defined(MBEDTLS_SSL_RENEGOTIATION)
412 mbedtls_ssl_conf_renegotiation(&tls_io_instance->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED);
413#endif
414
415 mbedtls_ssl_init(&tls_io_instance->ssl);
416 mbedtls_ssl_set_bio(&tls_io_instance->ssl, tls_io_instance, on_io_send, on_io_recv, NULL);
417 mbedtls_ssl_set_hostname(&tls_io_instance->ssl, tls_io_instance->hostname);
418
419 mbedtls_ssl_session_init(&tls_io_instance->ssn);
420
421 mbedtls_ssl_set_session(&tls_io_instance->ssl, &tls_io_instance->ssn);
422 mbedtls_ssl_setup(&tls_io_instance->ssl, &tls_io_instance->config);
423
424 tls_io_instance->tls_status = TLS_STATE_INITIALIZED;
425 }
426}
427
428CONCRETE_IO_HANDLE tlsio_mbedtls_create(void *io_create_parameters)
429{
430 TLSIO_CONFIG *tls_io_config = (TLSIO_CONFIG *)io_create_parameters;
431 TLS_IO_INSTANCE *result;
432
433 if (tls_io_config == NULL)
434 {
435 LogError("NULL tls_io_config");
436 result = NULL;
437 }
438 else
439 {
440 /* Codes_SRS_TLSIO_MBED_OS5_TLS_99_006: [ The tlsio_mbedtls_create shall return NULL if allocating memory for TLS_IO_INSTANCE failed. ]*/
441 result = calloc(1, sizeof(TLS_IO_INSTANCE));
442 if (result != NULL)
443 {
444 SOCKETIO_CONFIG socketio_config;
445 const IO_INTERFACE_DESCRIPTION *underlying_io_interface;
446 void *io_interface_parameters;
447
448 if (tls_io_config->underlying_io_interface != NULL)
449 {
450 underlying_io_interface = tls_io_config->underlying_io_interface;
451 io_interface_parameters = tls_io_config->underlying_io_parameters;
452 }
453 else
454 {
455 socketio_config.hostname = tls_io_config->hostname;
456 socketio_config.port = tls_io_config->port;
457 socketio_config.accepted_socket = NULL;
458 underlying_io_interface = socketio_get_interface_description();
459 io_interface_parameters = &socketio_config;
460 }
461
462 if (underlying_io_interface == NULL)
463 {
464 free(result);
465 result = NULL;
466 LogError("Failed getting socket IO interface description.");
467 }
468 else
469 {
470 if (mallocAndStrcpy_s((char **)&result->hostname, tls_io_config->hostname) != 0)
471 {
472 free(result);
473 result = NULL;
474 LogError("Failure allocating hostname.");
475 }
476 else if ((result->socket_io = xio_create(underlying_io_interface, io_interface_parameters)) == NULL)
477 {
478 LogError("socket xio create failed");
479 free(result->hostname);
480 free(result);
481 result = NULL;
482 }
483 else
484 {
485 result->tls_status = TLS_STATE_NOT_INITIALIZED;
486 mbedtls_init((void*)result);
487
488 result->tlsio_state = TLSIO_STATE_NOT_OPEN;
489 }
490 }
491 }
492 else
493 {
494 LogError("Failure allocating TLS object");
495 }
496 }
497
498 return result;
499}
500
501void tlsio_mbedtls_destroy(CONCRETE_IO_HANDLE tls_io)
502{
503 if (tls_io != NULL)
504 {
505 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
506
507 mbedtls_uninit(tls_io_instance);
508
509 xio_close(tls_io_instance->socket_io, NULL, NULL);
510
511 if (tls_io_instance->socket_io_read_bytes != NULL)
512 {
513 free(tls_io_instance->socket_io_read_bytes);
514 tls_io_instance->socket_io_read_bytes = NULL;
515 }
516 xio_destroy(tls_io_instance->socket_io);
517 if (tls_io_instance->hostname != NULL)
518 {
519 free(tls_io_instance->hostname);
520 tls_io_instance->hostname = NULL;
521 }
522 if (tls_io_instance->trusted_certificates != NULL)
523 {
524 free(tls_io_instance->trusted_certificates);
525 tls_io_instance->trusted_certificates = NULL;
526 }
527 if (tls_io_instance->x509_certificate != NULL)
528 {
529 free(tls_io_instance->x509_certificate);
530 tls_io_instance->x509_certificate = NULL;
531 }
532 if (tls_io_instance->x509_private_key != NULL)
533 {
534 free(tls_io_instance->x509_private_key);
535 tls_io_instance->x509_private_key = NULL;
536 }
537 free(tls_io);
538 }
539}
540
541int tlsio_mbedtls_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)
542{
543 int result = 0;
544
545 if (tls_io == NULL)
546 {
547 LogError("Invalid parameter specified tls_io: NULL");
548 result = MU_FAILURE;
549 }
550 else
551 {
552 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
553
554 if (tls_io_instance->tlsio_state != TLSIO_STATE_NOT_OPEN)
555 {
556 LogError("IO should not be open: %d", tls_io_instance->tlsio_state);
557 result = MU_FAILURE;
558 }
559 else
560 {
561
562 tls_io_instance->on_bytes_received = on_bytes_received;
563 tls_io_instance->on_bytes_received_context = on_bytes_received_context;
564
565 tls_io_instance->on_io_open_complete = on_io_open_complete;
566 tls_io_instance->on_io_open_complete_context = on_io_open_complete_context;
567
568 tls_io_instance->on_io_error = on_io_error;
569 tls_io_instance->on_io_error_context = on_io_error_context;
570
571 tls_io_instance->tlsio_state = TLSIO_STATE_OPENING_UNDERLYING_IO;
572
573 mbedtls_ssl_session_reset(&tls_io_instance->ssl);
574
575 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)
576 {
577
578 LogError("Underlying IO open failed");
579 tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
580 result = MU_FAILURE;
581 }
582 }
583 }
584 return result;
585}
586
587int tlsio_mbedtls_close(CONCRETE_IO_HANDLE tls_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void *callback_context)
588{
589 int result = 0;
590
591 if (tls_io == NULL)
592 {
593 LogError("Invalid parameter specified tls_io: NULL");
594 result = MU_FAILURE;
595 }
596 else
597 {
598 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
599
600 if ((tls_io_instance->tlsio_state == TLSIO_STATE_NOT_OPEN) ||
601 (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING))
602 {
603 LogError("IO should not be closed: %d", tls_io_instance->tlsio_state);
604 result = MU_FAILURE;
605 }
606 else
607 {
608 if (tls_io_instance->tls_status == TLS_STATE_INITIALIZED)
609 {
610 mbedtls_ssl_close_notify(&tls_io_instance->ssl);
611 }
612
613 tls_io_instance->tlsio_state = TLSIO_STATE_CLOSING;
614 tls_io_instance->on_io_close_complete = on_io_close_complete;
615 tls_io_instance->on_io_close_complete_context = callback_context;
616 if (xio_close(tls_io_instance->socket_io, on_underlying_io_close_complete_during_close, tls_io_instance) != 0)
617 {
618 LogError("xio_close failed");
619 result = MU_FAILURE;
620 }
621 else
622 {
623 result = 0;
624 }
625 }
626 }
627 return result;
628}
629
630int tlsio_mbedtls_send(CONCRETE_IO_HANDLE tls_io, const void *buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void *callback_context)
631{
632 int result = 0;
633
634 if (tls_io == NULL || (buffer == NULL) || (size == 0))
635 {
636 LogError("Invalid parameter specified tls_io: %p, buffer: %p, size: %ul", tls_io, buffer, (unsigned int)size);
637 result = MU_FAILURE;
638 }
639 else
640 {
641 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
642 if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
643 {
644 LogError("Invalid state specified %d", tls_io_instance->tlsio_state);
645 result = MU_FAILURE;
646 }
647 else
648 {
649 tls_io_instance->on_send_complete = on_send_complete;
650 tls_io_instance->on_send_complete_callback_context = callback_context;
651 int res = mbedtls_ssl_write(&tls_io_instance->ssl, buffer, size);
652 if (res != (int)size)
653 {
654 LogError("Unexpected data size returned from mbedtls_ssl_write %d/%d", res, (int)size);
655 result = MU_FAILURE;
656 }
657 else
658 {
659 result = 0;
660 }
661 tls_io_instance->on_send_complete = NULL;
662 tls_io_instance->on_send_complete_callback_context = NULL;
663 }
664 }
665 return result;
666}
667
668void tlsio_mbedtls_dowork(CONCRETE_IO_HANDLE tls_io)
669{
670 if (tls_io != NULL)
671 {
672 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
673
674 if (tls_io_instance->tlsio_state == TLSIO_STATE_OPENING_UNDERLYING_IO)
675 {
676 xio_dowork(tls_io_instance->socket_io);
677 }
678 else if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE || tls_io_instance->tlsio_state == TLSIO_STATE_OPEN)
679 {
680 decode_ssl_received_bytes(tls_io_instance);
681 // Note: no need to call xio_dowork here because it's called in on_io_recv which is the callback function of decode_ssl_received_bytes
682 }
683 }
684}
685
686/*this function will clone an option given by name and value*/
687static void *tlsio_mbedtls_CloneOption(const char *name, const void *value)
688{
689 void *result = NULL;
690 if (name == NULL || value == NULL)
691 {
692 LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
693 result = NULL;
694 }
695 else
696 {
697 if (strcmp(name, OPTION_UNDERLYING_IO_OPTIONS) == 0)
698 {
699 result = (void *)value;
700 }
701 else if (strcmp(name, OPTION_TRUSTED_CERT) == 0)
702 {
703 if (mallocAndStrcpy_s((char **)&result, value) != 0)
704 {
705 LogError("unable to mallocAndStrcpy_s TrustedCerts value");
706 result = NULL;
707 }
708 else
709 {
710 /*return as is*/
711 }
712 }
713 else if (strcmp(name, SU_OPTION_X509_CERT) == 0)
714 {
715 if (mallocAndStrcpy_s((char**)&result, value) != 0)
716 {
717 LogError("unable to mallocAndStrcpy_s x509certificate value");
718 result = NULL;
719 }
720 else
721 {
722 /*return as is*/
723 }
724 }
725 else if (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0)
726 {
727 if (mallocAndStrcpy_s((char**)&result, value) != 0)
728 {
729 LogError("unable to mallocAndStrcpy_s x509privatekey value");
730 result = NULL;
731 }
732 else
733 {
734 /*return as is*/
735 }
736 }
737 else if (strcmp(name, OPTION_X509_ECC_CERT) == 0)
738 {
739 if (mallocAndStrcpy_s((char**)&result, value) != 0)
740 {
741 LogError("unable to mallocAndStrcpy_s x509EccCertificate value");
742 result = NULL;
743 }
744 else
745 {
746 /*return as is*/
747 }
748 }
749 else if (strcmp(name, OPTION_X509_ECC_KEY) == 0)
750 {
751 if (mallocAndStrcpy_s((char**)&result, value) != 0)
752 {
753 LogError("unable to mallocAndStrcpy_s x509EccKey value");
754 result = NULL;
755 }
756 else
757 {
758 /*return as is*/
759 }
760 }
761 else
762 {
763 LogError("not handled option : %s", name);
764 result = NULL;
765 }
766 }
767 return result;
768}
769
770/*this function destroys an option previously created*/
771static void tlsio_mbedtls_DestroyOption(const char *name, const void *value)
772{
773 /*since all options for this layer are actually string copies., disposing of one is just calling free*/
774 if (name == NULL || value == NULL)
775 {
776 LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
777 }
778 else
779 {
780 if (
781 (strcmp(name, OPTION_TRUSTED_CERT) == 0) ||
782 (strcmp(name, SU_OPTION_X509_CERT) == 0) ||
783 (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0) ||
784 (strcmp(name, OPTION_X509_ECC_CERT) == 0) ||
785 (strcmp(name, OPTION_X509_ECC_KEY) == 0)
786 )
787 {
788 free((void*)value);
789 }
790 else if (strcmp(name, OPTION_UNDERLYING_IO_OPTIONS) == 0)
791 {
792 OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
793 }
794 else
795 {
796 LogError("not handled option : %s", name);
797 }
798 }
799}
800
801int tlsio_mbedtls_setoption(CONCRETE_IO_HANDLE tls_io, const char *optionName, const void *value)
802{
803 int result = 0;
804
805 if (tls_io == NULL || optionName == NULL)
806 {
807 result = MU_FAILURE;
808 }
809 else
810 {
811 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)tls_io;
812
813 if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
814 {
815 if (tls_io_instance->trusted_certificates != NULL)
816 {
817 // Free the memory if it has been previously allocated
818 free(tls_io_instance->trusted_certificates);
819 tls_io_instance->trusted_certificates = NULL;
820 }
821 if (mallocAndStrcpy_s(&tls_io_instance->trusted_certificates, (const char *)value) != 0)
822 {
823 LogError("unable to mallocAndStrcpy_s");
824 result = MU_FAILURE;
825 }
826 else
827 {
828 int parse_result = mbedtls_x509_crt_parse(&tls_io_instance->trusted_certificates_parsed, (const unsigned char *)value, (int)(strlen(value) + 1));
829 if (parse_result != 0)
830 {
831 LogInfo("Malformed pem certificate");
832 result = MU_FAILURE;
833 }
834 else
835 {
836 mbedtls_ssl_conf_ca_chain(&tls_io_instance->config, &tls_io_instance->trusted_certificates_parsed, NULL);
837 }
838 }
839 }
840 else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
841 {
842 if (tls_io_instance->x509_certificate != NULL)
843 {
844 // Free the memory if it has been previously allocated
845 free(tls_io_instance->x509_certificate);
846 }
847
848 if (mallocAndStrcpy_s(&tls_io_instance->x509_certificate, (const char *)value) != 0)
849 {
850 LogError("unable to mallocAndStrcpy_s on certificate");
851 result = MU_FAILURE;
852 }
853 else if (mbedtls_x509_crt_parse(&tls_io_instance->owncert, (const unsigned char *)value, (int)(strlen(value) + 1)) != 0)
854 {
855 LogError("failure parsing certificate");
856 free(tls_io_instance->x509_certificate);
857 result = MU_FAILURE;
858 }
859 else if (tls_io_instance->pKey.pk_info != NULL && mbedtls_ssl_conf_own_cert(&tls_io_instance->config, &tls_io_instance->owncert, &tls_io_instance->pKey) != 0)
860 {
861 LogError("failure calling mbedtls_ssl_conf_own_cert");
862 free(tls_io_instance->x509_certificate);
863 result = MU_FAILURE;
864 }
865 else
866 {
867 result = 0;
868 }
869 }
870 else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
871 {
872 if (tls_io_instance->x509_private_key != NULL)
873 {
874 // Free the memory if it has been previously allocated
875 free(tls_io_instance->x509_private_key);
876 }
877
878 if (mallocAndStrcpy_s(&tls_io_instance->x509_private_key, (const char *)value) != 0)
879 {
880 LogError("unable to mallocAndStrcpy_s on private key");
881 result = MU_FAILURE;
882 }
883 else if (mbedtls_pk_parse_key(&tls_io_instance->pKey, (const unsigned char *)value, (int)(strlen(value) + 1), NULL, 0) != 0)
884 {
885 LogError("failure parsing Private Key");
886 free(tls_io_instance->x509_private_key);
887 result = MU_FAILURE;
888 }
889 else if (tls_io_instance->owncert.version > 0 && mbedtls_ssl_conf_own_cert(&tls_io_instance->config, &tls_io_instance->owncert, &tls_io_instance->pKey))
890 {
891 LogError("failure calling mbedtls_ssl_conf_own_cert on cert");
892 free(tls_io_instance->x509_private_key);
893 result = MU_FAILURE;
894 }
895 else
896 {
897 result = 0;
898 }
899 }
900 else if (strcmp(optionName, OPTION_UNDERLYING_IO_OPTIONS) == 0)
901 {
902 if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, (void*)tls_io_instance->socket_io) != OPTIONHANDLER_OK)
903 {
904 LogError("failed feeding options to underlying I/O instance");
905 result = MU_FAILURE;
906 }
907 else
908 {
909 result = 0;
910 }
911 }
912 else
913 {
914 // tls_io_instance->socket_io is never NULL
915 result = xio_setoption(tls_io_instance->socket_io, optionName, value);
916 }
917 }
918
919 return result;
920}
921
922OPTIONHANDLER_HANDLE tlsio_mbedtls_retrieveoptions(CONCRETE_IO_HANDLE handle)
923{
924 OPTIONHANDLER_HANDLE result = NULL;
925 if (handle == NULL)
926 {
927 LogError("invalid parameter detected: CONCRETE_IO_HANDLE handle=%p", handle);
928 result = NULL;
929 }
930 else
931 {
932 result = OptionHandler_Create(tlsio_mbedtls_CloneOption, tlsio_mbedtls_DestroyOption, tlsio_mbedtls_setoption);
933 if (result == NULL)
934 {
935 LogError("unable to OptionHandler_Create");
936 /*return as is*/
937 }
938 else
939 {
940 /*this layer cares about the certificates*/
941 TLS_IO_INSTANCE *tls_io_instance = (TLS_IO_INSTANCE *)handle;
942 OPTIONHANDLER_HANDLE underlying_io_options;
943
944 if ((underlying_io_options = xio_retrieveoptions(tls_io_instance->socket_io)) == NULL ||
945 OptionHandler_AddOption(result, OPTION_UNDERLYING_IO_OPTIONS, underlying_io_options) != OPTIONHANDLER_OK)
946 {
947 LogError("unable to save underlying_io options");
948 OptionHandler_Destroy(underlying_io_options);
949 OptionHandler_Destroy(result);
950 result = NULL;
951 }
952 else if (tls_io_instance->trusted_certificates != NULL &&
953 OptionHandler_AddOption(result, OPTION_TRUSTED_CERT, tls_io_instance->trusted_certificates) != OPTIONHANDLER_OK)
954 {
955 LogError("unable to save TrustedCerts option");
956 OptionHandler_Destroy(result);
957 result = NULL;
958 }
959 else if (&tls_io_instance->owncert != NULL && tls_io_instance->x509_certificate != NULL &&
960 OptionHandler_AddOption(result, SU_OPTION_X509_CERT, tls_io_instance->x509_certificate) != OPTIONHANDLER_OK)
961 {
962 LogError("unable to save x509certificate option");
963 OptionHandler_Destroy(result);
964 result = NULL;
965 }
966 else if (
967 (&tls_io_instance->pKey != NULL) && tls_io_instance->x509_private_key != NULL &&
968 (OptionHandler_AddOption(result, SU_OPTION_X509_PRIVATE_KEY, tls_io_instance->x509_private_key) != OPTIONHANDLER_OK)
969 )
970 {
971 LogError("unable to save x509privatekey option");
972 OptionHandler_Destroy(result);
973 result = NULL;
974 }
975 else
976 {
977 /*all is fine, all interesting options have been saved*/
978 /*return as is*/
979 }
980 }
981 }
982 return result;
983}
984
985static const IO_INTERFACE_DESCRIPTION tlsio_mbedtls_interface_description =
986 {
987 tlsio_mbedtls_retrieveoptions,
988 tlsio_mbedtls_create,
989 tlsio_mbedtls_destroy,
990 tlsio_mbedtls_open,
991 tlsio_mbedtls_close,
992 tlsio_mbedtls_send,
993 tlsio_mbedtls_dowork,
994 tlsio_mbedtls_setoption};
995
996const IO_INTERFACE_DESCRIPTION *tlsio_mbedtls_get_interface_description(void)
997{
998 return &tlsio_mbedtls_interface_description;
999}
Note: See TracBrowser for help on using the repository browser.