support aliyun sdk on TencentOS tiny
sample: examples\aliyun_iotkit_csdk_mqtt project: board\TencentOS_tiny_EVB_MX_Plus\KEIL\aliyun_iotkit_csdk_mqtt
This commit is contained in:
517
components/connectivity/iotkit-embedded-3.0.1/3rdparty/wrappers/tls/HAL_DTLS_mbedtls.c
vendored
Normal file
517
components/connectivity/iotkit-embedded-3.0.1/3rdparty/wrappers/tls/HAL_DTLS_mbedtls.c
vendored
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "infra_config.h"
|
||||
#ifdef COAP_DTLS_SUPPORT
|
||||
#include "wrappers_defs.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/debug.h"
|
||||
#include "mbedtls/timing.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ssl_cookie.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
|
||||
void *HAL_Malloc(uint32_t size);
|
||||
void HAL_Free(void *ptr);
|
||||
void HAL_Printf(const char *fmt, ...);
|
||||
|
||||
#define DTLS_TRC(...) HAL_Printf("[trc] "), HAL_Printf(__VA_ARGS__)
|
||||
#define DTLS_DUMP(...) HAL_Printf("[dump] "), HAL_Printf(__VA_ARGS__)
|
||||
#define DTLS_DEBUG(...) HAL_Printf("[dbg] "), HAL_Printf(__VA_ARGS__)
|
||||
#define DTLS_INFO(...) HAL_Printf("[inf] "), HAL_Printf(__VA_ARGS__)
|
||||
#define DTLS_ERR(...) HAL_Printf("[err] "), HAL_Printf(__VA_ARGS__)
|
||||
|
||||
#ifdef DTLS_SESSION_SAVE
|
||||
mbedtls_ssl_session *saved_session = NULL;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
mbedtls_ssl_context context;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_entropy_context entropy;
|
||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
|
||||
mbedtls_x509_crt cacert;
|
||||
#endif
|
||||
mbedtls_net_context fd;
|
||||
mbedtls_timing_delay_context timer;
|
||||
mbedtls_ssl_cookie_ctx cookie_ctx;
|
||||
} dtls_session_t;
|
||||
|
||||
#define MBEDTLS_MEM_TEST 1
|
||||
|
||||
#ifdef MBEDTLS_MEM_TEST
|
||||
|
||||
#define MBEDTLS_MEM_INFO_MAGIC 0x12345678
|
||||
|
||||
static unsigned int mbedtls_mem_used = 0;
|
||||
static unsigned int mbedtls_max_mem_used = 0;
|
||||
static dtls_hooks_t g_dtls_hooks = {HAL_Malloc, HAL_Free};
|
||||
|
||||
typedef struct {
|
||||
int magic;
|
||||
int size;
|
||||
} mbedtls_mem_info_t;
|
||||
|
||||
void *_DTLSCalloc_wrapper(size_t n, size_t size)
|
||||
{
|
||||
void *buf = NULL;
|
||||
mbedtls_mem_info_t *mem_info = NULL;
|
||||
|
||||
if (n == 0 || size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf = g_dtls_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;
|
||||
}
|
||||
|
||||
/* DTLS_TRC("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 _DTLSFree_wrapper(void *ptr)
|
||||
{
|
||||
mbedtls_mem_info_t *mem_info = NULL;
|
||||
if (NULL == ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
mem_info = ptr - sizeof(mbedtls_mem_info_t);
|
||||
if (mem_info->magic != MBEDTLS_MEM_INFO_MAGIC) {
|
||||
DTLS_TRC("Warning - invalid mem info magic: 0x%x\r\n", mem_info->magic);
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_mem_used -= mem_info->size;
|
||||
/* DTLS_TRC("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_dtls_hooks.free(mem_info);
|
||||
}
|
||||
|
||||
#else
|
||||
static void *_DTLSCalloc_wrapper(size_t n, size_t s)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
size_t len = n * s;
|
||||
ptr = HAL_Malloc(len);
|
||||
if (NULL != ptr) {
|
||||
memset(ptr, 0x00, len);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void _DTLSFree_wrapper(void *ptr)
|
||||
{
|
||||
if (NULL != ptr) {
|
||||
HAL_Free(ptr);
|
||||
ptr = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DTLS_SESSION_SAVE
|
||||
static int _DTLSSession_save(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 defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
size_t cert_len;
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
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_X509_CRT_PARSE_C)
|
||||
if (session->peer_cert == NULL) {
|
||||
cert_len = 0;
|
||||
} else {
|
||||
cert_len = session->peer_cert->raw.len;
|
||||
}
|
||||
|
||||
if (left < 3 + cert_len) {
|
||||
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
|
||||
}
|
||||
|
||||
*p++ = (unsigned char)(cert_len >> 16 & 0xFF);
|
||||
*p++ = (unsigned char)(cert_len >> 8 & 0xFF);
|
||||
*p++ = (unsigned char)(cert_len & 0xFF);
|
||||
|
||||
if (session->peer_cert != NULL) {
|
||||
memcpy(p, session->peer_cert->raw.p, cert_len);
|
||||
}
|
||||
|
||||
p += cert_len;
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
*olen = p - buf;
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int _DTLSVerifyOptions_set(dtls_session_t *p_dtls_session, unsigned char *p_ca_cert_pem, char *host)
|
||||
{
|
||||
int result;
|
||||
unsigned int err_code = DTLS_SUCCESS;
|
||||
|
||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
|
||||
if (p_ca_cert_pem != NULL) {
|
||||
mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
if (strstr(host, "pre.iot-as-coap")) {
|
||||
DTLS_TRC("host = '%s' so verify server OPTIONAL\r\n", host);
|
||||
mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
}
|
||||
DTLS_TRC("Call mbedtls_ssl_conf_authmode\r\n");
|
||||
|
||||
DTLS_TRC("x509 ca cert pem len %d\r\n%s\r\n", (int)strlen((char *)p_ca_cert_pem) + 1, p_ca_cert_pem);
|
||||
result = mbedtls_x509_crt_parse(&p_dtls_session->cacert,
|
||||
p_ca_cert_pem,
|
||||
strlen((const char *)p_ca_cert_pem) + 1);
|
||||
|
||||
DTLS_TRC("mbedtls_x509_crt_parse result 0x%04x\r\n", result);
|
||||
if (0 != result) {
|
||||
err_code = DTLS_INVALID_CA_CERTIFICATE;
|
||||
} else {
|
||||
mbedtls_ssl_conf_ca_chain(&p_dtls_session->conf, &p_dtls_session->cacert, NULL);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
static void _DTLSLog_wrapper(void *p_ctx, int level,
|
||||
const char *p_file, int line, const char *p_str)
|
||||
{
|
||||
DTLS_INFO("[mbedTLS]:[%s]:[%d]: %s\r\n", p_file, line, p_str);
|
||||
}
|
||||
|
||||
static unsigned int _DTLSContext_setup(dtls_session_t *p_dtls_session, coap_dtls_options_t *p_options)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
mbedtls_ssl_init(&p_dtls_session->context);
|
||||
|
||||
result = mbedtls_ssl_setup(&p_dtls_session->context, &p_dtls_session->conf);
|
||||
DTLS_TRC("mbedtls_ssl_setup result 0x%04x\r\n", result);
|
||||
|
||||
if (result == 0) {
|
||||
if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
mbedtls_ssl_set_timer_cb(&p_dtls_session->context,
|
||||
(void *)&p_dtls_session->timer,
|
||||
mbedtls_timing_set_delay,
|
||||
mbedtls_timing_get_delay);
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
|
||||
DTLS_TRC("mbedtls_ssl_set_hostname %s\r\n", p_options->p_host);
|
||||
mbedtls_ssl_set_hostname(&p_dtls_session->context, p_options->p_host);
|
||||
#endif
|
||||
mbedtls_ssl_set_bio(&p_dtls_session->context,
|
||||
(void *)&p_dtls_session->fd,
|
||||
mbedtls_net_send,
|
||||
mbedtls_net_recv,
|
||||
mbedtls_net_recv_timeout);
|
||||
DTLS_TRC("mbedtls_ssl_set_bio result 0x%04x\r\n", result);
|
||||
|
||||
#ifdef DTLS_SESSION_SAVE
|
||||
if (NULL != saved_session) {
|
||||
result = mbedtls_ssl_set_session(&p_dtls_session->context, saved_session);
|
||||
DTLS_TRC("mbedtls_ssl_set_session return 0x%04x\r\n", result);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
result = mbedtls_ssl_handshake(&p_dtls_session->context);
|
||||
} while (result == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
result == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
DTLS_TRC("mbedtls_ssl_handshake result 0x%04x\r\n", result);
|
||||
#ifdef MBEDTLS_MEM_TEST
|
||||
DTLS_TRC("mbedtls handshake memory total used: %d max used: %d\r\n",
|
||||
mbedtls_mem_used, mbedtls_max_mem_used);
|
||||
#endif
|
||||
|
||||
#ifdef DTLS_SESSION_SAVE
|
||||
if (0 == result) {
|
||||
if (NULL == saved_session) {
|
||||
saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
|
||||
}
|
||||
if (NULL != saved_session) {
|
||||
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
|
||||
result = mbedtls_ssl_get_session(&p_dtls_session->context, saved_session);
|
||||
DTLS_TRC("mbedtls_ssl_get_session return 0x%04x\r\n", result);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (result ? DTLS_HANDSHAKE_FAILED : DTLS_SUCCESS);
|
||||
}
|
||||
|
||||
dtls_session_t *_DTLSSession_init()
|
||||
{
|
||||
dtls_session_t *p_dtls_session = NULL;
|
||||
p_dtls_session = HAL_Malloc(sizeof(dtls_session_t));
|
||||
|
||||
mbedtls_debug_set_threshold(0);
|
||||
#ifdef MBEDTLS_MEM_TEST
|
||||
mbedtls_mem_used = 0;
|
||||
mbedtls_max_mem_used = 0;
|
||||
#endif
|
||||
mbedtls_platform_set_calloc_free(_DTLSCalloc_wrapper, _DTLSFree_wrapper);
|
||||
if (NULL != p_dtls_session) {
|
||||
mbedtls_net_init(&p_dtls_session->fd);
|
||||
mbedtls_ssl_init(&p_dtls_session->context);
|
||||
mbedtls_ssl_config_init(&p_dtls_session->conf);
|
||||
mbedtls_net_init(&p_dtls_session->fd);
|
||||
|
||||
mbedtls_ssl_cookie_init(&p_dtls_session->cookie_ctx);
|
||||
|
||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
|
||||
mbedtls_x509_crt_init(&p_dtls_session->cacert);
|
||||
#endif
|
||||
mbedtls_ctr_drbg_init(&p_dtls_session->ctr_drbg);
|
||||
mbedtls_entropy_init(&p_dtls_session->entropy);
|
||||
DTLS_INFO("HAL_DTLSSession_init success\r\n");
|
||||
|
||||
}
|
||||
|
||||
return p_dtls_session;
|
||||
}
|
||||
|
||||
unsigned int _DTLSSession_deinit(dtls_session_t *p_dtls_session)
|
||||
{
|
||||
int ret;
|
||||
if (p_dtls_session != NULL) {
|
||||
do {
|
||||
ret = mbedtls_ssl_close_notify(&p_dtls_session->context);
|
||||
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
|
||||
mbedtls_net_free(&p_dtls_session->fd);
|
||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
|
||||
mbedtls_x509_crt_free(&p_dtls_session->cacert);
|
||||
#endif
|
||||
mbedtls_ssl_cookie_free(&p_dtls_session->cookie_ctx);
|
||||
|
||||
mbedtls_ssl_config_free(&p_dtls_session->conf);
|
||||
mbedtls_ssl_free(&p_dtls_session->context);
|
||||
|
||||
mbedtls_ctr_drbg_free(&p_dtls_session->ctr_drbg);
|
||||
mbedtls_entropy_free(&p_dtls_session->entropy);
|
||||
HAL_Free(p_dtls_session);
|
||||
}
|
||||
|
||||
return DTLS_SUCCESS;
|
||||
}
|
||||
|
||||
int HAL_DTLSHooks_set(dtls_hooks_t *hooks)
|
||||
{
|
||||
if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) {
|
||||
return DTLS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
g_dtls_hooks.malloc = hooks->malloc;
|
||||
g_dtls_hooks.free = hooks->free;
|
||||
|
||||
return DTLS_SUCCESS;
|
||||
}
|
||||
|
||||
DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options)
|
||||
{
|
||||
char port[6] = {0};
|
||||
int result = 0;
|
||||
dtls_session_t *p_dtls_session = NULL;
|
||||
|
||||
p_dtls_session = _DTLSSession_init();
|
||||
if (NULL != p_dtls_session) {
|
||||
mbedtls_ssl_config_init(&p_dtls_session->conf);
|
||||
result = mbedtls_ctr_drbg_seed(&p_dtls_session->ctr_drbg, mbedtls_entropy_func, &p_dtls_session->entropy,
|
||||
(const unsigned char *)"IoTx",
|
||||
strlen("IoTx"));
|
||||
if (0 != result) {
|
||||
DTLS_ERR("mbedtls_ctr_drbg_seed result 0x%04x\r\n", result);
|
||||
goto error;
|
||||
}
|
||||
result = mbedtls_ssl_config_defaults(&p_dtls_session->conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_DATAGRAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (0 != result) {
|
||||
DTLS_ERR("mbedtls_ssl_config_defaults result 0x%04x\r\n", result);
|
||||
goto error;
|
||||
}
|
||||
mbedtls_ssl_conf_rng(&p_dtls_session->conf, mbedtls_ctr_drbg_random, &p_dtls_session->ctr_drbg);
|
||||
mbedtls_ssl_conf_dbg(&p_dtls_session->conf, _DTLSLog_wrapper, NULL);
|
||||
|
||||
result = mbedtls_ssl_cookie_setup(&p_dtls_session->cookie_ctx,
|
||||
mbedtls_ctr_drbg_random, &p_dtls_session->ctr_drbg);
|
||||
if (0 != result) {
|
||||
DTLS_ERR("mbedtls_ssl_cookie_setup result 0x%04x\r\n", result);
|
||||
goto error;
|
||||
}
|
||||
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
|
||||
mbedtls_ssl_conf_dtls_cookies(&p_dtls_session->conf, mbedtls_ssl_cookie_write,
|
||||
mbedtls_ssl_cookie_check, &p_dtls_session->cookie_ctx);
|
||||
#endif
|
||||
|
||||
result = _DTLSVerifyOptions_set(p_dtls_session, p_options->p_ca_cert_pem, p_options->p_host);
|
||||
|
||||
if (DTLS_SUCCESS != result) {
|
||||
DTLS_ERR("DTLSVerifyOptions_set result 0x%04x\r\n", result);
|
||||
goto error;
|
||||
}
|
||||
sprintf(port, "%u", p_options->port);
|
||||
result = mbedtls_net_connect(&p_dtls_session->fd, p_options->p_host,
|
||||
port, MBEDTLS_NET_PROTO_UDP);
|
||||
if (0 != result) {
|
||||
DTLS_ERR("mbedtls_net_connect result 0x%04x\r\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_SSL_PROTO_DTLS
|
||||
if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
mbedtls_ssl_conf_min_version(&p_dtls_session->conf,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3,
|
||||
MBEDTLS_SSL_MINOR_VERSION_3);
|
||||
|
||||
mbedtls_ssl_conf_max_version(&p_dtls_session->conf,
|
||||
MBEDTLS_SSL_MAJOR_VERSION_3,
|
||||
MBEDTLS_SSL_MINOR_VERSION_3);
|
||||
|
||||
mbedtls_ssl_conf_handshake_timeout(&p_dtls_session->conf,
|
||||
(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2),
|
||||
(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4));
|
||||
}
|
||||
#endif
|
||||
result = _DTLSContext_setup(p_dtls_session, p_options);
|
||||
if (DTLS_SUCCESS != result) {
|
||||
DTLS_ERR("DTLSVerifyOptions_set result 0x%04x\r\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return (DTLSContext *)p_dtls_session;
|
||||
}
|
||||
|
||||
error:
|
||||
if (NULL != p_dtls_session) {
|
||||
_DTLSSession_deinit(p_dtls_session);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int HAL_DTLSSession_write(DTLSContext *context,
|
||||
const unsigned char *p_data,
|
||||
unsigned int *p_datalen)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int err_code = DTLS_SUCCESS;
|
||||
dtls_session_t *p_dtls_session = (dtls_session_t *)context;
|
||||
|
||||
if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
|
||||
len = (*p_datalen);
|
||||
len = mbedtls_ssl_write(&p_dtls_session->context, p_data, len);
|
||||
|
||||
if (len < 0) {
|
||||
if (len == MBEDTLS_ERR_SSL_CONN_EOF) {
|
||||
if (p_dtls_session->context.state < MBEDTLS_SSL_HANDSHAKE_OVER) {
|
||||
err_code = DTLS_HANDSHAKE_IN_PROGRESS;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(*p_datalen) = len;
|
||||
err_code = DTLS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return err_code;
|
||||
}
|
||||
|
||||
unsigned int HAL_DTLSSession_read(DTLSContext *context,
|
||||
unsigned char *p_data,
|
||||
unsigned int *p_datalen,
|
||||
unsigned int timeout)
|
||||
{
|
||||
int len = 0;
|
||||
unsigned int err_code = DTLS_READ_DATA_FAILED;
|
||||
dtls_session_t *p_dtls_session = (dtls_session_t *)context;
|
||||
|
||||
if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
|
||||
mbedtls_ssl_conf_read_timeout(&(p_dtls_session->conf), timeout);
|
||||
len = mbedtls_ssl_read(&p_dtls_session->context, p_data, *p_datalen);
|
||||
|
||||
if (0 < len) {
|
||||
*p_datalen = len;
|
||||
err_code = DTLS_SUCCESS;
|
||||
DTLS_TRC("mbedtls_ssl_read len %d bytes\r\n", len);
|
||||
} else {
|
||||
*p_datalen = 0;
|
||||
if (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == len) {
|
||||
err_code = DTLS_FATAL_ALERT_MESSAGE;
|
||||
DTLS_INFO("Recv peer fatal alert message\r\n");
|
||||
} else if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == len) {
|
||||
err_code = DTLS_PEER_CLOSE_NOTIFY;
|
||||
DTLS_INFO("The DTLS session was closed by peer\r\n");
|
||||
} else if (MBEDTLS_ERR_SSL_TIMEOUT == len) {
|
||||
err_code = DTLS_SUCCESS;
|
||||
DTLS_TRC("DTLS recv timeout\r\n");
|
||||
} else {
|
||||
DTLS_TRC("mbedtls_ssl_read error result (-0x%04x)\r\n", len);
|
||||
}
|
||||
}
|
||||
}
|
||||
return err_code;
|
||||
}
|
||||
|
||||
unsigned int HAL_DTLSSession_free(DTLSContext *context)
|
||||
{
|
||||
dtls_session_t *p_dtls_session = NULL;
|
||||
if (NULL != context) {
|
||||
p_dtls_session = (dtls_session_t *)context;
|
||||
return _DTLSSession_deinit(p_dtls_session);
|
||||
}
|
||||
|
||||
return DTLS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
860
components/connectivity/iotkit-embedded-3.0.1/3rdparty/wrappers/tls/HAL_TLS_mbedtls.c
vendored
Normal file
860
components/connectivity/iotkit-embedded-3.0.1/3rdparty/wrappers/tls/HAL_TLS_mbedtls.c
vendored
Normal file
@@ -0,0 +1,860 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(_PLATFORM_IS_LINUX_)
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include "infra_config.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_defs.h"
|
||||
|
||||
#define SEND_TIMEOUT_SECONDS (10)
|
||||
#define GUIDER_ONLINE_HOSTNAME ("iot-auth.cn-shanghai.aliyuncs.com")
|
||||
#define GUIDER_PRE_ADDRESS ("100.67.80.107")
|
||||
|
||||
#ifndef CONFIG_MBEDTLS_DEBUG_LEVEL
|
||||
#define CONFIG_MBEDTLS_DEBUG_LEVEL 0
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
void *HAL_Malloc(uint32_t size);
|
||||
void HAL_Free(void *ptr);
|
||||
|
||||
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;
|
||||
|
||||
#if defined(TLS_SAVE_TICKET)
|
||||
|
||||
#define TLS_MAX_SESSION_BUF 384
|
||||
#define KV_SESSION_KEY "TLS_SESSION"
|
||||
|
||||
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 defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
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 unsigned int _avRandom()
|
||||
{
|
||||
return (((unsigned int)rand() << 16) + rand());
|
||||
}
|
||||
|
||||
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)_avRandom() ;
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
/* Setup Client Cert/Key */
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#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 /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
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 defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
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, stdout);
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&(pTlsData->ssl), &(pTlsData->conf))) != 0) {
|
||||
printf("failed! mbedtls_ssl_setup returned %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#if defined(ON_PRE) || defined(ON_DAILY)
|
||||
printf("SKIPPING mbedtls_ssl_set_hostname() when ON_PRE or ON_DAILY defined!\n");
|
||||
#else
|
||||
mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr);
|
||||
#endif
|
||||
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;
|
||||
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));
|
||||
|
||||
ret = HAL_Kv_Get(KV_SESSION_KEY, 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);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
printf(" ok\n");
|
||||
|
||||
#if defined(TLS_SAVE_TICKET)
|
||||
if (NULL == saved_session) {
|
||||
do {
|
||||
size_t real_session_len = 0;
|
||||
unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF); //for test
|
||||
if (save_buf == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
|
||||
if (NULL == saved_session) {
|
||||
HAL_Free(save_buf);
|
||||
break;
|
||||
}
|
||||
memset(save_buf, 0x00, sizeof(TLS_MAX_SESSION_BUF));
|
||||
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
|
||||
|
||||
ret = mbedtls_ssl_get_session(&(pTlsData->ssl), saved_session);
|
||||
if (ret != 0) {
|
||||
HAL_Free(save_buf);
|
||||
HAL_Free(saved_session);
|
||||
saved_session = NULL;
|
||||
break;
|
||||
}
|
||||
ret = ssl_serialize_session(saved_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) {
|
||||
HAL_Kv_Set(KV_SESSION_KEY, (void *)save_buf, real_session_len, 1);
|
||||
}
|
||||
HAL_Free(save_buf);
|
||||
} while (0);
|
||||
}
|
||||
#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) {
|
||||
mbedtls_strerror(ret, err_str, sizeof(err_str));
|
||||
printf("ssl recv error: code = %d, 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 {
|
||||
mbedtls_strerror(ret, err_str, sizeof(err_str));
|
||||
printf("ssl recv error: code = %d, 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];
|
||||
mbedtls_strerror(ret, err_str, sizeof(err_str));
|
||||
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 defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
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
|
||||
mbedtls_ssl_free(&(pTlsData->ssl));
|
||||
mbedtls_ssl_config_free(&(pTlsData->conf));
|
||||
printf("ssl_disconnect\n");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#if defined(ON_PRE)
|
||||
if (!strcmp(GUIDER_ONLINE_HOSTNAME, host)) {
|
||||
printf("ALTERING '%s' to '%s' since ON_PRE defined!\n", host, GUIDER_PRE_ADDRESS);
|
||||
alter = GUIDER_PRE_ADDRESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_platform_set_calloc_free(_SSLCalloc_wrapper, _SSLFree_wrapper);
|
||||
|
||||
if (0 != _TLSConnectNetwork(pTlsData, alter, port_str, ca_crt, ca_crt_len, NULL, 0, NULL, 0, NULL, 0)) {
|
||||
_network_ssl_disconnect(pTlsData);
|
||||
g_ssl_hooks.free((void *)pTlsData);
|
||||
return (uintptr_t)NULL;
|
||||
}
|
||||
|
||||
return (uintptr_t)pTlsData;
|
||||
}
|
||||
|
Reference in New Issue
Block a user