feat: 移植腾讯云物联网开发平台 C SDK
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @copyright
|
||||
*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright(C) 2018 - 2021 THL A29 Limited, a Tencent company.All rights reserved.
|
||||
*
|
||||
* Licensed under the MIT License(the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @file qcloud_iot_tls_client.h
|
||||
* @brief header file for tls client
|
||||
* @author fancyxu (fancyxu@tencent.com)
|
||||
* @version 1.0
|
||||
* @date 2021-07-12
|
||||
*
|
||||
* @par Change Log:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-07-12 <td>1.0 <td>fancyxu <td>first commit
|
||||
* </table>
|
||||
*/
|
||||
|
||||
#ifndef IOT_HUB_DEVICE_C_SDK_3RD_MBEDTLS_PORT_INC_QCLOUD_IOT_TLS_CLIENT_H_
|
||||
#define IOT_HUB_DEVICE_C_SDK_3RD_MBEDTLS_PORT_INC_QCLOUD_IOT_TLS_CLIENT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "qcloud_iot_platform.h"
|
||||
|
||||
#ifndef MAX_SIZE_OF_CLIENT_ID
|
||||
#define MAX_SIZE_OF_CLIENT_ID (80)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Define structure for TLS connection parameters
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
const char *ca_crt;
|
||||
uint16_t ca_crt_len;
|
||||
|
||||
#ifdef AUTH_MODE_CERT
|
||||
/**
|
||||
* Device with certificate
|
||||
*/
|
||||
const char *cert_file; // public certificate file
|
||||
const char *key_file; // pravite certificate file
|
||||
#else
|
||||
/**
|
||||
* Device with PSK
|
||||
*/
|
||||
const char *psk; // PSK string
|
||||
const char *psk_id; // PSK ID
|
||||
#endif
|
||||
|
||||
size_t psk_length; // PSK length
|
||||
|
||||
unsigned int timeout_ms; // SSL handshake timeout in millisecond
|
||||
|
||||
} SSLConnectParams;
|
||||
|
||||
typedef SSLConnectParams TLSConnectParams;
|
||||
|
||||
/**
|
||||
* @brief Tls setup and sharkhand
|
||||
*
|
||||
* @param[in] connect_params connect params of tls
|
||||
* @param[in] host server host
|
||||
* @param[in] port server port
|
||||
* @return tls handle, 0 for fail
|
||||
*/
|
||||
uintptr_t qcloud_iot_tls_client_connect(const TLSConnectParams *connect_params, const char *host, const char *port);
|
||||
|
||||
/**
|
||||
* @brief Disconect and free
|
||||
*
|
||||
* @param[in,out] handle tls handle
|
||||
*/
|
||||
void qcloud_iot_tls_client_disconnect(uintptr_t handle);
|
||||
|
||||
/**
|
||||
* @brief Write msg with tls
|
||||
*
|
||||
* @param[in,out] handle tls handle
|
||||
* @param[in] msg msg to write
|
||||
* @param[in] total_len number of bytes to write
|
||||
* @param[in] timeout_ms timeout millsecond
|
||||
* @param[out] written_len number of bytes writtern
|
||||
* @return @see IotReturnCode
|
||||
*/
|
||||
int qcloud_iot_tls_client_write(uintptr_t handle, unsigned char *msg, size_t total_len, uint32_t timeout_ms,
|
||||
size_t *written_len);
|
||||
|
||||
/**
|
||||
* @brief Read msg with tls
|
||||
*
|
||||
* @param[in,out] handle tls handle
|
||||
* @param[out] msg msg buffer
|
||||
* @param[in] total_len buffer len
|
||||
* @param[in] timeout_ms timeout millsecond
|
||||
* @param[out] read_len number of bytes read
|
||||
* @return @see IotReturnCode
|
||||
*/
|
||||
int qcloud_iot_tls_client_read(uintptr_t handle, unsigned char *msg, size_t total_len, uint32_t timeout_ms,
|
||||
size_t *read_len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // IOT_HUB_DEVICE_C_SDK_3RD_MBEDTLS_PORT_INC_QCLOUD_IOT_TLS_CLIENT_H_
|
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @copyright
|
||||
*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright(C) 2018 - 2021 THL A29 Limited, a Tencent company.All rights reserved.
|
||||
*
|
||||
* Licensed under the MIT License(the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @file qcloud_iot_tls_psk_config.h
|
||||
* @brief set config for tls psk
|
||||
* @author fancyxu (fancyxu@tencent.com)
|
||||
* @version 1.0
|
||||
* @date 2021-07-12
|
||||
*
|
||||
* @par Change Log:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-07-12 <td>1.0 <td>fancyxu <td>first commit
|
||||
* </table>
|
||||
*/
|
||||
|
||||
#ifndef IOT_HUB_DEVICE_C_SDK_3RD_MBEDTLS_PORT_INC_QCLOUD_IOT_TLS_PSK_CONFIG_H
|
||||
#define IOT_HUB_DEVICE_C_SDK_3RD_MBEDTLS_PORT_INC_QCLOUD_IOT_TLS_PSK_CONFIG_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* System support */
|
||||
#define MBEDTLS_HAVE_ASM
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
#define MBEDTLS_TIMING_ALT
|
||||
// #define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
// #define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
|
||||
/* mbed TLS feature support */
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_CIPHER_PADDING_PKCS7
|
||||
#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
|
||||
#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
|
||||
#define MBEDTLS_CIPHER_PADDING_ZEROS
|
||||
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
|
||||
/* mbed TLS modules */
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
|
||||
#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
|
||||
#define MBEDTLS_SSL_SESSION_TICKETS
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_SSL_MAX_CONTENT_LEN 3584
|
||||
#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
|
||||
|
||||
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
|
||||
|
||||
/* For testing with compat.sh */
|
||||
#include "mbedtls/check_config.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // IOT_HUB_DEVICE_C_SDK_3RD_MBEDTLS_PORT_INC_QCLOUD_IOT_TLS_PSK_CONFIG_H
|
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @copyright
|
||||
*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright(C) 2018 - 2021 THL A29 Limited, a Tencent company.All rights reserved.
|
||||
*
|
||||
* Licensed under the MIT License(the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @file qcloud_iot_net_socket.c
|
||||
* @brief implements mbedtls net socket api for tls client
|
||||
* @author fancyxu (fancyxu@tencent.com)
|
||||
* @version 1.0
|
||||
* @date 2021-07-09
|
||||
*
|
||||
* @par Change Log:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-07-09 <td>1.0 <td>fancyxu <td>first commit
|
||||
* </table>
|
||||
*/
|
||||
|
||||
#include "qcloud_iot_platform.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
|
||||
/**
|
||||
* @brief Convert return code from IotReturnCode to mbedtls error code
|
||||
*
|
||||
* @param[in] iot_return_code @see IotReturnCode
|
||||
* @return mbedtls error code
|
||||
*/
|
||||
static int _return_code_convert(int iot_return_code)
|
||||
{
|
||||
switch (iot_return_code) {
|
||||
case QCLOUD_ERR_TCP_UNKNOWN_HOST:
|
||||
return MBEDTLS_ERR_NET_UNKNOWN_HOST;
|
||||
case QCLOUD_ERR_TCP_SOCKET_FAILED:
|
||||
return MBEDTLS_ERR_NET_SOCKET_FAILED;
|
||||
case QCLOUD_ERR_TCP_CONNECT:
|
||||
return MBEDTLS_ERR_NET_CONNECT_FAILED;
|
||||
case QCLOUD_ERR_TCP_WRITE_TIMEOUT:
|
||||
return MBEDTLS_ERR_SSL_WANT_WRITE;
|
||||
case QCLOUD_ERR_TCP_WRITE_FAIL:
|
||||
return MBEDTLS_ERR_NET_SEND_FAILED;
|
||||
case QCLOUD_ERR_TCP_PEER_SHUTDOWN:
|
||||
return MBEDTLS_ERR_NET_CONN_RESET;
|
||||
case QCLOUD_ERR_TCP_READ_TIMEOUT:
|
||||
return MBEDTLS_ERR_SSL_TIMEOUT;
|
||||
case QCLOUD_ERR_TCP_NOTHING_TO_READ:
|
||||
return MBEDTLS_ERR_SSL_WANT_READ;
|
||||
case QCLOUD_ERR_TCP_READ_FAIL:
|
||||
return MBEDTLS_ERR_NET_RECV_FAILED;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init net context
|
||||
*
|
||||
* @param[in,out] ctx mbedtls net context handle
|
||||
*/
|
||||
void mbedtls_net_init(mbedtls_net_context *ctx)
|
||||
{
|
||||
ctx->fd = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initiate a TCP connection with host:port and the given protocol
|
||||
*
|
||||
* @param[in,out] ctx mbedtls net context handle
|
||||
* @param[in] host host to connect
|
||||
* @param[in] port port to connect
|
||||
* @param[in] proto no use for always tcp
|
||||
* @return fd > 0 for success, others for mbedtls error code
|
||||
*/
|
||||
int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto)
|
||||
{
|
||||
ctx->fd = HAL_TCP_Connect(host, port);
|
||||
return ctx->fd < 0 ? _return_code_convert(ctx->fd) : ctx->fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read at most 'len' characters
|
||||
*
|
||||
* @param[in] ctx mbedtls net context handle
|
||||
* @param[out] buf data buffer
|
||||
* @param[in] len data buffer len
|
||||
* @return > 0 for data received bytes, others for mbedtls error code
|
||||
*/
|
||||
int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
|
||||
{
|
||||
int rc;
|
||||
size_t rlen;
|
||||
int fd = ((mbedtls_net_context *)ctx)->fd;
|
||||
|
||||
rc = HAL_TCP_Read(fd, buf, len, INT_MAX, &rlen);
|
||||
|
||||
return rc ? _return_code_convert(rc) : rlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read at most 'len' characters, blocking for at most 'timeout' ms
|
||||
*
|
||||
* @param[in] ctx mbedtls net context handle
|
||||
* @param[out] buf data buffer
|
||||
* @param[in] len data buffer len
|
||||
* @param[in] timeout read timeout
|
||||
* @return > 0 for data received bytes, others for mbedtls error code
|
||||
*/
|
||||
int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout)
|
||||
{
|
||||
int rc;
|
||||
size_t rlen;
|
||||
int fd = ((mbedtls_net_context *)ctx)->fd;
|
||||
|
||||
rc = HAL_TCP_Read(fd, buf, len, timeout, &rlen);
|
||||
|
||||
return rc ? _return_code_convert(rc) : rlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write at most 'len' characters
|
||||
*
|
||||
* @param[in] ctx mbedtls net context handle
|
||||
* @param[in] buf data buffer
|
||||
* @param[in] len data buffer len
|
||||
* @return > 0 for data writtern bytes, others for mbedtls error code
|
||||
*/
|
||||
int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
|
||||
{
|
||||
int rc;
|
||||
size_t wlen;
|
||||
int fd = ((mbedtls_net_context *)ctx)->fd;
|
||||
|
||||
rc = HAL_TCP_Write(fd, buf, len, INT_MAX, &wlen);
|
||||
|
||||
return rc ? _return_code_convert(rc) : wlen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gracefully close the connection
|
||||
*
|
||||
* @param ctx mbedtls net context handle
|
||||
*/
|
||||
void mbedtls_net_free(mbedtls_net_context *ctx)
|
||||
{
|
||||
HAL_TCP_Disconnect(ctx->fd);
|
||||
}
|
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* @copyright
|
||||
*
|
||||
* Tencent is pleased to support the open source community by making IoT Hub available.
|
||||
* Copyright(C) 2018 - 2021 THL A29 Limited, a Tencent company.All rights reserved.
|
||||
*
|
||||
* Licensed under the MIT License(the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is
|
||||
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @file qcloud_iot_tls_client.c
|
||||
* @brief implements tls client with mbedtls
|
||||
* @author fancyxu (fancyxu@tencent.com)
|
||||
* @version 1.0
|
||||
* @date 2021-07-12
|
||||
*
|
||||
* @par Change Log:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-07-12 <td>1.0 <td>fancyxu <td>first commit
|
||||
* </table>
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "qcloud_iot_tls_client.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
|
||||
#ifdef AUTH_MODE_KEY
|
||||
/**
|
||||
* @brief Only tls psk is supportted when using psk
|
||||
*
|
||||
*/
|
||||
static const int ciphersuites[] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, 0};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data structure for mbedtls SSL connection
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
mbedtls_net_context socket_fd;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config ssl_conf;
|
||||
#ifdef AUTH_MODE_CERT
|
||||
mbedtls_x509_crt ca_cert;
|
||||
mbedtls_x509_crt client_cert;
|
||||
#endif
|
||||
mbedtls_pk_context private_key;
|
||||
} TLSHandle;
|
||||
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
#define DEBUG_LEVEL 0
|
||||
static void _ssl_debug(void *ctx, int level, const char *file, int line, const char *str)
|
||||
{
|
||||
Log_i("[mbedTLS]:[%s]:[%d]: %s\r\n", STRING_PTR_PRINT_SANITY_CHECK(file), line, STRING_PTR_PRINT_SANITY_CHECK(str));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief mbedtls SSL client init
|
||||
*
|
||||
* 1. call a series of mbedtls init functions
|
||||
* 2. init and set seed for random functions
|
||||
* 3. load CA file, cert files or PSK
|
||||
*
|
||||
* @param[in,out] tls_handle mbedtls TLS handle
|
||||
* @param[in] connect_params device info for TLS connection
|
||||
* @return @see IotReturnCode
|
||||
*/
|
||||
static int _mbedtls_tls_client_init(TLSHandle *tls_handle, const TLSConnectParams *connect_params)
|
||||
{
|
||||
int rc;
|
||||
|
||||
mbedtls_net_init(&tls_handle->socket_fd);
|
||||
mbedtls_ssl_init(&tls_handle->ssl);
|
||||
mbedtls_ssl_config_init(&tls_handle->ssl_conf);
|
||||
mbedtls_ctr_drbg_init(&tls_handle->ctr_drbg);
|
||||
mbedtls_entropy_init(&tls_handle->entropy);
|
||||
#ifdef AUTH_MODE_CERT
|
||||
mbedtls_x509_crt_init(&tls_handle->ca_cert);
|
||||
mbedtls_x509_crt_init(&tls_handle->client_cert);
|
||||
mbedtls_pk_init(&tls_handle->private_key);
|
||||
#endif
|
||||
#ifdef MBEDTLS_DEBUG_C
|
||||
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
||||
mbedtls_ssl_conf_dbg(&tls_handle->ssl_conf, _ssl_debug, NULL);
|
||||
#endif
|
||||
|
||||
rc = mbedtls_ctr_drbg_seed(&tls_handle->ctr_drbg, mbedtls_entropy_func, &tls_handle->entropy, NULL, 0);
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ctr_drbg_seed failed returned 0x%04x", -rc);
|
||||
return QCLOUD_ERR_SSL_INIT;
|
||||
}
|
||||
|
||||
#ifdef AUTH_MODE_CERT
|
||||
if (!connect_params->cert_file || !connect_params->key_file || !connect_params->ca_crt) {
|
||||
Log_d("cert_file/key_file/ca is empty!|cert_file=%s|key_file=%s|ca=%s",
|
||||
STRING_PTR_PRINT_SANITY_CHECK(connect_params->cert_file),
|
||||
STRING_PTR_PRINT_SANITY_CHECK(connect_params->key_file),
|
||||
STRING_PTR_PRINT_SANITY_CHECK(connect_params->ca_crt));
|
||||
return QCLOUD_ERR_SSL_CERT;
|
||||
}
|
||||
|
||||
rc = mbedtls_x509_crt_parse(&tls_handle->ca_cert, (const unsigned char *)connect_params->ca_crt,
|
||||
(connect_params->ca_crt_len + 1));
|
||||
if (rc) {
|
||||
Log_e("parse ca crt failed returned 0x%04x", -rc);
|
||||
return QCLOUD_ERR_SSL_CERT;
|
||||
}
|
||||
|
||||
rc = mbedtls_x509_crt_parse_file(&tls_handle->client_cert, connect_params->cert_file);
|
||||
if (rc) {
|
||||
Log_e("load client cert file failed returned 0x%04x", -rc);
|
||||
return QCLOUD_ERR_SSL_CERT;
|
||||
}
|
||||
|
||||
rc = mbedtls_pk_parse_keyfile(&tls_handle->private_key, connect_params->key_file, "");
|
||||
if (rc) {
|
||||
Log_e("load client key file failed returned 0x%04x", -rc);
|
||||
return QCLOUD_ERR_SSL_CERT;
|
||||
}
|
||||
#else
|
||||
if (!connect_params->psk || !connect_params->psk_id) {
|
||||
Log_d("psk/psk_id is empty!");
|
||||
return QCLOUD_ERR_SSL_INIT;
|
||||
}
|
||||
|
||||
rc = mbedtls_ssl_conf_psk(&tls_handle->ssl_conf, (unsigned char *)connect_params->psk, connect_params->psk_length,
|
||||
(const unsigned char *)connect_params->psk_id, strlen(connect_params->psk_id));
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ssl_conf_psk fail 0x%04x", -rc);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
return QCLOUD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free memory/resources allocated by mbedtls
|
||||
*
|
||||
* @param[in,out] tls_handle @see TLSHandle
|
||||
*/
|
||||
static void _mbedtls_tls_client_free(TLSHandle *tls_handle)
|
||||
{
|
||||
mbedtls_net_free(&(tls_handle->socket_fd));
|
||||
#ifdef AUTH_MODE_CERT
|
||||
mbedtls_x509_crt_free(&tls_handle->client_cert);
|
||||
mbedtls_x509_crt_free(&tls_handle->ca_cert);
|
||||
mbedtls_pk_free(&tls_handle->private_key);
|
||||
#endif
|
||||
mbedtls_ssl_free(&tls_handle->ssl);
|
||||
mbedtls_ssl_config_free(&tls_handle->ssl_conf);
|
||||
mbedtls_ctr_drbg_free(&tls_handle->ctr_drbg);
|
||||
mbedtls_entropy_free(&tls_handle->entropy);
|
||||
HAL_Free(tls_handle);
|
||||
}
|
||||
|
||||
#ifdef AUTH_MODE_CERT
|
||||
/**
|
||||
* @brief verify server certificate
|
||||
*
|
||||
* mbedtls has provided similar function mbedtls_x509_crt_verify_with_profile
|
||||
*/
|
||||
int _mbedtls_tls_client_certificate_verify(void *hostname, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
return *flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Tls setup and sharkhand
|
||||
*
|
||||
* @param[in] connect_params connect params of tls
|
||||
* @param[in] host server host
|
||||
* @param[in] port server port
|
||||
* @return tls handle, 0 for fail
|
||||
*/
|
||||
uintptr_t qcloud_iot_tls_client_connect(const TLSConnectParams *connect_params, const char *host, const char *port)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
TLSHandle *tls_handle = (TLSHandle *)HAL_Malloc(sizeof(TLSHandle));
|
||||
if (!tls_handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = _mbedtls_tls_client_init(tls_handle, connect_params);
|
||||
if (rc) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
Log_d("Setting up the SSL/TLS structure...");
|
||||
rc = mbedtls_ssl_config_defaults(&tls_handle->ssl_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ssl_config_defaults failed returned 0x%04x", -rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_rng(&tls_handle->ssl_conf, mbedtls_ctr_drbg_random, &tls_handle->ctr_drbg);
|
||||
#ifdef AUTH_MODE_CERT
|
||||
mbedtls_ssl_conf_verify(&(tls_handle->ssl_conf), _mbedtls_tls_client_certificate_verify, (void *)host);
|
||||
mbedtls_ssl_conf_authmode(&(tls_handle->ssl_conf), MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
mbedtls_ssl_conf_ca_chain(&tls_handle->ssl_conf, &tls_handle->ca_cert, NULL);
|
||||
rc = mbedtls_ssl_conf_own_cert(&tls_handle->ssl_conf, &tls_handle->client_cert, &tls_handle->private_key);
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ssl_conf_own_cert failed returned 0x%04x", -rc);
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
mbedtls_ssl_conf_read_timeout(&tls_handle->ssl_conf, connect_params->timeout_ms);
|
||||
rc = mbedtls_ssl_setup(&tls_handle->ssl, &tls_handle->ssl_conf);
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ssl_setup failed returned 0x%04x", -rc);
|
||||
goto error;
|
||||
}
|
||||
#ifdef AUTH_MODE_CERT
|
||||
// Set the hostname to check against the received server certificate and sni
|
||||
rc = mbedtls_ssl_set_hostname(&tls_handle->ssl, host);
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ssl_set_hostname failed returned 0x%04x", -rc);
|
||||
goto error;
|
||||
}
|
||||
#else
|
||||
// ciphersuites selection for PSK device
|
||||
if (connect_params->psk) {
|
||||
mbedtls_ssl_conf_ciphersuites(&(tls_handle->ssl_conf), ciphersuites);
|
||||
}
|
||||
#endif
|
||||
mbedtls_ssl_set_bio(&tls_handle->ssl, &tls_handle->socket_fd, mbedtls_net_send, mbedtls_net_recv,
|
||||
mbedtls_net_recv_timeout);
|
||||
Log_d("Performing the SSL/TLS handshake...");
|
||||
Log_d("Connecting to /%s/%s...", STRING_PTR_PRINT_SANITY_CHECK(host), STRING_PTR_PRINT_SANITY_CHECK(port));
|
||||
rc = mbedtls_net_connect(&tls_handle->socket_fd, host, port, MBEDTLS_NET_PROTO_TCP);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_handshake(&tls_handle->ssl);
|
||||
if (rc && rc != MBEDTLS_ERR_SSL_WANT_READ && rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
Log_e("mbedtls_ssl_handshake failed returned 0x%04x", -rc);
|
||||
|
||||
#ifdef AUTH_MODE_CERT
|
||||
if (rc == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
|
||||
Log_e("Unable to verify the server's certificate");
|
||||
}
|
||||
#endif
|
||||
goto error;
|
||||
}
|
||||
} while (rc);
|
||||
|
||||
rc = mbedtls_ssl_get_verify_result(&(tls_handle->ssl));
|
||||
if (rc) {
|
||||
Log_e("mbedtls_ssl_get_verify_result failed returned 0x%04x", -rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_read_timeout(&tls_handle->ssl_conf, 200);
|
||||
|
||||
Log_d("connected with /%s/%s...", STRING_PTR_PRINT_SANITY_CHECK(host), port);
|
||||
return (uintptr_t)tls_handle;
|
||||
|
||||
error:
|
||||
_mbedtls_tls_client_free(tls_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconect and free
|
||||
*
|
||||
* @param[in,out] handle tls handle
|
||||
*/
|
||||
void qcloud_iot_tls_client_disconnect(uintptr_t handle)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
TLSHandle *tls_handle = (TLSHandle *)handle;
|
||||
if (!tls_handle) {
|
||||
Log_d("handle is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
rc = mbedtls_ssl_close_notify(&tls_handle->ssl);
|
||||
} while (rc == MBEDTLS_ERR_SSL_WANT_READ || rc == MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||
_mbedtls_tls_client_free(tls_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write msg with tls
|
||||
*
|
||||
* @param[in,out] handle tls handle
|
||||
* @param[in] msg msg to write
|
||||
* @param[in] total_len number of bytes to write
|
||||
* @param[in] timeout_ms timeout millsecond
|
||||
* @param[out] written_len number of bytes writtern
|
||||
* @return @see IotReturnCode
|
||||
*/
|
||||
int qcloud_iot_tls_client_write(uintptr_t handle, unsigned char *msg, size_t total_len, uint32_t timeout_ms,
|
||||
size_t *written_len)
|
||||
{
|
||||
QcloudIotTimer timer;
|
||||
size_t written_so_far;
|
||||
int write_rc = 0;
|
||||
|
||||
TLSHandle *tls_handle = (TLSHandle *)handle;
|
||||
IOT_Timer_CountdownMs(&timer, (unsigned int)timeout_ms);
|
||||
|
||||
for (written_so_far = 0; written_so_far < total_len && !IOT_Timer_Expired(&timer); written_so_far += write_rc) {
|
||||
do {
|
||||
write_rc = mbedtls_ssl_write(&tls_handle->ssl, msg + written_so_far, total_len - written_so_far);
|
||||
if (write_rc < 0 && write_rc != MBEDTLS_ERR_SSL_WANT_READ && write_rc != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
Log_e("HAL_TLS_write failed 0x%04x", -write_rc);
|
||||
return QCLOUD_ERR_SSL_WRITE;
|
||||
}
|
||||
|
||||
if (IOT_Timer_Expired(&timer)) {
|
||||
break;
|
||||
}
|
||||
} while (write_rc <= 0);
|
||||
}
|
||||
|
||||
*written_len = written_so_far;
|
||||
if (IOT_Timer_Expired(&timer) && written_so_far != total_len) {
|
||||
return QCLOUD_ERR_SSL_WRITE_TIMEOUT;
|
||||
}
|
||||
return QCLOUD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read msg with tls
|
||||
*
|
||||
* @param[in,out] handle tls handle
|
||||
* @param[out] msg msg buffer
|
||||
* @param[in] total_len buffer len
|
||||
* @param[in] timeout_ms timeout millsecond
|
||||
* @param[out] read_len number of bytes read
|
||||
* @return @see IotReturnCode
|
||||
*/
|
||||
int qcloud_iot_tls_client_read(uintptr_t handle, unsigned char *msg, size_t total_len, uint32_t timeout_ms,
|
||||
size_t *read_len)
|
||||
{
|
||||
QcloudIotTimer timer;
|
||||
int read_rc;
|
||||
|
||||
TLSHandle *tls_handle = (TLSHandle *)handle;
|
||||
IOT_Timer_CountdownMs(&timer, timeout_ms);
|
||||
|
||||
*read_len = 0;
|
||||
|
||||
do {
|
||||
read_rc = mbedtls_ssl_read(&tls_handle->ssl, msg + *read_len, total_len - *read_len);
|
||||
if (read_rc <= 0 && read_rc != MBEDTLS_ERR_SSL_WANT_WRITE && read_rc != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
read_rc != MBEDTLS_ERR_SSL_TIMEOUT) {
|
||||
Log_e("cloud_iot_network_tls_read failed: 0x%04x", -read_rc);
|
||||
return QCLOUD_ERR_SSL_READ;
|
||||
}
|
||||
*read_len += read_rc > 0 ? read_rc : 0;
|
||||
|
||||
if (IOT_Timer_Expired(&timer)) {
|
||||
break;
|
||||
}
|
||||
} while (*read_len < total_len);
|
||||
|
||||
if (*read_len > 0) {
|
||||
return QCLOUD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
return *read_len == 0 ? QCLOUD_ERR_SSL_NOTHING_TO_READ : QCLOUD_ERR_SSL_READ_TIMEOUT;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user