1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdint.h>
12 #include "linkkit/infra/infra_config.h"
13 #ifdef COAP_DTLS_SUPPORT
14 #include "linkkit/wrappers/wrappers_defs.h"
15 #include "mbedtls/ssl.h"
16 #include "mbedtls/platform.h"
17 #include "mbedtls/sha256.h"
18 #include "mbedtls/debug.h"
19 #include "mbedtls/timing.h"
20 #include "mbedtls/ctr_drbg.h"
21 #include "mbedtls/entropy.h"
22 #include "mbedtls/ssl_cookie.h"
23 #include "mbedtls/net_sockets.h"
24 #include "linkkit/wrappers/wrappers.h"
25 
26 #define DTLS_TRC(...)   HAL_Printf("[trc] "), HAL_Printf(__VA_ARGS__)
27 #define DTLS_DUMP(...)  HAL_Printf("[dump] "), HAL_Printf(__VA_ARGS__)
28 #define DTLS_DEBUG(...) HAL_Printf("[dbg] "), HAL_Printf(__VA_ARGS__)
29 #define DTLS_INFO(...)  HAL_Printf("[inf] "), HAL_Printf(__VA_ARGS__)
30 #define DTLS_ERR(...)   HAL_Printf("[err] "), HAL_Printf(__VA_ARGS__)
31 
32 #ifdef DTLS_SESSION_SAVE
33 mbedtls_ssl_session *saved_session = NULL;
34 #endif
35 
36 typedef struct {
37     mbedtls_ssl_context context;
38     mbedtls_ssl_config conf;
39     mbedtls_ctr_drbg_context ctr_drbg;
40     mbedtls_entropy_context entropy;
41 #ifdef MBEDTLS_X509_CRT_PARSE_C
42     mbedtls_x509_crt cacert;
43 #endif
44     mbedtls_net_context fd;
45     mbedtls_timing_delay_context timer;
46     mbedtls_ssl_cookie_ctx cookie_ctx;
47 } dtls_session_t;
48 
49 typedef struct {
50     void *(*malloc)(uint32_t size);
51     void (*free)(void *ptr);
52 } dtls_hooks_t;
53 
54 #define MBEDTLS_MEM_TEST 1
55 
56 #ifdef MBEDTLS_MEM_TEST
57 
58 #define MBEDTLS_MEM_INFO_MAGIC 0x12345678
59 
60 static unsigned int mbedtls_mem_used = 0;
61 static unsigned int mbedtls_max_mem_used = 0;
62 static dtls_hooks_t g_dtls_hooks = { HAL_Malloc, HAL_Free };
63 
64 typedef struct {
65     int magic;
66     int size;
67 } mbedtls_mem_info_t;
68 
_DTLSMalloc_wrapper(uint32_t size)69 static void *_DTLSMalloc_wrapper(uint32_t size)
70 {
71     return HAL_Malloc(size);
72 }
73 
_DTLSCalloc_wrapper(size_t n,size_t size)74 static void *_DTLSCalloc_wrapper(size_t n, size_t size)
75 {
76     void *buf = NULL;
77     mbedtls_mem_info_t *mem_info = NULL;
78 
79     if (n == 0 || size == 0) {
80         return NULL;
81     }
82 
83     buf = g_dtls_hooks.malloc(n * size + sizeof(mbedtls_mem_info_t));
84     if (NULL == buf) {
85         return NULL;
86     } else {
87         memset(buf, 0, n * size + sizeof(mbedtls_mem_info_t));
88     }
89 
90     mem_info = (mbedtls_mem_info_t *)buf;
91     mem_info->magic = MBEDTLS_MEM_INFO_MAGIC;
92     mem_info->size = n * size;
93     buf += sizeof(mbedtls_mem_info_t);
94 
95     mbedtls_mem_used += mem_info->size;
96     if (mbedtls_mem_used > mbedtls_max_mem_used) {
97         mbedtls_max_mem_used = mbedtls_mem_used;
98     }
99 
100     /* DTLS_TRC("INFO -- mbedtls malloc: %p %d  total used: %d  max used:
101        %d\r\n", buf, (int)size, mbedtls_mem_used, mbedtls_max_mem_used); */
102 
103     return buf;
104 }
105 
_DTLSFree_wrapper(void * ptr)106 void _DTLSFree_wrapper(void *ptr)
107 {
108     mbedtls_mem_info_t *mem_info = NULL;
109     if (NULL == ptr) {
110         return;
111     }
112 
113     mem_info = ptr - sizeof(mbedtls_mem_info_t);
114     if (mem_info->magic != MBEDTLS_MEM_INFO_MAGIC) {
115         DTLS_TRC("Warning - invalid mem info magic: 0x%x\r\n", mem_info->magic);
116         return;
117     }
118 
119     mbedtls_mem_used -= mem_info->size;
120     /* DTLS_TRC("INFO mbedtls free: %p %d  total used: %d  max used: %d\r\n",
121                        ptr, mem_info->size, mbedtls_mem_used,
122        mbedtls_max_mem_used);*/
123 
124     g_dtls_hooks.free(mem_info);
125 }
126 
127 #else
_DTLSCalloc_wrapper(size_t n,size_t s)128 static void *_DTLSCalloc_wrapper(size_t n, size_t s)
129 {
130     void *ptr = NULL;
131     size_t len = n * s;
132     ptr = HAL_Malloc(len);
133     if (NULL != ptr) {
134         memset(ptr, 0x00, len);
135     }
136     return ptr;
137 }
138 
_DTLSFree_wrapper(void * ptr)139 static void _DTLSFree_wrapper(void *ptr)
140 {
141     if (NULL != ptr) {
142         HAL_Free(ptr);
143         ptr = NULL;
144     }
145 }
146 #endif
147 
148 #ifdef DTLS_SESSION_SAVE
_DTLSSession_save(const mbedtls_ssl_session * session,unsigned char * buf,size_t buf_len,size_t * olen)149 static int _DTLSSession_save(const mbedtls_ssl_session *session,
150                              unsigned char *buf, size_t buf_len, size_t *olen)
151 {
152     unsigned char *p = buf;
153     size_t left = buf_len;
154 #if defined(MBEDTLS_X509_CRT_PARSE_C)
155     size_t cert_len;
156 #endif /* MBEDTLS_X509_CRT_PARSE_C */
157 
158     if (left < sizeof(mbedtls_ssl_session)) {
159         return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
160     }
161 
162     memcpy(p, session, sizeof(mbedtls_ssl_session));
163     p += sizeof(mbedtls_ssl_session);
164     left -= sizeof(mbedtls_ssl_session);
165 
166 #if defined(MBEDTLS_X509_CRT_PARSE_C)
167     if (session->peer_cert == NULL) {
168         cert_len = 0;
169     } else {
170         cert_len = session->peer_cert->raw.len;
171     }
172 
173     if (left < 3 + cert_len) {
174         return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
175     }
176 
177     *p++ = (unsigned char)(cert_len >> 16 & 0xFF);
178     *p++ = (unsigned char)(cert_len >> 8 & 0xFF);
179     *p++ = (unsigned char)(cert_len & 0xFF);
180 
181     if (session->peer_cert != NULL) {
182         memcpy(p, session->peer_cert->raw.p, cert_len);
183     }
184 
185     p += cert_len;
186 #endif /* MBEDTLS_X509_CRT_PARSE_C */
187 
188     *olen = p - buf;
189 
190     return 0;
191 }
192 #endif
193 
_DTLSVerifyOptions_set(dtls_session_t * p_dtls_session,unsigned char * p_ca_cert_pem,char * host)194 static unsigned int _DTLSVerifyOptions_set(dtls_session_t *p_dtls_session,
195                                            unsigned char *p_ca_cert_pem,
196                                            char *host)
197 {
198     int result;
199     unsigned int err_code = DTLS_SUCCESS;
200 
201 #ifdef MBEDTLS_X509_CRT_PARSE_C
202     if (p_ca_cert_pem != NULL) {
203         mbedtls_ssl_conf_authmode(&p_dtls_session->conf,
204                                   MBEDTLS_SSL_VERIFY_REQUIRED);
205         if (strstr(host, "pre.iot-as-coap")) {
206             DTLS_TRC("host = '%s' so verify server OPTIONAL\r\n", host);
207             mbedtls_ssl_conf_authmode(&p_dtls_session->conf,
208                                       MBEDTLS_SSL_VERIFY_OPTIONAL);
209         }
210         DTLS_TRC("Call mbedtls_ssl_conf_authmode\r\n");
211 
212         DTLS_TRC("x509 ca cert pem len %d\r\n%s\r\n",
213                  (int)strlen((char *)p_ca_cert_pem) + 1, p_ca_cert_pem);
214         result =
215             mbedtls_x509_crt_parse(&p_dtls_session->cacert, p_ca_cert_pem,
216                                    strlen((const char *)p_ca_cert_pem) + 1);
217 
218         DTLS_TRC("mbedtls_x509_crt_parse result 0x%04x\r\n", result);
219         if (0 != result) {
220             err_code = DTLS_INVALID_CA_CERTIFICATE;
221         } else {
222             mbedtls_ssl_conf_ca_chain(&p_dtls_session->conf,
223                                       &p_dtls_session->cacert, NULL);
224         }
225     } else
226 #endif
227     {
228         mbedtls_ssl_conf_authmode(&p_dtls_session->conf,
229                                   MBEDTLS_SSL_VERIFY_NONE);
230     }
231 
232     return err_code;
233 }
234 
_DTLSLog_wrapper(void * p_ctx,int level,const char * p_file,int line,const char * p_str)235 static void _DTLSLog_wrapper(void *p_ctx, int level, const char *p_file,
236                              int line, const char *p_str)
237 {
238     DTLS_INFO("[mbedTLS]:[%s]:[%d]: %s\r\n", p_file, line, p_str);
239 }
240 
_DTLSContext_setup(dtls_session_t * p_dtls_session,coap_dtls_options_t * p_options)241 static unsigned int _DTLSContext_setup(dtls_session_t *p_dtls_session,
242                                        coap_dtls_options_t *p_options)
243 {
244     int result = 0;
245 
246     mbedtls_ssl_init(&p_dtls_session->context);
247 
248     result = mbedtls_ssl_setup(&p_dtls_session->context, &p_dtls_session->conf);
249     DTLS_TRC("mbedtls_ssl_setup result 0x%04x\r\n", result);
250 
251     if (result == 0) {
252         if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
253             mbedtls_ssl_set_timer_cb(
254                 &p_dtls_session->context, (void *)&p_dtls_session->timer,
255                 mbedtls_timing_set_delay, mbedtls_timing_get_delay);
256         }
257 
258 #ifdef MBEDTLS_X509_CRT_PARSE_C
259         DTLS_TRC("mbedtls_ssl_set_hostname %s\r\n", p_options->p_host);
260         mbedtls_ssl_set_hostname(&p_dtls_session->context, p_options->p_host);
261 #endif
262         mbedtls_ssl_set_bio(&p_dtls_session->context,
263                             (void *)&p_dtls_session->fd, mbedtls_net_send,
264                             mbedtls_net_recv, mbedtls_net_recv_timeout);
265         DTLS_TRC("mbedtls_ssl_set_bio result 0x%04x\r\n", result);
266 
267 #ifdef DTLS_SESSION_SAVE
268         if (NULL != saved_session) {
269             result = mbedtls_ssl_set_session(&p_dtls_session->context,
270                                              saved_session);
271             DTLS_TRC("mbedtls_ssl_set_session return 0x%04x\r\n", result);
272         }
273 #endif
274 
275         do {
276             result = mbedtls_ssl_handshake(&p_dtls_session->context);
277         } while (result == MBEDTLS_ERR_SSL_WANT_READ ||
278                  result == MBEDTLS_ERR_SSL_WANT_WRITE);
279         DTLS_TRC("mbedtls_ssl_handshake result 0x%04x\r\n", result);
280 #ifdef MBEDTLS_MEM_TEST
281         DTLS_TRC("mbedtls handshake memory total used: %d  max used: %d\r\n",
282                  mbedtls_mem_used, mbedtls_max_mem_used);
283 #endif
284 
285 #ifdef DTLS_SESSION_SAVE
286         if (0 == result) {
287             if (NULL == saved_session) {
288                 saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
289             }
290             if (NULL != saved_session) {
291                 memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
292                 result = mbedtls_ssl_get_session(&p_dtls_session->context,
293                                                  saved_session);
294                 DTLS_TRC("mbedtls_ssl_get_session return 0x%04x\r\n", result);
295             }
296         }
297 #endif
298     }
299 
300     return result ? DTLS_HANDSHAKE_FAILED : DTLS_SUCCESS;
301 }
302 
_DTLSSession_init()303 dtls_session_t *_DTLSSession_init()
304 {
305     dtls_session_t *p_dtls_session = NULL;
306     p_dtls_session = HAL_Malloc(sizeof(dtls_session_t));
307 #if defined(MBEDTLS_DEBUG_C)
308     mbedtls_debug_set_threshold(0);
309 #endif
310 #ifdef MBEDTLS_MEM_TEST
311     mbedtls_mem_used = 0;
312     mbedtls_max_mem_used = 0;
313 #endif
314     /*    mbedtls_platform_set_calloc_free(_DTLSCalloc_wrapper,
315      * _DTLSFree_wrapper);*/
316     if (NULL != p_dtls_session) {
317         mbedtls_net_init(&p_dtls_session->fd);
318         mbedtls_ssl_init(&p_dtls_session->context);
319         mbedtls_ssl_config_init(&p_dtls_session->conf);
320         mbedtls_net_init(&p_dtls_session->fd);
321 
322         mbedtls_ssl_cookie_init(&p_dtls_session->cookie_ctx);
323 
324 #ifdef MBEDTLS_X509_CRT_PARSE_C
325         mbedtls_x509_crt_init(&p_dtls_session->cacert);
326 #endif
327 #ifdef MBEDTLS_ENTROPY_C
328         mbedtls_ctr_drbg_init(&p_dtls_session->ctr_drbg);
329         mbedtls_entropy_init(&p_dtls_session->entropy);
330 #endif
331         DTLS_INFO("HAL_DTLSSession_init success\r\n");
332     }
333 
334     return p_dtls_session;
335 }
336 
_DTLSSession_deinit(dtls_session_t * p_dtls_session)337 unsigned int _DTLSSession_deinit(dtls_session_t *p_dtls_session)
338 {
339     int ret;
340     if (p_dtls_session != NULL) {
341         do {
342             ret = mbedtls_ssl_close_notify(&p_dtls_session->context);
343         } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
344 
345         mbedtls_net_free(&p_dtls_session->fd);
346 #ifdef MBEDTLS_X509_CRT_PARSE_C
347         mbedtls_x509_crt_free(&p_dtls_session->cacert);
348 #endif
349         mbedtls_ssl_cookie_free(&p_dtls_session->cookie_ctx);
350 
351         mbedtls_ssl_config_free(&p_dtls_session->conf);
352         mbedtls_ssl_free(&p_dtls_session->context);
353 #ifdef MBEDTLS_ENTROPY_C
354         mbedtls_ctr_drbg_free(&p_dtls_session->ctr_drbg);
355         mbedtls_entropy_free(&p_dtls_session->entropy);
356 #endif
357         HAL_Free(p_dtls_session);
358     }
359 
360     return DTLS_SUCCESS;
361 }
362 /*
363 int _DTLSHooks_set(dtls_hooks_t *hooks)
364 {
365     if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) {
366         return DTLS_INVALID_PARAM;
367     }
368 
369     g_dtls_hooks.malloc = hooks->malloc;
370     g_dtls_hooks.free = hooks->free;
371 
372     return DTLS_SUCCESS;
373 }
374 */
375 
HAL_DTLSSession_create(coap_dtls_options_t * p_options)376 DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options)
377 {
378     char port[6] = { 0 };
379     int result = 0;
380     dtls_session_t *p_dtls_session = NULL;
381     /*
382     dtls_hooks_t dtls_hooks;
383 
384     memset(&dtls_hooks, 0, sizeof(dtls_hooks_t));
385     dtls_hooks.malloc = _DTLSMalloc_wrapper;
386     dtls_hooks.free = _DTLSFree_wrapper;
387 
388     _DTLSHooks_set(&dtls_hooks);
389     */
390     p_dtls_session = _DTLSSession_init();
391     if (NULL != p_dtls_session) {
392         mbedtls_ssl_config_init(&p_dtls_session->conf);
393 #ifdef MBEDTLS_ENTROPY_C
394         result = mbedtls_ctr_drbg_seed(
395             &p_dtls_session->ctr_drbg, mbedtls_entropy_func,
396             &p_dtls_session->entropy, (const unsigned char *)"IoTx",
397             strlen("IoTx"));
398         if (0 != result) {
399             DTLS_ERR("mbedtls_ctr_drbg_seed result 0x%04x\r\n", result);
400             goto error;
401         }
402 #endif
403         result = mbedtls_ssl_config_defaults(
404             &p_dtls_session->conf, MBEDTLS_SSL_IS_CLIENT,
405             MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT);
406         if (0 != result) {
407             DTLS_ERR("mbedtls_ssl_config_defaults result 0x%04x\r\n", result);
408             goto error;
409         }
410 #if defined(MBEDTLS_DEBUG_C)
411         mbedtls_ssl_conf_rng(&p_dtls_session->conf, mbedtls_ctr_drbg_random,
412                              &p_dtls_session->ctr_drbg);
413         mbedtls_ssl_conf_dbg(&p_dtls_session->conf, _DTLSLog_wrapper, NULL);
414 #endif
415 #ifdef MBEDTLS_ENTROPY_C
416         result = mbedtls_ssl_cookie_setup(&p_dtls_session->cookie_ctx,
417                                           mbedtls_ctr_drbg_random,
418                                           &p_dtls_session->ctr_drbg);
419         if (0 != result) {
420             DTLS_ERR("mbedtls_ssl_cookie_setup result 0x%04x\r\n", result);
421             goto error;
422         }
423 #endif
424 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
425         mbedtls_ssl_conf_dtls_cookies(
426             &p_dtls_session->conf, mbedtls_ssl_cookie_write,
427             mbedtls_ssl_cookie_check, &p_dtls_session->cookie_ctx);
428 #endif
429 
430         result = _DTLSVerifyOptions_set(
431             p_dtls_session, p_options->p_ca_cert_pem, p_options->p_host);
432 
433         if (DTLS_SUCCESS != result) {
434             DTLS_ERR("DTLSVerifyOptions_set result 0x%04x\r\n", result);
435             goto error;
436         }
437         sprintf(port, "%u", p_options->port);
438         result = mbedtls_net_connect(&p_dtls_session->fd, p_options->p_host,
439                                      port, MBEDTLS_NET_PROTO_UDP);
440         if (0 != result) {
441             DTLS_ERR("mbedtls_net_connect result 0x%04x\r\n", result);
442             goto error;
443         }
444 
445 #ifdef MBEDTLS_SSL_PROTO_DTLS
446         if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
447             mbedtls_ssl_conf_min_version(&p_dtls_session->conf,
448                                          MBEDTLS_SSL_MAJOR_VERSION_3,
449                                          MBEDTLS_SSL_MINOR_VERSION_3);
450 
451             mbedtls_ssl_conf_max_version(&p_dtls_session->conf,
452                                          MBEDTLS_SSL_MAJOR_VERSION_3,
453                                          MBEDTLS_SSL_MINOR_VERSION_3);
454 
455             mbedtls_ssl_conf_handshake_timeout(
456                 &p_dtls_session->conf, (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2),
457                 (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4));
458         }
459 #endif
460         result = _DTLSContext_setup(p_dtls_session, p_options);
461         if (DTLS_SUCCESS != result) {
462             DTLS_ERR("DTLSVerifyOptions_set result 0x%04x\r\n", result);
463             goto error;
464         }
465 
466         return (DTLSContext *)p_dtls_session;
467     }
468 
469 error:
470     if (NULL != p_dtls_session) {
471         _DTLSSession_deinit(p_dtls_session);
472     }
473     return NULL;
474 }
475 
HAL_DTLSSession_write(DTLSContext * context,const unsigned char * p_data,unsigned int * p_datalen)476 unsigned int HAL_DTLSSession_write(DTLSContext *context,
477                                    const unsigned char *p_data,
478                                    unsigned int *p_datalen)
479 {
480     int len = 0;
481     unsigned int err_code = DTLS_SUCCESS;
482     dtls_session_t *p_dtls_session = (dtls_session_t *)context;
483 
484     if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
485         len = (*p_datalen);
486         len = mbedtls_ssl_write(&p_dtls_session->context, p_data, len);
487 
488         if (len < 0) {
489             if (len == MBEDTLS_ERR_SSL_CONN_EOF) {
490                 if (p_dtls_session->context.state <
491                     MBEDTLS_SSL_HANDSHAKE_OVER) {
492                     err_code = DTLS_HANDSHAKE_IN_PROGRESS;
493                 }
494             }
495         } else {
496             (*p_datalen) = len;
497             err_code = DTLS_SUCCESS;
498         }
499     }
500 
501     return err_code;
502 }
503 
HAL_DTLSSession_read(DTLSContext * context,unsigned char * p_data,unsigned int * p_datalen,unsigned int timeout)504 unsigned int HAL_DTLSSession_read(DTLSContext *context, unsigned char *p_data,
505                                   unsigned int *p_datalen, unsigned int timeout)
506 {
507     int len = 0;
508     unsigned int err_code = DTLS_READ_DATA_FAILED;
509     dtls_session_t *p_dtls_session = (dtls_session_t *)context;
510 
511     if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
512         mbedtls_ssl_conf_read_timeout(&(p_dtls_session->conf), timeout);
513         len = mbedtls_ssl_read(&p_dtls_session->context, p_data, *p_datalen);
514 
515         if (0 < len) {
516             *p_datalen = len;
517             err_code = DTLS_SUCCESS;
518             DTLS_TRC("mbedtls_ssl_read len %d bytes\r\n", len);
519         } else {
520             *p_datalen = 0;
521             if (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == len) {
522                 err_code = DTLS_FATAL_ALERT_MESSAGE;
523                 DTLS_INFO("Recv peer fatal alert message\r\n");
524             } else if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == len) {
525                 err_code = DTLS_PEER_CLOSE_NOTIFY;
526                 DTLS_INFO("The DTLS session was closed by peer\r\n");
527             } else if (MBEDTLS_ERR_SSL_TIMEOUT == len) {
528                 err_code = DTLS_SUCCESS;
529                 DTLS_TRC("DTLS recv timeout\r\n");
530             } else {
531                 DTLS_TRC("mbedtls_ssl_read error result (-0x%04x)\r\n", len);
532             }
533         }
534     }
535     return err_code;
536 }
537 
HAL_DTLSSession_free(DTLSContext * context)538 unsigned int HAL_DTLSSession_free(DTLSContext *context)
539 {
540     dtls_session_t *p_dtls_session = NULL;
541     if (NULL != context) {
542         p_dtls_session = (dtls_session_t *)context;
543         return _DTLSSession_deinit(p_dtls_session);
544     }
545 
546     return DTLS_INVALID_PARAM;
547 }
548 
549 #endif
550