1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/socket.h>
10 
11 #include "aos/errno.h"
12 #include "aos/kernel.h"
13 #include "aos/kv.h"
14 #include "ulog/ulog.h"
15 
16 
17 #ifdef AOS_COMP_UND
18     #include "und/und.h"
19 #endif
20 
21 #include "mbedtls/error.h"
22 #include "mbedtls/ssl.h"
23 #include "mbedtls/net.h"
24 #include "mbedtls/x509_crt.h"
25 #include "mbedtls/pk.h"
26 #include "mbedtls/debug.h"
27 #include "mbedtls/platform.h"
28 #include "linkkit/wrappers/wrappers_defs.h"
29 #include "linkkit/wrappers/wrappers_os.h"
30 #ifdef HAL_TLS_DNS_ENHANCE
31 #include "dns.h"
32 #endif
33 #define LOG_TAG                    "HAL_TLS"
34 
35 #define platform_info(format, ...) LOGI(LOG_TAG, format, ##__VA_ARGS__)
36 #define platform_err(format, ...)  LOGE(LOG_TAG, format, ##__VA_ARGS__)
37 
38 #define SEND_TIMEOUT_SECONDS       (10)
39 
40 #define DEBUG_LEVEL                10
41 
42 typedef struct _TLSDataParams {
43     mbedtls_ssl_context ssl;  /**< mbed TLS control context. */
44     mbedtls_net_context fd;   /**< mbed TLS network context. */
45     mbedtls_ssl_config conf;  /**< mbed TLS configuration context. */
46     mbedtls_x509_crt cacertl; /**< mbed TLS CA certification. */
47     mbedtls_x509_crt clicert; /**< mbed TLS Client certification. */
48     mbedtls_pk_context pkey;  /**< mbed TLS Client key. */
49 } TLSDataParams_t, *TLSDataParams_pt;
50 
51 #ifdef HAL_TLS_DNS_ENHANCE
52 static char *g_fixed_list[3] = { "106.15.83.29", "106.15.100.2",
53                                  "139.196.135.135" };
54 #endif
55 
56 #if defined(TLS_SAVE_TICKET)
57 
58 #define KEY_MAX_LEN         64
59 #define TLS_MAX_SESSION_BUF 384
60 #define KV_SESSION_KEY_FMT  "TLS_%s"
61 
62 extern int HAL_Kv_Set(const char *key, const void *val, int len, int sync);
63 
64 extern int HAL_Kv_Get(const char *key, void *val, int *buffer_len);
65 
66 static mbedtls_ssl_session *saved_session = NULL;
67 
ssl_serialize_session(const mbedtls_ssl_session * session,unsigned char * buf,size_t buf_len,size_t * olen)68 static int ssl_serialize_session(const mbedtls_ssl_session *session,
69                                  unsigned char *buf, size_t buf_len,
70                                  size_t *olen)
71 {
72     unsigned char *p = buf;
73     size_t left = buf_len;
74 
75     if (left < sizeof(mbedtls_ssl_session)) {
76         return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
77     }
78 
79     memcpy(p, session, sizeof(mbedtls_ssl_session));
80     p += sizeof(mbedtls_ssl_session);
81     left -= sizeof(mbedtls_ssl_session);
82 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
83     if (left < sizeof(mbedtls_ssl_session)) {
84         return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
85     }
86     memcpy(p, session->ticket, session->ticket_len);
87     p += session->ticket_len;
88     left -= session->ticket_len;
89 #endif
90 
91     *olen = p - buf;
92 
93     return 0;
94 }
95 
ssl_deserialize_session(mbedtls_ssl_session * session,const unsigned char * buf,size_t len)96 static int ssl_deserialize_session(mbedtls_ssl_session *session,
97                                    const unsigned char *buf, size_t len)
98 {
99     const unsigned char *p = buf;
100     const unsigned char *const end = buf + len;
101 
102     if (sizeof(mbedtls_ssl_session) > (size_t)(end - p)) {
103         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
104     }
105 
106     memcpy(session, p, sizeof(mbedtls_ssl_session));
107     p += sizeof(mbedtls_ssl_session);
108 #if defined(MBEDTLS_X509_CRT_PARSE_C)
109     session->peer_cert = NULL;
110 #endif
111 
112 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
113     if (session->ticket_len > 0) {
114         if (session->ticket_len > (size_t)(end - p)) {
115             return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
116         }
117         session->ticket = HAL_Malloc(session->ticket_len);
118         if (session->ticket == NULL) {
119             return MBEDTLS_ERR_SSL_ALLOC_FAILED;
120         }
121         memcpy(session->ticket, p, session->ticket_len);
122         p += session->ticket_len;
123         printf("saved ticket len = %d \r\n", (int)session->ticket_len);
124     }
125 #endif
126 
127     if (p != end) {
128         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
129     }
130 
131     return 0;
132 }
133 #endif
134 
135 #ifdef HAL_TLS_DNS_ENHANCE
utils_str2uint(char * input,uint8_t input_len,uint32_t * output)136 static void utils_str2uint(char *input, uint8_t input_len, uint32_t *output)
137 {
138     uint8_t index = 0;
139     uint32_t temp = 0;
140 
141     for (index = 0; index < input_len; index++) {
142         if (input[index] < '0' || input[index] > '9') {
143             return;
144         }
145         temp = temp * 10 + input[index] - '0';
146     }
147     *output = temp;
148 }
149 
mbedtls_net_connect_timeout_backup(mbedtls_net_context * ctx,const char * host,const char * port,int proto,unsigned int timeout)150 static int mbedtls_net_connect_timeout_backup(mbedtls_net_context *ctx,
151                                               const char *host,
152                                               const char *port, int proto,
153                                               unsigned int timeout)
154 {
155     int ret;
156     struct sockaddr_in address;
157     size_t addr_len;
158     struct timeval sendtimeout;
159     uint8_t dns_retry = 0, dns_count = 0;
160     uint32_t uint_port = 0;
161     char *ip[DNS_RESULT_COUNT] = { 0 };
162 
163     memset(&address, 0, sizeof(struct sockaddr_in));
164     utils_str2uint((char *)port, strlen(port), &uint_port);
165 
166     while (dns_retry++ < 8) {
167         ret = dns_getaddrinfo((char *)host, ip);
168         if (ret != 0) {
169             platform_info(
170                 "getaddrinfo error[%d], res: %d, host: %s, port: %s\n",
171                 dns_retry, ret, host, port);
172             HAL_SleepMs(1000);
173             continue;
174         } else {
175             break;
176         }
177     }
178     if (ret != 0) {
179         // try fixed ip:
180         if (strstr(host, "iot-as-mqtt.cn-shanghai.aliyuncs.com") != NULL) {
181             int i;
182             for (i = 0; i < 3; i++) {
183                 ip[i] = g_fixed_list[i];
184             }
185             platform_info("using fixed ip\n");
186         } else {
187             return MBEDTLS_ERR_NET_UNKNOWN_HOST;
188         }
189     }
190 
191     /* Try the sockaddrs until a connection succeeds */
192     ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
193     for (dns_count = 0; dns_count < DNS_RESULT_COUNT; dns_count++) {
194         if (ip[dns_count] == NULL || strlen(ip[dns_count]) == 0) {
195             continue;
196         }
197         platform_info("ip address: %s\n", ip[dns_count]);
198 
199         ctx->fd = (int)socket(AF_INET, SOCK_STREAM, 0);
200         if (ctx->fd < 0) {
201             ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
202             continue;
203         }
204 
205         sendtimeout.tv_sec = timeout;
206         sendtimeout.tv_usec = 0;
207 
208         if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &sendtimeout,
209                             sizeof(sendtimeout))) {
210             platform_err("setsockopt error");
211         }
212         platform_info("setsockopt SO_SNDTIMEO timeout: %ds",
213                       sendtimeout.tv_sec);
214 
215         address.sin_family = AF_INET;
216         address.sin_addr.s_addr = inet_addr(ip[dns_count]);
217         address.sin_port = htons(uint_port);
218 
219         addr_len = sizeof(address);
220 
221         if (connect(ctx->fd, (struct sockaddr *)&address, addr_len) == 0) {
222             ret = 0;
223             break;
224         }
225 
226         close(ctx->fd);
227         ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
228     }
229 
230     return ret;
231 }
232 #endif
233 
_avRandom()234 static unsigned int _avRandom()
235 {
236     return ((unsigned int)aos_rand() << 16) + aos_rand();
237 }
238 
_ssl_random(void * p_rng,unsigned char * output,size_t output_len)239 static int _ssl_random(void *p_rng, unsigned char *output, size_t output_len)
240 {
241     uint32_t rnglen = output_len;
242     uint8_t rngoffset = 0;
243 
244     while (rnglen > 0) {
245         *(output + rngoffset) = (unsigned char)_avRandom();
246         rngoffset++;
247         rnglen--;
248     }
249     return 0;
250 }
251 
_aos_srand(unsigned int seed)252 static void _aos_srand(unsigned int seed)
253 {
254 #define SEED_MAGIC 0x123
255     int ret = 0;
256     int seed_len = 0;
257     unsigned int seed_val = 0;
258     static char *g_seed_key = "seed_key";
259 
260     seed_len = sizeof(seed_val);
261     ret = aos_kv_get(g_seed_key, &seed_val, &seed_len);
262     if (ret) {
263         seed_val = SEED_MAGIC;
264     }
265     seed_val += seed;
266     srand(seed_val);
267 
268     seed_val = rand();
269     aos_kv_set(g_seed_key, &seed_val, sizeof(seed_val), 1);
270 }
271 
_ssl_debug(void * ctx,int level,const char * file,int line,const char * str)272 static void _ssl_debug(void *ctx, int level, const char *file, int line,
273                        const char *str)
274 {
275     ((void)level);
276     if (NULL != ctx) {
277         platform_info("%s", str);
278     }
279 }
280 
_real_confirm(int verify_result)281 static int _real_confirm(int verify_result)
282 {
283     platform_info("certificate verification result: 0x%02x", verify_result);
284 
285 #if defined(FORCE_SSL_VERIFY)
286     if ((verify_result & MBEDTLS_X509_BADCERT_EXPIRED) != 0) {
287         platform_err("! fail ! ERROR_CERTIFICATE_EXPIRED");
288         return -1;
289     }
290 
291     if ((verify_result & MBEDTLS_X509_BADCERT_REVOKED) != 0) {
292         platform_err("! fail ! server certificate has been revoked");
293         return -1;
294     }
295 
296     if ((verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) {
297         platform_err("! fail ! CN mismatch");
298         return -1;
299     }
300 
301     if ((verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) {
302         platform_err("! fail ! self-signed or not signed by a trusted CA");
303         return -1;
304     }
305 #endif
306 
307     return 0;
308 }
309 
_ssl_client_init(mbedtls_ssl_context * ssl,mbedtls_net_context * tcp_fd,mbedtls_ssl_config * conf,mbedtls_x509_crt * crt509_ca,const char * ca_crt,size_t ca_len,mbedtls_x509_crt * crt509_cli,const char * cli_crt,size_t cli_len,mbedtls_pk_context * pk_cli,const char * cli_key,size_t key_len,const char * cli_pwd,size_t pwd_len)310 static int _ssl_client_init(mbedtls_ssl_context *ssl,
311                             mbedtls_net_context *tcp_fd,
312                             mbedtls_ssl_config *conf,
313                             mbedtls_x509_crt *crt509_ca, const char *ca_crt,
314                             size_t ca_len, mbedtls_x509_crt *crt509_cli,
315                             const char *cli_crt, size_t cli_len,
316                             mbedtls_pk_context *pk_cli, const char *cli_key,
317                             size_t key_len, const char *cli_pwd, size_t pwd_len)
318 {
319     int ret = -1;
320 
321     /*
322      * 0. Initialize the RNG and the session data
323      */
324 #if defined(MBEDTLS_DEBUG_C)
325     mbedtls_debug_set_threshold((int)DEBUG_LEVEL);
326 #endif
327     aos_srand((uint32_t)aos_now_ms());
328 
329     mbedtls_net_init(tcp_fd);
330     mbedtls_ssl_init(ssl);
331     mbedtls_ssl_config_init(conf);
332     mbedtls_x509_crt_init(crt509_ca);
333     _aos_srand(aos_now_ms());
334     /*verify_source->trusted_ca_crt==NULL
335      * 0. Initialize certificates
336      */
337     platform_info("Loading the CA root certificate ...");
338     if (NULL != ca_crt) {
339         ret = mbedtls_x509_crt_parse(
340                       crt509_ca, (const unsigned char *)ca_crt, ca_len);
341         if (ret != 0) {
342             platform_err(" failed ! x509parse_crt returned -0x%04x", -ret);
343             return ret;
344         }
345     }
346     platform_info(" ok (%d skipped)", ret);
347 
348     /* Setup Client Cert/Key */
349 #if defined(MBEDTLS_X509_CRT_PARSE_C)
350 #if defined(MBEDTLS_CERTS_C)
351     mbedtls_x509_crt_init(crt509_cli);
352     mbedtls_pk_init(pk_cli);
353 #endif
354     if (cli_crt != NULL && cli_key != NULL) {
355 #if defined(MBEDTLS_CERTS_C)
356         platform_info("start prepare client cert .");
357         ret = mbedtls_x509_crt_parse(crt509_cli, (const unsigned char *)cli_crt,
358                                      cli_len);
359 #else
360         {
361             ret = 1;
362             platform_err("MBEDTLS_CERTS_C not defined.");
363         }
364 #endif
365         if (ret != 0) {
366             platform_err(" failed!  mbedtls_x509_crt_parse returned -0x%x\n",
367                          -ret);
368             return ret;
369         }
370 
371 #if defined(MBEDTLS_CERTS_C)
372         platform_info("start mbedtls_pk_parse_key[%s]", cli_pwd);
373         ret = mbedtls_pk_parse_key(pk_cli, (const unsigned char *)cli_key,
374                                    key_len, (const unsigned char *)cli_pwd,
375                                    pwd_len);
376 #else
377         {
378             ret = 1;
379             platform_err("MBEDTLS_CERTS_C not defined.");
380         }
381 #endif
382 
383         if (ret != 0) {
384             platform_err(" failed\n  !  mbedtls_pk_parse_key returned -0x%x\n",
385                          -ret);
386             return ret;
387         }
388     }
389 #endif /* MBEDTLS_X509_CRT_PARSE_C */
390 
391     return 0;
392 }
393 
394 /**
395  * @brief This function connects to the specific SSL server with TLS, and
396  * returns a value that indicates whether the connection is create successfully
397  * or not. Call #NewNetwork() to initialize network structure before calling
398  * this function.
399  * @param[in] n is the the network structure pointer.
400  * @param[in] addr is the Server Host name or IP address.
401  * @param[in] port is the Server Port.
402  * @param[in] ca_crt is the Server's CA certification.
403  * @param[in] ca_crt_len is the length of Server's CA certification.
404  * @param[in] client_crt is the client certification.
405  * @param[in] client_crt_len is the length of client certification.
406  * @param[in] client_key is the client key.
407  * @param[in] client_key_len is the length of client key.
408  * @param[in] client_pwd is the password of client key.
409  * @param[in] client_pwd_len is the length of client key's password.
410  * @sa #NewNetwork();
411  * @return If the return value is 0, the connection is created successfully. If
412  * the return value is -1, then calling lwIP #socket() has failed. If the return
413  * value is -2, then calling lwIP #connect() has failed. Any other value
414  * indicates that calling lwIP #getaddrinfo() has failed.
415  */
_TLSConnectNetwork(TLSDataParams_t * pTlsData,const char * addr,const char * port,const char * ca_crt,size_t ca_crt_len,const char * client_crt,size_t client_crt_len,const char * client_key,size_t client_key_len,const char * client_pwd,size_t client_pwd_len)416 static int _TLSConnectNetwork(TLSDataParams_t *pTlsData, const char *addr,
417                               const char *port, const char *ca_crt,
418                               size_t ca_crt_len, const char *client_crt,
419                               size_t client_crt_len, const char *client_key,
420                               size_t client_key_len, const char *client_pwd,
421                               size_t client_pwd_len)
422 {
423     int ret = -1;
424     /*
425      * 0. Init
426      */
427     ret = _ssl_client_init(&(pTlsData->ssl), &(pTlsData->fd),
428                            &(pTlsData->conf), &(pTlsData->cacertl), ca_crt,
429                            ca_crt_len, &(pTlsData->clicert), client_crt,
430                            client_crt_len, &(pTlsData->pkey), client_key,
431                            client_key_len, client_pwd, client_pwd_len);
432     if (ret != 0) {
433         platform_err(" failed ! ssl_client_init returned -0x%04x", -ret);
434         return ret;
435     }
436 
437     /*
438      * 1. Start the connection
439      */
440     platform_info("Connecting to /%s/%s...", addr, port);
441     do {
442         ret = mbedtls_net_connect(&(pTlsData->fd), addr, port,
443                                   MBEDTLS_NET_PROTO_TCP);
444         if (ret == 0) {
445             break;
446         }
447 
448         platform_err(" connect failed ! net_connect returned -0x%04x", -ret);
449 #if defined(HAL_TLS_DNS_ENHANCE)
450         ret = mbedtls_net_connect_timeout_backup(&(pTlsData->fd), addr, port,
451                                                  MBEDTLS_NET_PROTO_TCP,
452                                                  SEND_TIMEOUT_SECONDS);
453         if (ret == 0) {
454             break;
455         }
456         platform_err(" backup failed ! net_connect returned -0x%04x", -ret);
457 #endif
458 
459 #ifdef AOS_COMP_UND
460         if (ret == MBEDTLS_ERR_NET_UNKNOWN_HOST) {
461             und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
462                               UND_STATIS_NETWORK_DNS_FIAL_REASON);
463         } else {
464             und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
465                               UND_STATIS_NETWORK_TCP_FAIL_REASON);
466         }
467 #endif
468         return ret;
469     } while (0);
470 
471     platform_info(" ok");
472 
473     /*
474      * 2. Setup stuff
475      */
476     platform_info("  . Setting up the SSL/TLS structure...");
477     ret = mbedtls_ssl_config_defaults(
478              &(pTlsData->conf), MBEDTLS_SSL_IS_CLIENT,
479              MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
480     if (ret != 0) {
481         platform_err(" failed! mbedtls_ssl_config_defaults returned %d", ret);
482 #ifdef AOS_COMP_UND
483         und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
484                           UND_STATIS_NETWORK_TLS_FAIL_REASON);
485 #endif
486         return ret;
487     }
488 
489     mbedtls_ssl_conf_max_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
490                                  MBEDTLS_SSL_MINOR_VERSION_3);
491     mbedtls_ssl_conf_min_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
492                                  MBEDTLS_SSL_MINOR_VERSION_3);
493 
494     platform_info(" ok");
495 
496     /* OPTIONAL is not optimal for security, but makes interop easier in this
497      * simplified example */
498     if (ca_crt != NULL) {
499 #if defined(FORCE_SSL_VERIFY)
500         mbedtls_ssl_conf_authmode(&(pTlsData->conf),
501                                   MBEDTLS_SSL_VERIFY_REQUIRED);
502 #else
503         mbedtls_ssl_conf_authmode(&(pTlsData->conf),
504                                   MBEDTLS_SSL_VERIFY_OPTIONAL);
505 #endif
506     } else {
507         mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_NONE);
508     }
509 
510 #if defined(MBEDTLS_X509_CRT_PARSE_C)
511     mbedtls_ssl_conf_ca_chain(&(pTlsData->conf), &(pTlsData->cacertl), NULL);
512 
513     ret = mbedtls_ssl_conf_own_cert(
514              &(pTlsData->conf), &(pTlsData->clicert), &(pTlsData->pkey));
515     if (ret != 0) {
516         platform_err(" failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n",
517                      ret);
518 #ifdef AOS_COMP_UND
519         und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
520                           UND_STATIS_NETWORK_TLS_FAIL_REASON);
521 #endif
522         return ret;
523     }
524 #endif
525     mbedtls_ssl_conf_rng(&(pTlsData->conf), _ssl_random, NULL);
526     mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, NULL);
527     /* mbedtls_ssl_conf_dbg( &(pTlsData->conf), _ssl_debug, stdout ); */
528 
529     ret = mbedtls_ssl_setup(&(pTlsData->ssl), &(pTlsData->conf));
530     if (ret != 0) {
531         platform_err("failed! mbedtls_ssl_setup returned %d", ret);
532 #ifdef AOS_COMP_UND
533         und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
534                           UND_STATIS_NETWORK_TLS_FAIL_REASON);
535 #endif
536         return ret;
537     }
538 #if defined(ON_PRE) || defined(ON_DAILY)
539     platform_err(
540         "SKIPPING mbedtls_ssl_set_hostname() when ON_PRE or ON_DAILY defined!");
541 #else
542     mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr);
543 #endif
544     mbedtls_ssl_set_bio(&(pTlsData->ssl), &(pTlsData->fd), mbedtls_net_send,
545                         mbedtls_net_recv, mbedtls_net_recv_timeout);
546 
547 #if defined(TLS_SAVE_TICKET)
548     if (NULL == saved_session) {
549         do {
550             int len = TLS_MAX_SESSION_BUF;
551             unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF);
552             char key_buf[KEY_MAX_LEN] = { 0 };
553             if (save_buf == NULL) {
554                 printf(" malloc failed\r\n");
555                 break;
556             }
557 
558             saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
559 
560             if (saved_session == NULL) {
561                 printf(" malloc failed\r\n");
562                 HAL_Free(save_buf);
563                 save_buf = NULL;
564                 break;
565             }
566 
567             memset(save_buf, 0x00, TLS_MAX_SESSION_BUF);
568             memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
569             HAL_Snprintf(key_buf, KEY_MAX_LEN - 1, KV_SESSION_KEY_FMT, addr);
570             ret = HAL_Kv_Get(key_buf, save_buf, &len);
571 
572             if (ret != 0 || len == 0) {
573                 printf(" kv get failed len=%d,ret = %d\r\n", len, ret);
574                 HAL_Free(saved_session);
575                 HAL_Free(save_buf);
576                 save_buf = NULL;
577                 saved_session = NULL;
578                 break;
579             }
580             ret = ssl_deserialize_session(saved_session, save_buf, len);
581             if (ret < 0) {
582                 printf("ssl_deserialize_session err,ret = %d\r\n", ret);
583                 HAL_Free(saved_session);
584                 HAL_Free(save_buf);
585                 save_buf = NULL;
586                 saved_session = NULL;
587                 break;
588             }
589             HAL_Free(save_buf);
590         } while (0);
591     }
592 
593     if (NULL != saved_session) {
594         mbedtls_ssl_set_session(&(pTlsData->ssl), saved_session);
595         printf("use saved session!!\r\n");
596     }
597 #endif
598     /*
599      * 4. Handshake
600      */
601     mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), 10000);
602     platform_info("Performing the SSL/TLS handshake...");
603 
604     while ((ret = mbedtls_ssl_handshake(&(pTlsData->ssl))) != 0) {
605         if ((ret != MBEDTLS_ERR_SSL_WANT_READ) &&
606             (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
607             platform_err("failed  ! mbedtls_ssl_handshake returned -0x%04x",
608                          -ret);
609 #ifdef AOS_COMP_UND
610             und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
611                               UND_STATIS_NETWORK_TLS_FAIL_REASON);
612 #endif
613 #if defined(TLS_SAVE_TICKET)
614             if (saved_session != NULL) {
615                 mbedtls_ssl_session_free(saved_session);
616                 HAL_Free(saved_session);
617                 saved_session = NULL;
618             }
619 #endif
620             return ret;
621         }
622     }
623     platform_info(" ok");
624 
625 #if defined(TLS_SAVE_TICKET)
626     do {
627         size_t real_session_len = 0;
628         mbedtls_ssl_session *new_session = NULL;
629 
630         new_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
631         if (NULL == new_session) {
632             break;
633         }
634 
635         memset(new_session, 0x00, sizeof(mbedtls_ssl_session));
636 
637         ret = mbedtls_ssl_get_session(&(pTlsData->ssl), new_session);
638         if (ret != 0) {
639             HAL_Free(new_session);
640             break;
641         }
642         if (saved_session == NULL) {
643             ret = 1;
644         } else if (new_session->ticket_len != saved_session->ticket_len) {
645             ret = 1;
646         } else {
647             ret = memcmp(new_session->ticket, saved_session->ticket,
648                          new_session->ticket_len);
649         }
650         if (ret != 0) {
651             unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF);
652             if (save_buf == NULL) {
653                 mbedtls_ssl_session_free(new_session);
654                 HAL_Free(new_session);
655                 new_session = NULL;
656                 break;
657             }
658             memset(save_buf, 0x00, sizeof(TLS_MAX_SESSION_BUF));
659             ret = ssl_serialize_session(new_session, save_buf,
660                                         TLS_MAX_SESSION_BUF, &real_session_len);
661             printf(
662                 "mbedtls_ssl_get_session_session return 0x%04x real_len=%d\r\n",
663                 ret, (int)real_session_len);
664             if (ret == 0) {
665                 char key_buf[KEY_MAX_LEN] = { 0 };
666                 HAL_Snprintf(key_buf, KEY_MAX_LEN - 1, KV_SESSION_KEY_FMT,
667                              addr);
668                 ret =
669                     HAL_Kv_Set(key_buf, (void *)save_buf, real_session_len, 1);
670                 if (ret < 0) {
671                     printf("save ticket to kv failed ret =%d ,len = %d\r\n",
672                            ret, (int)real_session_len);
673                 }
674             }
675             HAL_Free(save_buf);
676         }
677         mbedtls_ssl_session_free(new_session);
678         HAL_Free(new_session);
679     } while (0);
680     if (saved_session != NULL) {
681         mbedtls_ssl_session_free(saved_session);
682         HAL_Free(saved_session);
683         saved_session = NULL;
684     }
685 #endif
686     /*
687      * 5. Verify the server certificate
688      */
689     platform_info("  . Verifying peer X.509 certificate..");
690     ret = _real_confirm(
691                   mbedtls_ssl_get_verify_result(&(pTlsData->ssl)));
692     if (ret != 0) {
693         platform_err(" failed  ! verify result not confirmed.");
694 #ifdef AOS_COMP_UND
695         und_update_statis(UND_STATIS_NETWORK_FAIL_IDX,
696                           UND_STATIS_NETWORK_TLS_FAIL_REASON);
697 #endif
698         return ret;
699     }
700     /* n->my_socket = (int)((n->tlsdataparams.fd).fd); */
701     /* WRITE_IOT_DEBUG_LOG("my_socket=%d", n->my_socket); */
702 
703     return 0;
704 }
705 
_network_ssl_read(TLSDataParams_t * pTlsData,char * buffer,int len,int timeout_ms)706 static int _network_ssl_read(TLSDataParams_t *pTlsData, char *buffer, int len,
707                              int timeout_ms)
708 {
709     uint32_t readLen = 0;
710     static int net_status = 0;
711     int ret = -1;
712 
713     uint32_t cur_time = HAL_UptimeMs();
714     uint32_t expire_time = cur_time + timeout_ms;
715     mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), timeout_ms);
716 
717     while (readLen < len) {
718         ret = mbedtls_ssl_read(&(pTlsData->ssl),
719                                (unsigned char *)(buffer + readLen),
720                                (len - readLen));
721         if (ret > 0) {
722             readLen += ret;
723             net_status = 0;
724         } else if (ret == 0) {
725             /* if ret is 0 and net_status is -2, indicate the connection is
726              * closed during last call */
727             if (net_status == -2) {
728 #ifdef AOS_COMP_UND
729                 und_update_statis(UND_STATIS_NETWORK_EXCEPTION_IDX,
730                                   UND_STATIS_NETWORK_RD_EXCEPTION_REASON);
731 #endif
732             }
733             return (net_status == -2) ? net_status : readLen;
734         } else {
735             if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret) {
736                 // mbedtls_strerror(ret, err_str, sizeof(err_str));
737                 platform_err("ssl recv error: code = %d", ret);
738                 net_status = -2; /* connection is closed */
739 #ifdef AOS_COMP_UND
740                 und_update_statis(UND_STATIS_NETWORK_EXCEPTION_IDX,
741                                   UND_STATIS_NETWORK_RD_EXCEPTION_REASON);
742 #endif
743                 break;
744 #ifdef CSP_LINUXHOST
745             } else if (MBEDTLS_ERR_SSL_WANT_READ == ret && errno == EINTR) {
746                 cur_time = HAL_UptimeMs();
747                 if ((cur_time - expire_time) < (UINT32_MAX / 2)) {
748                     return readLen;
749                 }
750                 HAL_SleepMs(10);
751                 continue;
752 
753 #endif
754             } else if ((MBEDTLS_ERR_SSL_TIMEOUT == ret) ||
755                        (MBEDTLS_ERR_SSL_CONN_EOF == ret) ||
756                        (MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED == ret) ||
757                        (MBEDTLS_ERR_SSL_WANT_READ == ret) ||
758                        (MBEDTLS_ERR_SSL_NON_FATAL == ret)) {
759                 /* read already complete */
760                 /* if call mbedtls_ssl_read again, it will return 0 (means EOF)
761                  */
762                 return readLen;
763             }
764 
765             else {
766                 // mbedtls_strerror(ret, err_str, sizeof(err_str));
767                 platform_err("ssl recv error: code = %d", ret);
768 #ifdef AOS_COMP_UND
769                 und_update_statis(UND_STATIS_NETWORK_EXCEPTION_IDX,
770                                   UND_STATIS_NETWORK_RD_EXCEPTION_REASON);
771 #endif
772                 net_status = -1;
773                 return -1; /* Connection error */
774             }
775         }
776     }
777 
778     return (readLen > 0) ? readLen : net_status;
779 }
780 
_network_ssl_write(TLSDataParams_t * pTlsData,const char * buffer,int len,int timeout_ms)781 static int _network_ssl_write(TLSDataParams_t *pTlsData, const char *buffer,
782                               int len, int timeout_ms)
783 {
784     uint32_t writtenLen = 0;
785     int ret = -1;
786 
787     while (writtenLen < len) {
788         ret = mbedtls_ssl_write(&(pTlsData->ssl),
789                                 (unsigned char *)(buffer + writtenLen),
790                                 (len - writtenLen));
791         if (ret > 0) {
792             writtenLen += ret;
793             continue;
794         } else if (ret == 0) {
795 #ifdef AOS_COMP_UND
796             und_update_statis(UND_STATIS_NETWORK_EXCEPTION_IDX,
797                               UND_STATIS_NETWORK_WR_EXCEPTION_REASON);
798 #endif
799             platform_err("ssl write timeout");
800             return 0;
801         } else {
802             // mbedtls_strerror(ret, err_str, sizeof(err_str));
803 #ifdef AOS_COMP_UND
804             und_update_statis(UND_STATIS_NETWORK_EXCEPTION_IDX,
805                               UND_STATIS_NETWORK_WR_EXCEPTION_REASON);
806 #endif
807             platform_err("ssl write fail, code=%d", ret);
808             return -1; /* Connnection error */
809         }
810     }
811 
812     return writtenLen;
813 }
814 
_network_ssl_disconnect(TLSDataParams_t * pTlsData)815 static void _network_ssl_disconnect(TLSDataParams_t *pTlsData)
816 {
817     mbedtls_ssl_close_notify(&(pTlsData->ssl));
818     mbedtls_net_free(&(pTlsData->fd));
819 #if defined(MBEDTLS_X509_CRT_PARSE_C)
820     mbedtls_x509_crt_free(&(pTlsData->cacertl));
821     if ((pTlsData->pkey).pk_info != NULL) {
822         platform_info("need release client crt&key");
823 #if defined(MBEDTLS_CERTS_C)
824         mbedtls_x509_crt_free(&(pTlsData->clicert));
825         mbedtls_pk_free(&(pTlsData->pkey));
826 #endif
827     }
828 #endif
829     mbedtls_ssl_free(&(pTlsData->ssl));
830     mbedtls_ssl_config_free(&(pTlsData->conf));
831     platform_info("ssl_disconnect");
832 }
833 
HAL_SSL_Read(uintptr_t handle,char * buf,int len,int timeout_ms)834 int32_t HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms)
835 {
836     return _network_ssl_read((TLSDataParams_t *)handle, buf, len, timeout_ms);
837 }
838 
HAL_SSL_Write(uintptr_t handle,const char * buf,int len,int timeout_ms)839 int32_t HAL_SSL_Write(uintptr_t handle, const char *buf, int len,
840                       int timeout_ms)
841 {
842     return _network_ssl_write((TLSDataParams_t *)handle, buf, len, timeout_ms);
843 }
844 
HAL_SSL_Destroy(uintptr_t handle)845 int32_t HAL_SSL_Destroy(uintptr_t handle)
846 {
847     if ((uintptr_t)NULL == handle) {
848         platform_err("handle is NULL");
849         return 0;
850     }
851 
852 #ifdef AOS_COMP_UND
853     und_update_statis(UND_STATIS_NETWORK_EXCEPTION_IDX,
854                       UND_STATIS_NETWORK_PING_EXCEPTION_REASON);
855 #endif
856     _network_ssl_disconnect((TLSDataParams_t *)handle);
857     aos_free((void *)handle);
858     return 0;
859 }
860 
HAL_SSL_Establish(const char * host,uint16_t port,const char * ca_crt,size_t ca_crt_len)861 uintptr_t HAL_SSL_Establish(const char *host, uint16_t port, const char *ca_crt,
862                             size_t ca_crt_len)
863 {
864     char port_str[6];
865     TLSDataParams_pt pTlsData;
866 
867     pTlsData = aos_malloc(sizeof(TLSDataParams_t));
868     if (NULL == pTlsData) {
869         return (uintptr_t)NULL;
870     }
871     memset(pTlsData, 0x0, sizeof(TLSDataParams_t));
872 
873     sprintf(port_str, "%u", port);
874 
875     if (0 != _TLSConnectNetwork(pTlsData, host, port_str, ca_crt, ca_crt_len,
876                                 NULL, 0, NULL, 0, NULL, 0)) {
877         _network_ssl_disconnect(pTlsData);
878         aos_free((void *)pTlsData);
879         return (uintptr_t)NULL;
880     }
881 
882     return (uintptr_t)pTlsData;
883 }
884