/* * Copyright (C) 2015-2018 Alibaba Group Holding Limited */ //#include #include //#include #include #include #if defined(_PLATFORM_IS_LINUX_) #include #include #include #include #include #include #include #include #include #include #endif #include "infra_config.h" #include "infra_compat.h" #include "mbedtls/error.h" #include "mbedtls/ssl.h" #include "mbedtls/net.h" #include "mbedtls/x509_crt.h" #include "mbedtls/pk.h" #include "mbedtls/debug.h" #include "mbedtls/platform.h" //#include "wrappers.h" #include "wrappers_defs.h" #include "infra_sha256.h" #include "infra_string.h" #include #define SEND_TIMEOUT_SECONDS (10) #ifndef CONFIG_MBEDTLS_DEBUG_LEVEL #define CONFIG_MBEDTLS_DEBUG_LEVEL 0 #endif #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 //add by tcq /* extern int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), */ /* void (*free_func)(void *)); */ typedef struct _TLSDataParams { mbedtls_ssl_context ssl; /**< mbed TLS control context. */ mbedtls_net_context fd; /**< mbed TLS network context. */ mbedtls_ssl_config conf; /**< mbed TLS configuration context. */ mbedtls_x509_crt cacertl; /**< mbed TLS CA certification. */ mbedtls_x509_crt clicert; /**< mbed TLS Client certification. */ mbedtls_pk_context pkey; /**< mbed TLS Client key. */ } TLSDataParams_t, *TLSDataParams_pt; static unsigned int mbedtls_mem_used = 0; static unsigned int mbedtls_max_mem_used = 0; static ssl_hooks_t g_ssl_hooks = {HAL_Malloc, HAL_Free}; #define MBEDTLS_MEM_INFO_MAGIC 0x12345678 typedef struct { int magic; int size; } mbedtls_mem_info_t; #define TLS_AUTH_MODE_CA 0 #define TLS_AUTH_MODE_PSK 1 #ifndef TLS_AUTH_MODE #define TLS_AUTH_MODE TLS_AUTH_MODE_CA #endif #if defined(TLS_SAVE_TICKET) #define KEY_MAX_LEN 64 #define TLS_MAX_SESSION_BUF 384 #define KV_SESSION_KEY_FMT "TLS_%s" extern int HAL_Kv_Set(const char *key, const void *val, int len, int sync); extern int HAL_Kv_Get(const char *key, void *val, int *buffer_len); static mbedtls_ssl_session *saved_session = NULL; static int ssl_serialize_session(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; size_t left = buf_len; if (left < sizeof(mbedtls_ssl_session)) { return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL); } memcpy(p, session, sizeof(mbedtls_ssl_session)); p += sizeof(mbedtls_ssl_session); left -= sizeof(mbedtls_ssl_session); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if (left < sizeof(mbedtls_ssl_session)) { return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL); } memcpy(p, session->ticket, session->ticket_len); p += session->ticket_len; left -= session->ticket_len; #endif *olen = p - buf; return (0); } static int ssl_deserialize_session(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char *const end = buf + len; if (sizeof(mbedtls_ssl_session) > (size_t)(end - p)) { return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA); } memcpy(session, p, sizeof(mbedtls_ssl_session)); p += sizeof(mbedtls_ssl_session); #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) session->peer_cert = NULL; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if (session->ticket_len > 0) { if (session->ticket_len > (size_t)(end - p)) { return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA); } session->ticket = HAL_Malloc(session->ticket_len); if (session->ticket == NULL) { return (MBEDTLS_ERR_SSL_ALLOC_FAILED); } memcpy(session->ticket, p, session->ticket_len); p += session->ticket_len; printf("saved ticket len = %d \r\n", (int)session->ticket_len); } #endif if (p != end) { return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA); } return (0); } #endif static void _srand(unsigned int seed) { #ifdef HAL_KV #define SEED_MAGIC 0x123 int ret = 0; int seed_len = 0; unsigned int seed_val = 0; static char *g_seed_key = "seed_key"; seed_len = sizeof(seed_val); ret = HAL_Kv_Get(g_seed_key, &seed_val, &seed_len); if (ret) { seed_val = SEED_MAGIC; } seed_val += seed; HAL_Srandom(seed_val); seed_val = rand(); HAL_Kv_Set(g_seed_key, &seed_val, sizeof(seed_val), 1); #else HAL_Srandom(seed); #endif } static int _ssl_random(void *p_rng, unsigned char *output, size_t output_len) { uint32_t rnglen = output_len; uint8_t rngoffset = 0; while (rnglen > 0) { *(output + rngoffset) = (unsigned char)HAL_Random(0); rngoffset++; rnglen--; } return 0; } static void _ssl_debug(void *ctx, int level, const char *file, int line, const char *str) { ((void) level); if (NULL != ctx) { #if 0 fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str); fflush((FILE *) ctx); #endif printf("%s\n", str); } } static int _real_confirm(int verify_result) { printf("certificate verification result: 0x%02x\n", verify_result); #if defined(FORCE_SSL_VERIFY) if ((verify_result & MBEDTLS_X509_BADCERT_EXPIRED) != 0) { printf("! fail ! ERROR_CERTIFICATE_EXPIRED\n"); return -1; } if ((verify_result & MBEDTLS_X509_BADCERT_REVOKED) != 0) { printf("! fail ! server certificate has been revoked\n"); return -1; } if ((verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) { printf("! fail ! CN mismatch\n"); return -1; } if ((verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) { printf("! fail ! self-signed or not signed by a trusted CA\n"); return -1; } #endif return 0; } static int _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 ) { int ret = -1; /* * 0. Initialize the RNG and the session data */ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold((int)CONFIG_MBEDTLS_DEBUG_LEVEL); #endif mbedtls_net_init(tcp_fd); mbedtls_ssl_init(ssl); mbedtls_ssl_config_init(conf); _srand(HAL_UptimeMs()); /* Setup Client Cert/Key */ #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) mbedtls_x509_crt_init(crt509_ca); /*verify_source->trusted_ca_crt==NULL * 0. Initialize certificates */ printf("Loading the CA root certificate ...\n"); if (NULL != ca_crt) { if (0 != (ret = mbedtls_x509_crt_parse(crt509_ca, (const unsigned char *)ca_crt, ca_len))) { printf(" failed ! x509parse_crt returned -0x%04x\n", -ret); return ret; } } printf(" ok (%d skipped)\n", ret); #if defined(MBEDTLS_CERTS_C) mbedtls_x509_crt_init(crt509_cli); mbedtls_pk_init(pk_cli); #endif if (cli_crt != NULL && cli_key != NULL) { #if defined(MBEDTLS_CERTS_C) printf("start prepare client cert .\n"); ret = mbedtls_x509_crt_parse(crt509_cli, (const unsigned char *) cli_crt, cli_len); #else { ret = 1; printf("MBEDTLS_CERTS_C not defined.\n"); } #endif if (ret != 0) { printf(" failed! mbedtls_x509_crt_parse returned -0x%x\n", -ret); return ret; } #if defined(MBEDTLS_CERTS_C) printf("start mbedtls_pk_parse_key[%s]\n", cli_pwd); ret = mbedtls_pk_parse_key(pk_cli, (const unsigned char *) cli_key, key_len, (const unsigned char *) cli_pwd, pwd_len); #else { ret = 1; printf("MBEDTLS_CERTS_C not defined.\n"); } #endif if (ret != 0) { printf(" failed\n ! mbedtls_pk_parse_key returned -0x%x\n", -ret); return ret; } } #endif /* if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) */ return 0; } #if defined(_PLATFORM_IS_LINUX_) static int net_prepare(void) { #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ !defined(EFI32) WSADATA wsaData; static int wsa_init_done = 0; if (wsa_init_done == 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { return (MBEDTLS_ERR_NET_SOCKET_FAILED); } wsa_init_done = 1; } #else #if !defined(EFIX64) && !defined(EFI32) signal(SIGPIPE, SIG_IGN); #endif #endif return (0); } static int mbedtls_net_connect_timeout(mbedtls_net_context *ctx, const char *host, const char *port, int proto, unsigned int timeout) { int ret; struct addrinfo hints, *addr_list, *cur; struct timeval sendtimeout; uint8_t dns_retry = 0; if ((ret = net_prepare()) != 0) { return (ret); } /* Do name resolution with both IPv6 and IPv4 */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; while (dns_retry++ < 8) { ret = getaddrinfo(host, port, &hints, &addr_list); if (ret != 0) { #if defined(_PLATFORM_IS_LINUX_) if (ret == EAI_AGAIN) { int rc = res_init(); printf("getaddrinfo res_init, rc is %d, errno is %d\n", rc, errno); } #endif printf("getaddrinfo error[%d], res: %s, host: %s, port: %s\n", dns_retry, gai_strerror(ret), host, port); sleep(1); continue; } else { break; } } if (ret != 0) { return (MBEDTLS_ERR_NET_UNKNOWN_HOST); } /* Try the sockaddrs until a connection succeeds */ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; for (cur = addr_list; cur != NULL; cur = cur->ai_next) { char ip4_str[INET_ADDRSTRLEN]; ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); if (ctx->fd < 0) { ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } sendtimeout.tv_sec = timeout; sendtimeout.tv_usec = 0; if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &sendtimeout, sizeof(sendtimeout))) { perror("setsockopt"); printf("setsockopt error\n"); } printf("setsockopt SO_SNDTIMEO timeout: %ds\n", (int)sendtimeout.tv_sec); inet_ntop(AF_INET, &((const struct sockaddr_in *)cur->ai_addr)->sin_addr, ip4_str, INET_ADDRSTRLEN); printf("connecting IP_ADDRESS: %s\n", ip4_str); if (connect(ctx->fd, cur->ai_addr, cur->ai_addrlen) == 0) { ret = 0; break; } close(ctx->fd); ret = MBEDTLS_ERR_NET_CONNECT_FAILED; } freeaddrinfo(addr_list); return (ret); } #endif void *_SSLCalloc_wrapper(size_t n, size_t size) { unsigned char *buf = NULL; mbedtls_mem_info_t *mem_info = NULL; if (n == 0 || size == 0) { return NULL; } buf = (unsigned char *)(g_ssl_hooks.malloc(n * size + sizeof(mbedtls_mem_info_t))); if (NULL == buf) { return NULL; } else { memset(buf, 0, n * size + sizeof(mbedtls_mem_info_t)); } mem_info = (mbedtls_mem_info_t *)buf; mem_info->magic = MBEDTLS_MEM_INFO_MAGIC; mem_info->size = n * size; buf += sizeof(mbedtls_mem_info_t); mbedtls_mem_used += mem_info->size; if (mbedtls_mem_used > mbedtls_max_mem_used) { mbedtls_max_mem_used = mbedtls_mem_used; } /* printf("INFO -- mbedtls malloc: %p %d total used: %d max used: %d\r\n", buf, (int)size, mbedtls_mem_used, mbedtls_max_mem_used); */ return buf; } void _SSLFree_wrapper(void *ptr) { mbedtls_mem_info_t *mem_info = NULL; if (NULL == ptr) { return; } mem_info = (mbedtls_mem_info_t *)((unsigned char *)ptr - sizeof(mbedtls_mem_info_t)); if (mem_info->magic != MBEDTLS_MEM_INFO_MAGIC) { printf("Warning - invalid mem info magic: 0x%x\r\n", mem_info->magic); return; } mbedtls_mem_used -= mem_info->size; /* printf("INFO mbedtls free: %p %d total used: %d max used: %d\r\n", ptr, mem_info->size, mbedtls_mem_used, mbedtls_max_mem_used);*/ g_ssl_hooks.free(mem_info); } /** * @brief This function connects to the specific SSL server with TLS, and returns a value that indicates whether the connection is create successfully or not. Call #NewNetwork() to initialize network structure before calling this function. * @param[in] n is the the network structure pointer. * @param[in] addr is the Server Host name or IP address. * @param[in] port is the Server Port. * @param[in] ca_crt is the Server's CA certification. * @param[in] ca_crt_len is the length of Server's CA certification. * @param[in] client_crt is the client certification. * @param[in] client_crt_len is the length of client certification. * @param[in] client_key is the client key. * @param[in] client_key_len is the length of client key. * @param[in] client_pwd is the password of client key. * @param[in] client_pwd_len is the length of client key's password. * @sa #NewNetwork(); * @return If the return value is 0, the connection is created successfully. If the return value is -1, then calling lwIP #socket() has failed. If the return value is -2, then calling lwIP #connect() has failed. Any other value indicates that calling lwIP #getaddrinfo() has failed. */ static int _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) { #if defined(_PLATFORM_IS_LINUX_) struct in_addr in; #endif /* #if defined(_PLATFORM_IS_LINUX_) */ int ret = -1; /* * 0. Init */ if (0 != (ret = _ssl_client_init(&(pTlsData->ssl), &(pTlsData->fd), &(pTlsData->conf), &(pTlsData->cacertl), ca_crt, ca_crt_len, &(pTlsData->clicert), client_crt, client_crt_len, &(pTlsData->pkey), client_key, client_key_len, client_pwd, client_pwd_len))) { printf(" failed ! ssl_client_init returned -0x%04x\n", -ret); return ret; } /* * 1. Start the connection */ printf("Connecting to /%s/%s...\n", addr, port); #if defined(_PLATFORM_IS_LINUX_) if (0 != (ret = mbedtls_net_connect_timeout(&(pTlsData->fd), addr, port, MBEDTLS_NET_PROTO_TCP, SEND_TIMEOUT_SECONDS))) { printf(" failed ! net_connect returned -0x%04x\n", -ret); return ret; } #else if (0 != (ret = mbedtls_net_connect(&(pTlsData->fd), addr, port, MBEDTLS_NET_PROTO_TCP))) { printf(" failed ! net_connect returned -0x%04x\n", -ret); return ret; } #endif printf(" ok\n"); /* * 2. Setup stuff */ printf(" . Setting up the SSL/TLS structure...\n"); if ((ret = mbedtls_ssl_config_defaults(&(pTlsData->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { printf(" failed! mbedtls_ssl_config_defaults returned %d\n", ret); return ret; } mbedtls_ssl_conf_max_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_min_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); printf(" ok\n"); /* OPTIONAL is not optimal for security, but makes interop easier in this simplified example */ if (ca_crt != NULL) { #if defined(FORCE_SSL_VERIFY) mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_REQUIRED); #else mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); #endif } else { mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_NONE); } #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) mbedtls_ssl_conf_ca_chain(&(pTlsData->conf), &(pTlsData->cacertl), NULL); if ((ret = mbedtls_ssl_conf_own_cert(&(pTlsData->conf), &(pTlsData->clicert), &(pTlsData->pkey))) != 0) { printf(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n", ret); return ret; } #elif (TLS_AUTH_MODE == TLS_AUTH_MODE_PSK) { static const int ciphersuites[1] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA}; char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0}; char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0}; char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0}; char *auth_type = "devicename"; char *sign_method = "hmacsha256"; char *timestamp = "2524608000000"; char *psk_identity = NULL, string_to_sign[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 33] = {0}; uint32_t psk_identity_len = 0; uint8_t sign_hex[32] = {0}; char sign_string[65] = {0}; IOT_Ioctl(IOTX_IOCTL_GET_PRODUCT_KEY, product_key); IOT_Ioctl(IOTX_IOCTL_GET_DEVICE_NAME, device_name); IOT_Ioctl(IOTX_IOCTL_GET_DEVICE_SECRET, device_secret); /* psk identity length */ psk_identity_len = strlen(auth_type) + strlen(sign_method) + strlen(product_key) + strlen(device_name) + strlen( timestamp) + 5; psk_identity = HAL_Malloc(psk_identity_len); if (psk_identity == NULL) { printf("psk_identity malloc failed\n"); return -1; } memset(psk_identity, 0, psk_identity_len); memcpy(psk_identity, auth_type, strlen(auth_type)); memcpy(psk_identity + strlen(psk_identity), "|", strlen("|")); memcpy(psk_identity + strlen(psk_identity), sign_method, strlen(sign_method)); memcpy(psk_identity + strlen(psk_identity), "|", strlen("|")); memcpy(psk_identity + strlen(psk_identity), product_key, strlen(product_key)); memcpy(psk_identity + strlen(psk_identity), "&", strlen("&")); memcpy(psk_identity + strlen(psk_identity), device_name, strlen(device_name)); memcpy(psk_identity + strlen(psk_identity), "|", strlen("|")); memcpy(psk_identity + strlen(psk_identity), timestamp, strlen(timestamp)); /* string to sign */ memcpy(string_to_sign, "id", strlen("id")); memcpy(string_to_sign + strlen(string_to_sign), product_key, strlen(product_key)); memcpy(string_to_sign + strlen(string_to_sign), "&", strlen("&")); memcpy(string_to_sign + strlen(string_to_sign), device_name, strlen(device_name)); memcpy(string_to_sign + strlen(string_to_sign), "timestamp", strlen("timestamp")); memcpy(string_to_sign + strlen(string_to_sign), timestamp, strlen(timestamp)); utils_hmac_sha256((uint8_t *)string_to_sign, strlen(string_to_sign), (uint8_t *)device_secret, strlen(device_secret), sign_hex); infra_hex2str(sign_hex, 32, sign_string); /* printf("psk_identity: %s\n",psk_identity); printf("psk : %s\n",sign_string); */ mbedtls_ssl_conf_psk(&(pTlsData->conf), (const unsigned char *)sign_string, strlen(sign_string), (const unsigned char *)psk_identity, strlen(psk_identity)); mbedtls_ssl_conf_ciphersuites(&(pTlsData->conf), ciphersuites); HAL_Free(psk_identity); printf("mbedtls psk config finished\n"); } #endif /* #elif (TLS_AUTH_MODE == TLS_AUTH_MODE_PSK) */ mbedtls_ssl_conf_rng(&(pTlsData->conf), _ssl_random, NULL); mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, NULL); mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, NULL); if ((ret = mbedtls_ssl_setup(&(pTlsData->ssl), &(pTlsData->conf))) != 0) { printf("failed! mbedtls_ssl_setup returned %d\n", ret); return ret; } #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) #if defined(_PLATFORM_IS_LINUX_) /* only set hostname when addr isn't ip string and hostname isn't preauth_shanghai */ if (inet_aton(addr, &in) == 0 && strcmp("iot-auth-pre.cn-shanghai.aliyuncs.com", addr)) { mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr); } #else if (strcmp("iot-auth-pre.cn-shanghai.aliyuncs.com", addr)) { mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr); } #endif /* #if defined(_PLATFORM_IS_LINUX_) */ #endif /* #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) */ mbedtls_ssl_set_bio(&(pTlsData->ssl), &(pTlsData->fd), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); #if defined(TLS_SAVE_TICKET) if (NULL == saved_session) { do { int len = TLS_MAX_SESSION_BUF; char key_buf[KEY_MAX_LEN] = {0}; unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF); if (save_buf == NULL) { printf(" malloc failed\r\n"); break; } saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session)); if (saved_session == NULL) { printf(" malloc failed\r\n"); HAL_Free(save_buf); save_buf = NULL; break; } memset(save_buf, 0x00, TLS_MAX_SESSION_BUF); memset(saved_session, 0x00, sizeof(mbedtls_ssl_session)); HAL_Snprintf(key_buf, KEY_MAX_LEN - 1, KV_SESSION_KEY_FMT, addr); ret = HAL_Kv_Get(key_buf, save_buf, &len); if (ret != 0 || len == 0) { printf(" kv get failed len=%d,ret = %d\r\n", len, ret); HAL_Free(saved_session); HAL_Free(save_buf); save_buf = NULL; saved_session = NULL; break; } ret = ssl_deserialize_session(saved_session, save_buf, len); if (ret < 0) { printf("ssl_deserialize_session err,ret = %d\r\n", ret); HAL_Free(saved_session); HAL_Free(save_buf); save_buf = NULL; saved_session = NULL; break; } HAL_Free(save_buf); } while (0); } if (NULL != saved_session) { mbedtls_ssl_set_session(&(pTlsData->ssl), saved_session); printf("use saved session!!\r\n"); } #endif /* * 4. Handshake */ mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), 10000); printf("Performing the SSL/TLS handshake...\n"); while ((ret = mbedtls_ssl_handshake(&(pTlsData->ssl))) != 0) { if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { printf("failed ! mbedtls_ssl_handshake returned -0x%04x\n", -ret); #if defined(TLS_SAVE_TICKET) if (saved_session != NULL) { mbedtls_ssl_session_free(saved_session); HAL_Free(saved_session); saved_session = NULL; } #endif return ret; } } printf(" ok\n"); #if defined(TLS_SAVE_TICKET) do { size_t real_session_len = 0; mbedtls_ssl_session *new_session = NULL; new_session = HAL_Malloc(sizeof(mbedtls_ssl_session)); if (NULL == new_session) { break; } memset(new_session, 0x00, sizeof(mbedtls_ssl_session)); ret = mbedtls_ssl_get_session(&(pTlsData->ssl), new_session); if (ret != 0) { HAL_Free(new_session); break; } if (saved_session == NULL) { ret = 1; } else if (new_session->ticket_len != saved_session->ticket_len) { ret = 1; } else { ret = memcmp(new_session->ticket, saved_session->ticket, new_session->ticket_len); } if (ret != 0) { unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF); if (save_buf == NULL) { mbedtls_ssl_session_free(new_session); HAL_Free(new_session); new_session = NULL; break; } memset(save_buf, 0x00, sizeof(TLS_MAX_SESSION_BUF)); ret = ssl_serialize_session(new_session, save_buf, TLS_MAX_SESSION_BUF, &real_session_len); printf("mbedtls_ssl_get_session_session return 0x%04x real_len=%d\r\n", ret, (int)real_session_len); if (ret == 0) { char key_buf[KEY_MAX_LEN] = {0}; HAL_Snprintf(key_buf, KEY_MAX_LEN - 1, KV_SESSION_KEY_FMT, addr); ret = HAL_Kv_Set(key_buf, (void *)save_buf, real_session_len, 1); if (ret < 0) { printf("save ticket to kv failed ret =%d ,len = %d\r\n", ret, (int)real_session_len); } } HAL_Free(save_buf); } mbedtls_ssl_session_free(new_session); HAL_Free(new_session); } while (0); if (saved_session != NULL) { mbedtls_ssl_session_free(saved_session); HAL_Free(saved_session); saved_session = NULL; } #endif /* * 5. Verify the server certificate */ printf(" . Verifying peer X.509 certificate..\n"); if (0 != (ret = _real_confirm(mbedtls_ssl_get_verify_result(&(pTlsData->ssl))))) { printf(" failed ! verify result not confirmed.\n"); return ret; } /* n->my_socket = (int)((n->tlsdataparams.fd).fd); */ /* WRITE_IOT_DEBUG_LOG("my_socket=%d", n->my_socket); */ return 0; } static int _network_ssl_read(TLSDataParams_t *pTlsData, char *buffer, int len, int timeout_ms) { uint32_t readLen = 0; static int net_status = 0; int ret = -1; char err_str[33]; mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), timeout_ms); while (readLen < len) { ret = mbedtls_ssl_read(&(pTlsData->ssl), (unsigned char *)(buffer + readLen), (len - readLen)); if (ret > 0) { readLen += ret; net_status = 0; } else if (ret == 0) { /* if ret is 0 and net_status is -2, indicate the connection is closed during last call */ return (net_status == -2) ? net_status : readLen; } else { if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret) { #if defined(MBEDTLS_ERROR_C) mbedtls_strerror(ret, err_str, sizeof(err_str)); #endif printf("ssl recv error: code = -0x%04X, err_str = '%s'\n", -ret, err_str); net_status = -2; /* connection is closed */ break; } else if ((MBEDTLS_ERR_SSL_TIMEOUT == ret) || (MBEDTLS_ERR_SSL_CONN_EOF == ret) || (MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED == ret) || (MBEDTLS_ERR_SSL_NON_FATAL == ret)) { /* read already complete */ /* if call mbedtls_ssl_read again, it will return 0 (means EOF) */ return readLen; } else { #if defined(MBEDTLS_ERROR_C) mbedtls_strerror(ret, err_str, sizeof(err_str)); #endif printf("ssl recv error: code = -0x%04X, err_str = '%s'\n", -ret, err_str); net_status = -1; return -1; /* Connection error */ } } } return (readLen > 0) ? readLen : net_status; } static int _network_ssl_write(TLSDataParams_t *pTlsData, const char *buffer, int len, int timeout_ms) { #if defined(_PLATFORM_IS_LINUX_) int32_t res = 0; int32_t write_bytes = 0; uint64_t timestart_ms = 0, timenow_ms = 0; struct timeval timestart, timenow, timeout; if (pTlsData == NULL) { return -1; } /* timeout */ timeout.tv_sec = timeout_ms / 1000; timeout.tv_usec = (timeout_ms % 1000) * 1000; /* Start Time */ gettimeofday(×tart, NULL); timestart_ms = timestart.tv_sec * 1000 + timestart.tv_usec / 1000; timenow_ms = timestart_ms; res = setsockopt(pTlsData->fd.fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); if (res < 0) { return -1; } do { gettimeofday(&timenow, NULL); timenow_ms = timenow.tv_sec * 1000 + timenow.tv_usec / 1000; if (timenow_ms - timestart_ms >= timenow_ms || timeout_ms - (timenow_ms - timestart_ms) > timeout_ms) { break; } res = mbedtls_ssl_write(&(pTlsData->ssl), (unsigned char *)buffer + write_bytes, len - write_bytes); if (res < 0) { if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE) { if (write_bytes == 0) { return -1; } break; } } else if (res == 0) { break; } else { write_bytes += res; } } while (((timenow_ms - timestart_ms) < timeout_ms) && (write_bytes < len)); return write_bytes; #else uint32_t writtenLen = 0; int ret = -1; if (pTlsData == NULL) { return -1; } while (writtenLen < len) { ret = mbedtls_ssl_write(&(pTlsData->ssl), (unsigned char *)(buffer + writtenLen), (len - writtenLen)); if (ret > 0) { writtenLen += ret; continue; } else if (ret == 0) { printf("ssl write timeout\n"); return 0; } else { char err_str[33]; #if defined(MBEDTLS_ERROR_C) mbedtls_strerror(ret, err_str, sizeof(err_str)); #endif printf("ssl write fail, code=%d, str=%s\n", ret, err_str); return -1; /* Connnection error */ } } return writtenLen; #endif } static void _network_ssl_disconnect(TLSDataParams_t *pTlsData) { mbedtls_ssl_close_notify(&(pTlsData->ssl)); mbedtls_net_free(&(pTlsData->fd)); #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) mbedtls_x509_crt_free(&(pTlsData->cacertl)); if ((pTlsData->pkey).pk_info != NULL) { printf("need release client crt&key\n"); #if defined(MBEDTLS_CERTS_C) mbedtls_x509_crt_free(&(pTlsData->clicert)); mbedtls_pk_free(&(pTlsData->pkey)); #endif } #endif /* #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) */ mbedtls_ssl_free(&(pTlsData->ssl)); mbedtls_ssl_config_free(&(pTlsData->conf)); printf("ssl_disconnect\n"); } int ssl_hooks_set(ssl_hooks_t *hooks) { if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) { return -1; } g_ssl_hooks.malloc = hooks->malloc; g_ssl_hooks.free = hooks->free; return 0; } const char *g_cli_crt = \ { \ "-----BEGIN CERTIFICATE-----\r\n" "MIIDhzCCAm+gAwIBAgIHNHa/qHDMmTANBgkqhkiG9w0BAQsFADBTMSgwJgYDVQQD\r\n" "DB9BbGliYWJhIENsb3VkIElvVCBPcGVyYXRpb24gQ0ExMRowGAYDVQQKDBFBbGli\r\n" "YWJhIENsb3VkIElvVDELMAkGA1UEBhMCQ04wIBcNMTkxMDE3MDExODE3WhgPMjEx\r\n" "OTEwMTcwMTE4MTdaMFExJjAkBgNVBAMMHUFsaWJhYmEgQ2xvdWQgSW9UIENlcnRp\r\n" "ZmljYXRlMRowGAYDVQQKDBFBbGliYWJhIENsb3VkIElvVDELMAkGA1UEBhMCQ04w\r\n" "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsNkQ57z1lpe/dSQqHmrfm\r\n" "2Hml0YPhac8yXdx1brUqzWg+robUsK8bxyr1yqlTL/aNNT6Kjeq8m8pZv/fEy42o\r\n" "WmQogrJ8nBYCdXGOYmfsdDrcvInkde8jiRLRduW+/aSeGqkWiKoInqvvSFRelGNv\r\n" "N9wZ7uRcL16jJGQFpvlowps/+Lkg6vNiJ0mjKLQRy3bjrwEazLBijfI5oyDQAcXj\r\n" "J4GEdA1vw/ZxQJkrI2ZXp2bfc3q1QciWb8mQDqNIG9DldfRddS2Vj4iDI3TNoFFf\r\n" "PF7eoSbycjaVfXnJY+cflapnwm/1LoCUNEi7ut25PzqP5JJbhV1XYg4A/OED1NRT\r\n" "AgMBAAGjYDBeMB8GA1UdIwQYMBaAFIo3m6hwzdX5SMiXfiGfWW9JjiQRMB0GA1Ud\r\n" "DgQWBBRtrOWad4BnTKm9l5n2scfjaUEoTjAOBgNVHQ8BAf8EBAMCA/gwDAYDVR0T\r\n" "AQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAiug/d0unpbHHtsg6RKrmIK/VLvAd\r\n" "F8Mjkohv8XBxu+8xqIb5JXsUEtdHWDHBXubmQvvh4OIVxByx967fUFT8u/mZFRwl\r\n" "banwK9wQgua3Y5M84k3jnWo3PfKERCOZ0DqY4ARjv8gZnZ1UEzDeslbft9SXwK5F\r\n" "1OtDmwAez+Kr+8Zw/r2bKu70eq5A+KAIF9KJEnLnxNrtAU7cw7BjfNGCYa3DswlC\r\n" "5cEdQe3llFl8RZJtznWdttQt5yJwweMEz9D4ac+aS8Kjiav51MC/DyBc7u4IeDYe\r\n" "1R1ufWK+qRKZKanTqWA3PS0pF54jmSwiRzQanmCST7nyKCIqoZXZJg476g==\r\n" "-----END CERTIFICATE-----\r\n" }; const char *g_cli_key = \ { \ "-----BEGIN RSA PRIVATE KEY-----\r\n" "MIIEpAIBAAKCAQEArDZEOe89ZaXv3UkKh5q35th5pdGD4WnPMl3cdW61Ks1oPq6G\r\n" "1LCvG8cq9cqpUy/2jTU+io3qvJvKWb/3xMuNqFpkKIKyfJwWAnVxjmJn7HQ63LyJ\r\n" "5HXvI4kS0Xblvv2knhqpFoiqCJ6r70hUXpRjbzfcGe7kXC9eoyRkBab5aMKbP/i5\r\n" "IOrzYidJoyi0Ect2468BGsywYo3yOaMg0AHF4yeBhHQNb8P2cUCZKyNmV6dm33N6\r\n" "tUHIlm/JkA6jSBvQ5XX0XXUtlY+IgyN0zaBRXzxe3qEm8nI2lX15yWPnH5WqZ8Jv\r\n" "9S6AlDRIu7rduT86j+SSW4VdV2IOAPzhA9TUUwIDAQABAoIBAEs5LRYtZaFIGX2M\r\n" "kTfooloIxyJiYXwOLv5uN4VoRWSb8uQmcijnwKWemypgSxRWSBkoX9g/44BdgMcx\r\n" "bnYdABTA3y0+4d5Cg+6xBFhQrdqAbtHK3WTZCwt3raunhvWlb8nMFX4NVlCLlsjf\r\n" "zFK/+Ks1OERvsHqACpOyqqo5ZIqYdiJ/onjW2FmR6v6midB2qKch9pyCTZGoxhJb\r\n" "8KgVYUzUoTxLgwwLzOdaZSCieHLJA67GtUDVyLPN0eD8apNlhdmCXCVUMgixNGuE\r\n" "Mz71GHnPi+uLLUUige7m1Qk9qTN/deilRgJ1nOp4AWu7sHbkilVXY7O47C6vFLWv\r\n" "NuGqplECgYEA7xkOfdS1TWbV/wL0QWCQWSagx+EjnpuxxIikyopFB8EOb3GlAN81\r\n" "DQzhmBWbrR8mqfGdjkqGy/XZyQjI7Apyyv1HJlwiPqsihULMs0vHZGxK7aQ7C06/\r\n" "yOgsiS3REF4paTUKqilCB+fpCdT8w1r+sT8APAb5XDP+iWSAVeO7LgsCgYEAuGLH\r\n" "Ye84tH3puN172b80OGqJX9ytDFcML08N0QcBKwjMx9dw6oh3cBNG4bjcjWZPzMSt\r\n" "owUkXuImAfhLmFGp+kyWqs9Soom1m5dTt6/Twwbii9u/243OtpmuKH1Jpg194H3n\r\n" "2ebl4uI1qMQpGXpHNukyKhKCVFNtEvrLwIOJh9kCgYEA1Ri167wqooOm8pOFcsdH\r\n" "n81nuv2Tq4cEVy+Z/9JgV9rerMDS2QYW2DzEy7FmgFOlOA3Z6LnPjfTeV+h2ermN\r\n" "OhGm2i9/be9E4xR4MMy3N2+1EDwxS5CyKbOUDedBz568tcHKcYI4EafF8Tdc2Bg/\r\n" "q2WFJfrpQB4vG/Dw2JwRdaUCgYEAtiV2e0ubg8ni6il54KgeySCNZrKUDF2tfsqk\r\n" "hnpZ8A44Za5xMG7xNjkEy5UX42NPr6QXN7SrskPLciS7YNRDiyy/pis6obBSRErg\r\n" "e9Po6H9Tqv/Bbv2OWBpGzl6+M5ieYfde44ZSUKhQg9CMHUwLL7Z8RM2WDAGB/b7d\r\n" "KueGJDkCgYBJzldXgBqOVDgoWLpcuMSZD8bvHHRsY0RSj3Otx4utKOw4ILEXAIyb\r\n" "d6BpbrZAinsNWOFXfpIeOobgs+VGOYClni4ULmW4XzRtb1n+9AWP33sMjr4xt8Qs\r\n" "fMLnYxXHzu/+uCVEpR3XLL0+bwMDdSqYRL9tc9EkQbvLzvZALl4flA==\r\n" "-----END RSA PRIVATE KEY-----\r\n" }; uintptr_t HAL_SSL_Establish(const char *host, uint16_t port, const char *ca_crt, uint32_t ca_crt_len) { char port_str[6]; const char *alter = host; TLSDataParams_pt pTlsData; if (host == NULL || ca_crt == NULL) { printf("input params are NULL, abort\n"); return 0; } if (!strlen(host) || (strlen(host) < 8)) { printf("invalid host: '%s'(len=%d), abort\n", host, (int)strlen(host)); return 0; } pTlsData = g_ssl_hooks.malloc(sizeof(TLSDataParams_t)); if (NULL == pTlsData) { return (uintptr_t)NULL; } memset(pTlsData, 0x0, sizeof(TLSDataParams_t)); sprintf(port_str, "%u", port); /* mbedtls_platform_set_calloc_free(_SSLCalloc_wrapper, _SSLFree_wrapper); */ if (0 != _TLSConnectNetwork(pTlsData, alter, port_str, ca_crt, ca_crt_len, g_cli_crt, strlen(g_cli_crt) + 1, g_cli_key, strlen(g_cli_key) + 1, NULL, 0)) { _network_ssl_disconnect(pTlsData); g_ssl_hooks.free((void *)pTlsData); return (uintptr_t)NULL; } return (uintptr_t)pTlsData; } int HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms) { return _network_ssl_read((TLSDataParams_t *)handle, buf, len, timeout_ms);; } int HAL_SSL_Write(uintptr_t handle, const char *buf, int len, int timeout_ms) { return _network_ssl_write((TLSDataParams_t *)handle, buf, len, timeout_ms); } int32_t HAL_SSL_Destroy(uintptr_t handle) { if ((uintptr_t)NULL == handle) { printf("handle is NULL\n"); return 0; } _network_ssl_disconnect((TLSDataParams_t *)handle); g_ssl_hooks.free((void *)handle); return 0; }