/*-----------------------------------------------------------------------------------------------*/ | |
/** | |
@file mbtk_mbedtls.c | |
@brief MBEDTLS API | |
*/ | |
/*-----------------------------------------------------------------------------------------------*/ | |
/*------------------------------------------------------------------------------------------------- | |
Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved. | |
mobiletek Wireless Solution Proprietary and Confidential. | |
-------------------------------------------------------------------------------------------------*/ | |
/*------------------------------------------------------------------------------------------------- | |
EDIT HISTORY | |
This section contains comments describing changes made to the file. | |
Notice that changes are listed in reverse chronological order. | |
$Header: $ | |
when who what, where, why | |
-------- --------- ----------------------------------------------------------------- | |
20250409 yq.wang Created . | |
-------------------------------------------------------------------------------------------------*/ | |
#ifdef MBTK_MBEDTLS_V3_6_2_SUPPORT | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include "mbtk_log.h" | |
#include "mbtk_mbedtls.h" | |
#define MBTK_SSL_PERS_STR_DEFAULT "mbtk_ssl" | |
#define MBTK_SSL_INFO_FD_DEFAULT -1 | |
#define MBTK_SSL_BUFFER_SIZE_1024 1024 | |
#define MBTK_SSL_BUFFER_SIZE_128 128 | |
static mbtk_mbedtls_ssl_result_e mbtk_mbedtls_ssl_info_free(mbtk_mbedtls_ssl_info_s *ssl_info) | |
{ | |
if(NULL == ssl_info) | |
{ | |
LOGE("[%s] ssl_info [NULL]", __func__); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
if(NULL != ssl_info->entropy) | |
{ | |
free(ssl_info->entropy); | |
ssl_info->entropy = NULL; | |
} | |
if(NULL != ssl_info->ctr_drbg) | |
{ | |
free(ssl_info->ctr_drbg); | |
ssl_info->ctr_drbg = NULL; | |
} | |
if(NULL != ssl_info->ssl) | |
{ | |
free(ssl_info->ssl); | |
ssl_info->ssl = NULL; | |
} | |
if(NULL != ssl_info->conf) | |
{ | |
free(ssl_info->conf); | |
ssl_info->conf = NULL; | |
} | |
if(NULL != ssl_info->cacert) | |
{ | |
free(ssl_info->cacert); | |
ssl_info->cacert = NULL; | |
} | |
if(NULL != ssl_info->clientcert) | |
{ | |
free(ssl_info->clientcert); | |
ssl_info->clientcert = NULL; | |
} | |
if(NULL != ssl_info->clientkey) | |
{ | |
free(ssl_info->clientkey); | |
ssl_info->clientkey = NULL; | |
} | |
return MBTK_MBEDTLS_SSL_RESULT_SUCCESS; | |
} | |
static mbtk_mbedtls_ssl_result_e mbtk_mbedtls_ssl_info_malloc(mbtk_mbedtls_ssl_info_s *ssl_info) | |
{ | |
if(NULL == ssl_info) | |
{ | |
LOGE("[%s] ssl_info [NULL]", __func__); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
ssl_info->entropy = (mbedtls_entropy_context *)malloc(sizeof(mbedtls_entropy_context)); | |
if(NULL == ssl_info->entropy) | |
{ | |
LOGE("[%s] entropy malloc() fail", __func__); | |
goto free_error; | |
} | |
ssl_info->ctr_drbg = (mbedtls_ctr_drbg_context *)malloc(sizeof(mbedtls_ctr_drbg_context)); | |
if(NULL == ssl_info->ctr_drbg) | |
{ | |
LOGE("[%s] ctr_drbg malloc() fail", __func__); | |
goto free_error; | |
} | |
ssl_info->ssl = (mbedtls_ssl_context *)malloc(sizeof(mbedtls_ssl_context)); | |
if(NULL == ssl_info->ssl) | |
{ | |
LOGE("[%s] ssl malloc() fail", __func__); | |
goto free_error; | |
} | |
ssl_info->conf = (mbedtls_ssl_config *)malloc(sizeof(mbedtls_ssl_config)); | |
if(NULL == ssl_info->conf) | |
{ | |
LOGE("[%s] conf malloc() fail", __func__); | |
goto free_error; | |
} | |
ssl_info->cacert = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); | |
if(NULL == ssl_info->cacert) | |
{ | |
LOGE("[%s] cacert malloc() fail", __func__); | |
goto free_error; | |
} | |
ssl_info->clientcert = (mbedtls_x509_crt *)malloc(sizeof(mbedtls_x509_crt)); | |
if(NULL == ssl_info->clientcert) | |
{ | |
LOGE("[%s] clientcert malloc() fail", __func__); | |
goto free_error; | |
} | |
ssl_info->clientkey = (mbedtls_pk_context *)malloc(sizeof(mbedtls_pk_context)); | |
if(NULL == ssl_info->clientkey) | |
{ | |
LOGE("[%s] clientkey malloc() fail", __func__); | |
goto free_error; | |
} | |
return MBTK_MBEDTLS_SSL_RESULT_SUCCESS; | |
free_error: | |
mbtk_mbedtls_ssl_info_free(ssl_info); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
mbtk_mbedtls_ssl_result_e mbtk_mbedtls_ssl_options_default(mbtk_mbedtls_ssl_options_s *opt) | |
{ | |
if(NULL == opt) | |
{ | |
LOGE("[%s] opt [NULL]", __func__); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
const mbedtls_x509_crt_profile mbtk_profile = mbedtls_x509_crt_profile_default; | |
opt->load_cert = false; | |
opt->ca_file = NULL; | |
opt->crt_file = NULL; | |
opt->key_file = NULL; | |
opt->pers_str = (unsigned char*)MBTK_SSL_PERS_STR_DEFAULT; | |
opt->pers_str_size = strlen((const char*)opt->pers_str); | |
opt->type = MBTK_MBEDTLS_SSL_IS_CLIENT; | |
opt->transprot = MBTK_MBEDTLS_SSL_TRANSPROT_STREAM; | |
opt->preset = MBTK_MBEDTLS_SSL_PRESET_DEFAULT; | |
opt->auth_mode = MBTK_MBEDTLS_SSL_VERIFY_OPTIONAL; | |
opt->renegotiation = MBTK_MBEDTLS_SSL_RENEGOTIATION_DISABLED; | |
opt->allow_legacy = MBTK_MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; | |
opt->min_version = MBTK_MBEDTLS_SSL_MINOR_VERSION_3; | |
opt->max_version = MBTK_MBEDTLS_SSL_MINOR_VERSION_4; | |
opt->allowed_mds = mbtk_profile.allowed_mds; | |
return MBTK_MBEDTLS_SSL_RESULT_SUCCESS; | |
} | |
int mbtk_mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) | |
{ | |
return mbedtls_ssl_write(ssl, buf, len); | |
} | |
int mbtk_mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) | |
{ | |
return mbedtls_ssl_read(ssl, buf, len); | |
} | |
mbtk_mbedtls_ssl_result_e mbtk_mbedtls_ssl_init(int fd , mbtk_mbedtls_ssl_options_s *opt, mbtk_mbedtls_ssl_info_s* inter_info) | |
{ | |
int ret = -1; | |
uint32_t flags = 0; | |
char verify_err[MBTK_SSL_BUFFER_SIZE_1024 + 1] = {0}; | |
char cert_buff[MBTK_SSL_BUFFER_SIZE_1024 + 1] = {0}; | |
mbtk_mbedtls_ssl_options_s temp_opt = {0}; | |
mbtk_mbedtls_ssl_info_s temp_ssl_info = {0}; | |
mbedtls_x509_crt_profile mbtk_profile = mbedtls_x509_crt_profile_default; | |
if(NULL == inter_info) | |
{ | |
LOGE("[%s] inter_info [NULL]", __func__); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
if(NULL == opt) | |
{ | |
ret = mbtk_mbedtls_ssl_options_default(&temp_opt); | |
} | |
else | |
{ | |
memset(&temp_opt, 0x00, sizeof(mbtk_mbedtls_ssl_options_s)); | |
memcpy(&temp_opt, opt, sizeof(mbtk_mbedtls_ssl_options_s)); | |
} | |
memset(&temp_ssl_info, 0x00, sizeof(mbtk_mbedtls_ssl_info_s)); | |
ret = mbtk_mbedtls_ssl_info_malloc(&temp_ssl_info); | |
if(ret != 0) | |
{ | |
LOGE("[%s] mbtk_mbedtls_ssl_info_malloc() fail", __func__); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
mbedtls_ctr_drbg_init(temp_ssl_info.ctr_drbg); | |
mbedtls_entropy_init(temp_ssl_info.entropy); | |
mbedtls_ssl_init(temp_ssl_info.ssl); | |
mbedtls_ssl_config_init(temp_ssl_info.conf); | |
mbedtls_x509_crt_init(temp_ssl_info.cacert); | |
mbedtls_x509_crt_init(temp_ssl_info.clientcert); | |
mbedtls_pk_init(temp_ssl_info.clientkey); | |
//1.Initialize the function for CTR_DRBG pseudorandom number generator | |
ret = mbedtls_ctr_drbg_seed(temp_ssl_info.ctr_drbg, mbedtls_entropy_func, temp_ssl_info.entropy, temp_opt.pers_str, temp_opt.pers_str_size); | |
if (ret != 0) | |
{ | |
LOGE("[%s] mbedtls_ctr_drbg_seed() fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
//2.Load certificate | |
if(temp_opt.load_cert) | |
{ | |
if(NULL == temp_opt.ca_file || NULL == temp_opt.crt_file || NULL == temp_opt.key_file) | |
{ | |
LOGE("[%s] file [NULL]", __func__); | |
goto error; | |
} | |
//2.1-Load root certificate | |
ret = mbedtls_x509_crt_parse_file(temp_ssl_info.cacert, temp_opt.ca_file); | |
if(ret != 0) | |
{ | |
LOGE("[%s] mbedtls_x509_crt_parse_file() CA fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
//2.2-Load the client public key | |
ret = mbedtls_x509_crt_parse_file(temp_ssl_info.clientcert, temp_opt.crt_file); | |
if(ret != 0) | |
{ | |
LOGE("[%s] mbedtls_x509_crt_parse_file() CRT fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
//2.3-Load the client private key | |
ret = mbedtls_pk_parse_keyfile(temp_ssl_info.clientkey, temp_opt.key_file, NULL, mbedtls_ctr_drbg_random, temp_ssl_info.ctr_drbg); | |
if(ret != 0) | |
{ | |
LOGE("[%s] mbedtls_pk_parse_keyfile() KEY fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
} | |
LOGD("[%s] Configure the SSL/TLS context...", __func__); | |
//3.Configure the SSL/TLS context | |
ret = mbedtls_ssl_config_defaults(temp_ssl_info.conf, temp_opt.type, temp_opt.transprot, temp_opt.preset); | |
if(ret != 0) | |
{ | |
LOGE("[%s] mbedtls_ssl_config_defaults() fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
mbedtls_ssl_conf_authmode(temp_ssl_info.conf, temp_opt.auth_mode); | |
mbedtls_ssl_conf_ca_chain(temp_ssl_info.conf, temp_ssl_info.cacert, NULL); | |
if(temp_opt.load_cert) | |
{ | |
ret = mbedtls_ssl_conf_own_cert(temp_ssl_info.conf, temp_ssl_info.clientcert, temp_ssl_info.clientkey); | |
if(ret != 0) | |
{ | |
LOGE("[%s] mbedtls_ssl_conf_own_cert() fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
} | |
mbedtls_ssl_conf_rng(temp_ssl_info.conf, mbedtls_ctr_drbg_random, temp_ssl_info.ctr_drbg); | |
//mbedtls_ssl_conf_renegotiation(&conf, temp_opt.renegotiation); | |
mbedtls_ssl_conf_legacy_renegotiation(temp_ssl_info.conf, temp_opt.allow_legacy); | |
// TLS 1.2 | |
mbedtls_ssl_conf_min_version(temp_ssl_info.conf, MBEDTLS_SSL_MAJOR_VERSION_3, temp_opt.min_version); | |
// TLS 1.3 | |
mbedtls_ssl_conf_max_version(temp_ssl_info.conf, MBEDTLS_SSL_MAJOR_VERSION_3, temp_opt.max_version); | |
mbtk_profile.allowed_mds = temp_opt.allowed_mds; | |
mbedtls_ssl_conf_cert_profile(temp_ssl_info.conf, &mbtk_profile); | |
//4.Binding SSL configuration | |
ret = mbedtls_ssl_setup(temp_ssl_info.ssl, temp_ssl_info.conf); | |
if (ret != 0) | |
{ | |
LOGE("[%s] mbedtls_ssl_setup() fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
mbedtls_ssl_set_bio(temp_ssl_info.ssl, &fd, mbedtls_net_send, mbedtls_net_recv, NULL); | |
LOGD("[%s] Performing the SSL/TLS handshake...", __func__); | |
//5.Shake hands | |
while((ret = mbedtls_ssl_handshake(temp_ssl_info.ssl)) != 0) | |
{ | |
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) | |
{ | |
LOGE("[%s] mbedtls_ssl_handshake() fail.[-0x%x]", __func__, -ret); | |
goto error; | |
} | |
} | |
LOGD("[%s] Handshake ok: Protocol[%s], Ciphersuite[%s]", __func__, mbedtls_ssl_get_version(temp_ssl_info.ssl), mbedtls_ssl_get_ciphersuite(temp_ssl_info.ssl)); | |
//6.Verification certificate | |
flags = mbedtls_ssl_get_verify_result(temp_ssl_info.ssl); | |
if(flags != 0) | |
{ | |
memset(verify_err, 0x00, MBTK_SSL_BUFFER_SIZE_1024 + 1); | |
mbedtls_x509_crt_verify_info(verify_err, MBTK_SSL_BUFFER_SIZE_1024, "[mbedtls_ssl_get_verify_result] ", flags); | |
LOGD("%s", verify_err); | |
if(temp_opt.auth_mode == MBTK_MBEDTLS_SSL_VERIFY_REQUIRED) | |
{ | |
LOGE("[%s] mbedtls_ssl_get_verify_result() fail", __func__); | |
goto error; | |
} | |
} | |
if(mbedtls_ssl_get_peer_cert(temp_ssl_info.ssl) != NULL) | |
{ | |
LOGD("[%s] Peer certificate information", __func__); | |
memset(cert_buff, 0x00, MBTK_SSL_BUFFER_SIZE_1024 + 1); | |
mbedtls_x509_crt_info(cert_buff, MBTK_SSL_BUFFER_SIZE_1024, "[mbedtls_ssl_get_verify_result] ", mbedtls_ssl_get_peer_cert(temp_ssl_info.ssl)); | |
LOGD("%s", cert_buff); | |
} | |
temp_ssl_info.fd = fd; | |
memcpy(inter_info, &temp_ssl_info, sizeof(mbtk_mbedtls_ssl_info_s)); | |
return MBTK_MBEDTLS_SSL_RESULT_SUCCESS; | |
error: | |
mbedtls_ssl_close_notify(temp_ssl_info.ssl); | |
mbedtls_ssl_free(temp_ssl_info.ssl); | |
mbedtls_ssl_config_free(temp_ssl_info.conf); | |
mbedtls_ctr_drbg_free(temp_ssl_info.ctr_drbg); | |
mbedtls_entropy_free(temp_ssl_info.entropy); | |
mbedtls_pk_free(temp_ssl_info.clientkey); | |
mbedtls_x509_crt_free(temp_ssl_info.clientcert); | |
mbedtls_x509_crt_free(temp_ssl_info.cacert); | |
mbtk_mbedtls_ssl_info_free(&temp_ssl_info); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
mbtk_mbedtls_ssl_result_e mbtk_mbedtls_ssl_deinit(mbtk_mbedtls_ssl_info_s* inter_info) | |
{ | |
if(NULL == inter_info) | |
{ | |
LOGE("[%s] inter_info [NULL]", __func__); | |
return MBTK_MBEDTLS_SSL_RESULT_FAIL; | |
} | |
int ret = -1; | |
char error_buf[MBTK_SSL_BUFFER_SIZE_128 + 1] = {0}; | |
do { | |
ret = mbedtls_ssl_close_notify(inter_info->ssl); | |
} while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); | |
if(ret != 0) | |
{ | |
memset(error_buf, 0x00, MBTK_SSL_BUFFER_SIZE_128 + 1); | |
mbedtls_strerror(ret, error_buf, MBTK_SSL_BUFFER_SIZE_128); | |
LOGE("[%s] mbedtls_ssl_close_notify() fail.[%s]", __func__, error_buf); | |
} | |
mbedtls_ssl_close_notify(inter_info->ssl); | |
mbedtls_ssl_free(inter_info->ssl); | |
mbedtls_ssl_config_free(inter_info->conf); | |
mbedtls_ctr_drbg_free(inter_info->ctr_drbg); | |
mbedtls_entropy_free(inter_info->entropy); | |
mbedtls_pk_free(inter_info->clientkey); | |
mbedtls_x509_crt_free(inter_info->clientcert); | |
mbedtls_x509_crt_free(inter_info->cacert); | |
inter_info->fd = MBTK_SSL_INFO_FD_DEFAULT; | |
mbtk_mbedtls_ssl_info_free(inter_info); | |
return MBTK_MBEDTLS_SSL_RESULT_SUCCESS; | |
} | |
#endif |