其实我的项目中有用mbedtls封装的ssl_mbedtls.c文件,/* Copyright(c) 2024 TP-Link Systems Inc.
*
* file
* brief SSL APIs for mbedtls
* details
*
* author Wang Shiqin
* version 1.0.0
* date 16Sep19
*
* warning
*
* history \arg
*/
#if defined(INCLUDE_SSL) && defined(INCLUDE_SSL_MBEDTLS)
//#define SSL_DEBUG_TIME
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include "ssl_backend.h"
#include "ssl_mbedtls.h"
#include <mbedtls/debug.h>
#ifdef INCLUDE_IMDA
static int g_ciphersuite[7] = { 0x2F, /* TLS_RSA_WITH_AES_128_CBC_SHA */
0x35, /* TLS_RSA_WITH_AES_256_CBC_SHA */
0xC02F, /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */
0xC014, /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */
0xC013, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */
0,
0 };
#elif defined(INCLUDE_CIPHER_LIST)
static int g_ciphersuite[5] = { 0xC030, /* TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 */
0xC02B, /* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 */
0xC0AD, /* TLS_ECDHE_ECDSA_WITH_AES_256_CCM */
0xC0AC, /* TLS_ECDHE_ECDSA_WITH_AES_128_CCM */
0 };
#else
static int g_ciphersuite[7] = { 0x2F, /* TLS_RSA_WITH_AES_128_CBC_SHA */
0x35, /* TLS_RSA_WITH_AES_256_CBC_SHA */
0x0A, /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
0xC02F, /* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 */
0xC014, /* TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA */
0xC013, /* TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA */
0 };
#endif
static int g_accept_timeout = 5000; /* 5s */
static int g_read_timeout = 5000; /* 5s */
static int g_write_timeout = 5000; /* 5s */
void set_debug_level(int level)
{
ssl_log(SSL_ERROR, "mbedtls_debug_set_threshold %d", level);
mbedtls_debug_set_threshold(level);
}
void tls_init_lib(void)
{
ssl_loglevel_init();
}
void tls_free_lib(void)
{
}
void tls_clear_error(void)
{
}
int tls_ctx_server_new(struct tls_root_ctx *ctx)
{
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ctx) return -1;
ctx->ca_chain = (mbedtls_x509_crt*)malloc(sizeof(mbedtls_x509_crt));
if (NULL == ctx->ca_chain) goto error;
ctx->crt_chain = (mbedtls_x509_crt*)malloc(sizeof(mbedtls_x509_crt));
if (NULL == ctx->crt_chain) goto error;
ctx->priv_key = (mbedtls_pk_context*)malloc(sizeof(mbedtls_pk_context));
if (NULL == ctx->priv_key) goto error;
mbedtls_x509_crt_init(ctx->ca_chain);
mbedtls_x509_crt_init(ctx->crt_chain);
mbedtls_pk_init(ctx->priv_key);
ctx->endpoint = MBEDTLS_SSL_IS_SERVER;
ctx->initialised = 1;
return 0;
error:
ssl_log(SSL_ERROR, "tls_ctx_server_new failed");
if (ctx->ca_chain) free(ctx->ca_chain);
if (ctx->crt_chain) free(ctx->crt_chain);
if (ctx->priv_key) free(ctx->priv_key);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return -1;
}
int tls_ctx_client_new(struct tls_root_ctx *ctx)
{
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ctx) return -1;
ctx->ca_chain = (mbedtls_x509_crt*)malloc(sizeof(mbedtls_x509_crt));
if (NULL == ctx->ca_chain) goto error;
ctx->crt_chain = (mbedtls_x509_crt*)malloc(sizeof(mbedtls_x509_crt));
if (NULL == ctx->crt_chain) goto error;
ctx->priv_key = (mbedtls_pk_context*)malloc(sizeof(mbedtls_pk_context));
if (NULL == ctx->priv_key) goto error;
mbedtls_x509_crt_init(ctx->ca_chain);
mbedtls_x509_crt_init(ctx->crt_chain);
mbedtls_pk_init(ctx->priv_key);
ctx->verify_time = 0;
ctx->verify_cn = NULL;
ctx->endpoint = MBEDTLS_SSL_IS_CLIENT;
ctx->initialised = 1;
return 0;
error:
ssl_log(SSL_ERROR, "tls_ctx_client_new failed");
if (ctx->ca_chain) free(ctx->ca_chain);
if (ctx->crt_chain) free(ctx->crt_chain);
if (ctx->priv_key) free(ctx->priv_key);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return -1;
}
void tls_ctx_free(struct tls_root_ctx *ctx)
{
if (ctx)
{
mbedtls_pk_free(ctx->priv_key);
if (ctx->priv_key)
{
free(ctx->priv_key);
}
mbedtls_x509_crt_free(ctx->ca_chain);
if (ctx->ca_chain)
{
free(ctx->ca_chain);
}
mbedtls_x509_crt_free(ctx->crt_chain);
if (ctx->crt_chain)
{
free(ctx->crt_chain);
}
ctx->verify_time = 0;
ctx->verify_cn = NULL;
ctx->initialised = 0;
free(ctx);
ctx = NULL;
}
}
int tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)
{
return 0;
}
static int verify_callback( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
{
char buf[1024];
((void) data);
ssl_log(SSL_ERROR, "Verify requested for (Depth %d):", depth);
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
ssl_log(SSL_ERROR, "%s", buf);
if ((*flags) == 0)
{
ssl_log(SSL_ERROR, "This certificate has no flags");
}
else
{
mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", *flags);
ssl_log(SSL_ERROR, "%s\n", buf);
}
return 0;
}
int tls_ctx_verify_cloud(struct tls_root_ctx *ctx, char *cert_file, int verify_time, char *cn)
{
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ctx || NULL == cert_file) return -1;
if (NULL == ctx->crt_chain || mbedtls_x509_crt_parse_file(ctx->crt_chain, cert_file) != 0)
{
ssl_log(SSL_ERROR, "load cer file error");
return -1;
}
ctx->verify_time = verify_time;
ctx->verify_cn = cn;
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int tls_ctx_verify_ca_buf(struct tls_root_ctx *ctx, const void *cert_buf, size_t len)
{
int ret = 0;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == cert_buf || NULL == ctx || NULL == ctx->crt_chain) return -1;
ssl_log(SSL_DEBUG, "buf len: %d %d", len, strlen(cert_buf));
if ((ret = mbedtls_x509_crt_parse(ctx->crt_chain, cert_buf, len)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509_crt_parse fail. ret=%d", ret);
return -1;
}
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int tls_ctx_verify_init(struct tls_root_ctx *ctx, int depth, char *ca_path, void *ud)
{
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ctx || NULL == ca_path) return -1;
if (NULL == ctx->ca_chain || mbedtls_x509_crt_parse_file(ctx->ca_chain, ca_path) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509_crt_parse_file fail.");
return -1;
}
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int tls_ctx_check_key(struct tls_root_ctx *ctx, char *cert_file, char *key_file, void *passwd)
{
int status;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ctx || NULL == cert_file || NULL == key_file
|| NULL == ctx->crt_chain) return -1;
if ((status = mbedtls_x509_crt_parse_file(ctx->crt_chain, cert_file)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509_crt_parse_file fail. ret=%d", status);
return -1;
}
if (NULL == ctx->priv_key) return -1;
status = mbedtls_pk_parse_keyfile(ctx->priv_key, key_file, NULL);
if (MBEDTLS_ERR_PK_PASSWORD_REQUIRED == status)
{
status = mbedtls_pk_parse_keyfile(ctx->priv_key, key_file, (const char*)passwd);
}
if (0 != status)
{
ssl_log(SSL_ERROR, "Cannot load private key file %s", key_file);
return -1;
}
if (mbedtls_pk_check_pair(&ctx->crt_chain->pk, ctx->priv_key) != 0)
{
ssl_log(SSL_ERROR, "Private key does not match the certificate");
return -1;
}
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
static void tp_debug(void *ctx, int level, const char *file, int line, const char *str)
{
const char *p, *basename;
/* Extract basename from file */
for (p = basename = file; *p != '\0'; p++)
if (*p == '/' || *p == '\\')
basename = p + 1;
fprintf((FILE *)ctx, "%s:%04d: |%d| %s", basename, line, level, str);
fflush((FILE *)ctx);
}
static void ssl_init_debug_level(void)
{
int level = 1;
FILE *f = NULL;
char line[5] = {0};
f = fopen("/var/mbedtls/dbg", "r");
if (f == NULL || fgets(line, sizeof(line), f) == NULL ||
sscanf(line, "%d", &level) != 1)
{
level = 0;
}
if (f != NULL) fclose(f);
set_debug_level(level);
}
static void ssl_init_timeout(void)
{
int accept_timeout = 5000;
int read_timeout = 5000;
int write_timeout = 5000;
FILE *f = NULL;
char line[32] = {0};
f = fopen("/var/mbedtls/timeout", "r");
if (f == NULL || fgets(line, sizeof(line), f) == NULL ||
sscanf(line, "%d %d %d", &accept_timeout, &read_timeout, &write_timeout) != 3)
{
if (f != NULL) fclose(f);
return;
}
if (f != NULL) fclose(f);
g_accept_timeout = accept_timeout;
g_read_timeout = read_timeout;
g_write_timeout = write_timeout;
ssl_log(SSL_ERROR, "g_accept_timeout: %d, g_read_timeout: %d, g_write_timeout: %d\n",
g_accept_timeout, g_read_timeout, g_write_timeout);
}
static void ssl_init_hs_dbg_level(void)
{
int level = 1;
FILE *f = NULL;
char line[5] = {0};
f = fopen("/var/mbedtls/hs", "r");
if (f == NULL || fgets(line, sizeof(line), f) == NULL ||
sscanf(line, "%d", &level) != 1)
{
level = 0;
}
if (f != NULL) fclose(f);
set_debug_level(level);
}
static void ssl_init_stream(struct tp_stream *stream)
{
stream->buf[0] = '\0';
stream->cur = stream->buf;
stream->end = stream->buf;
}
static inline void buf_free_entry(struct buf_entry *entry)
{
if (NULL != entry)
{
//printf("-free %p\n", entry);
free(entry->data);
free(entry);
}
}
static void buf_free_entries(struct write_buf *buf)
{
while (buf->first_block)
{
struct buf_entry *cur_block = buf->first_block;
buf->first_block = cur_block->next_block;
buf_free_entry(cur_block);
}
buf->last_block = NULL;
buf->cur_block = NULL;
buf->data_len = 0;
}
static struct buf_entry* buf_create_entry(void)
{
struct buf_entry *entry = (struct buf_entry *)malloc(sizeof(struct buf_entry));
if (NULL == entry) return NULL;
entry->data = (char *)malloc(TP_BUF_ENTRY_LEN);
if (NULL == entry->data)
{
free(entry);
return NULL;
}
entry->used_len = 0;
entry->free_len = TP_BUF_ENTRY_LEN;
entry->next_block = NULL;
//printf("+create %p\n", entry);
return entry;
}
static int buf_write_data_1block(struct write_buf *buf, char *in, size_t len)
{
struct buf_entry *cur_block = buf->cur_block;
if (len > TP_BUF_ENTRY_LEN)
{
return -1;
}
if (NULL == cur_block)
{
cur_block = buf_create_entry();
if (NULL == cur_block) return -1;
cur_block->next_block = NULL;
if (NULL == buf->first_block)
{
buf->first_block = cur_block;
}
if (NULL != buf->last_block)
{
buf->last_block->next_block = cur_block;
}
buf->last_block = buf->cur_block = cur_block;
}
else
{
if (cur_block->free_len < len)
{
cur_block= cur_block->next_block;
if (NULL == cur_block)
{
cur_block = buf_create_entry();
if (NULL == cur_block) return -1;
cur_block->next_block = NULL;
buf->last_block->next_block = cur_block;
buf->last_block = buf->cur_block = cur_block;
}
else
{
if (cur_block->free_len != TP_BUF_ENTRY_LEN ||
cur_block->used_len > 0)
{
ssl_log(SSL_ERROR, "free_len: %d, used_len: %d\n",
cur_block->free_len, cur_block->used_len);
return -1;
}
buf->cur_block = cur_block;
}
}
}
//printf("cur_block: %p\n", cur_block);
if (cur_block->free_len < len)
{
ssl_log(SSL_ERROR, "free_len: %d, len: %d\n", cur_block->free_len, len);
return -1;
}
if (cur_block->used_len + len > TP_BUF_ENTRY_LEN)
{
ssl_log(SSL_ERROR, "used_len: %d, len: %d\n", cur_block->used_len, len);
return -1;
}
memcpy(cur_block->data + cur_block->used_len, in, len);
cur_block->used_len += len;
cur_block->free_len -= len;
buf->data_len += len;
return len;
}
static int buf_write_data(struct write_buf *buf, char *in, size_t len)
{
int ret;
size_t write_len = 0;
size_t left_len = len;
while (left_len > 0)
{
ret = (left_len < TP_BUF_ENTRY_LEN) ? left_len : TP_BUF_ENTRY_LEN;
ret = buf_write_data_1block(buf, in + write_len, ret);
if (ret <= 0) return -1;
write_len += ret;
left_len -= ret;
}
return write_len;
}
static int buf_read_data(struct write_buf *buf, char *out, size_t len)
{
size_t read_len = 0;
struct buf_entry *cur_block = buf->first_block;
while (cur_block)
{
if (cur_block->used_len == 0) return read_len;
if (len - read_len < cur_block->used_len) return read_len;
memcpy(out + read_len, cur_block->data, cur_block->used_len);
read_len += cur_block->used_len;
cur_block = cur_block->next_block;
}
return read_len;
}
static size_t buf_get_data_len(struct write_buf *buf)
{
return buf->data_len;
}
static void buf_reinit(struct write_buf *buf)
{
if (NULL == buf) return;
struct buf_entry *cur_block = buf->first_block;
while (cur_block)
{
cur_block->free_len = TP_BUF_ENTRY_LEN;
cur_block->used_len = 0;
cur_block = cur_block->next_block;
}
buf->cur_block = buf->first_block;
buf->data_len = 0;
}
#if 0
static void buf_info(struct write_buf *buf)
{
struct buf_entry *cur_block;
printf("%d (%p %p %p)\n", buf->data_len, buf->first_block, buf->cur_block,
buf->last_block);
cur_block = buf->first_block;
while (cur_block)
{
printf("%p: %d %d\n", cur_block, cur_block->free_len, cur_block->used_len);
cur_block = cur_block->next_block;
}
}
#endif
static long long get_time_ms()
{
struct timeval tv;
if (0 != gettimeofday(&tv, NULL)) {
return 0;
}
return ((long long)tv.tv_sec * 1000 + (long long)tv.tv_usec / 1000);
}
#ifdef INCLUDE_HTTP_SSL_MIN_TLS1_2
int ssl_init(struct tp_ssl *ssl, const struct tls_root_ctx *ssl_ctx, int is_server, int is_cwmp)
#else
int ssl_init(struct tp_ssl *ssl, const struct tls_root_ctx *ssl_ctx, int is_server)
#endif /* INCLUDE_HTTP_SSL_MIN_TLS1_2 */
{
int ret = -1;
const char *pers = "tp_ssl";
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ssl || NULL == ssl_ctx) return -1;
memset(ssl, 0, sizeof(struct tp_ssl));
ssl_init_debug_level();
ssl_init_timeout();
mbedtls_ctr_drbg_init(&ssl->ctr_drbg);
mbedtls_entropy_init(&ssl->entropy);
if ((ret = mbedtls_ctr_drbg_seed(&ssl->ctr_drbg, mbedtls_entropy_func, &ssl->entropy,
(const unsigned char *) pers, strlen(pers))) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_ctr_drbg_seed returned %d\n", ret );
goto exit;
}
/* Initialise SSL config */
mbedtls_ssl_config_init(&ssl->ssl_config);
if ((ret = mbedtls_ssl_config_defaults(&ssl->ssl_config, ssl_ctx->endpoint,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_config_defaults returned %d\n", ret );
goto exit;
}
mbedtls_ssl_conf_rng(&ssl->ssl_config, mbedtls_ctr_drbg_random, &ssl->ctr_drbg);
mbedtls_ssl_conf_dbg(&ssl->ssl_config, tp_debug, stdout);
mbedtls_ssl_cache_init(&ssl->cache);
mbedtls_ssl_conf_session_cache(&ssl->ssl_config, &ssl->cache,
mbedtls_ssl_cache_get,
mbedtls_ssl_cache_set);
mbedtls_ssl_conf_ciphersuites(&ssl->ssl_config, g_ciphersuite);
mbedtls_ssl_conf_ca_chain(&ssl->ssl_config, ssl_ctx->ca_chain, NULL);
if ((ret = mbedtls_ssl_conf_own_cert(&ssl->ssl_config, ssl_ctx->crt_chain,
ssl_ctx->priv_key)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_conf_own_cert returned %d\n", ret );
goto exit;
}
if (!is_server)
{
mbedtls_ssl_conf_verify(&ssl->ssl_config, verify_callback, NULL);
mbedtls_ssl_conf_authmode(&ssl->ssl_config, MBEDTLS_SSL_VERIFY_OPTIONAL);
}
#ifdef INCLUDE_IMDA
mbedtls_ssl_conf_min_version(&ssl->ssl_config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
#else
#ifdef INCLUDE_HTTP_SSL_MIN_TLS1_2
if (1 != is_cwmp)
{
mbedtls_ssl_conf_min_version(&ssl->ssl_config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
}
else
#endif /* INCLUDE_HTTP_SSL_MIN_TLS1_2 */
{
mbedtls_ssl_conf_min_version(&ssl->ssl_config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_1);
}
#endif /* INCLUDE_IMDA */
mbedtls_ssl_conf_max_version(&ssl->ssl_config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
/* Initialise SSL context */
ssl->ctx = (mbedtls_ssl_context*)malloc(sizeof(mbedtls_ssl_context));
if (NULL == ssl->ctx) goto exit;
mbedtls_ssl_init(ssl->ctx);
if (mbedtls_ssl_setup(ssl->ctx, &ssl->ssl_config) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_setup failed");
return -1;
}
if (is_server)
{
ssl->endpoint = MBEDTLS_SSL_IS_SERVER;
}
else
{
if (ssl_ctx->verify_cn)
{
mbedtls_ssl_set_hostname(ssl->ctx, ssl_ctx->verify_cn);
ssl->verify_cn = 1;
}
if (ssl_ctx->verify_time)
{
ssl->verify_time = 1;
}
ssl->endpoint = MBEDTLS_SSL_IS_CLIENT;
}
ssl_init_stream(&ssl->stream);
ret = 0;
exit:
ssl_log(SSL_DEBUG, "leave %s ret=%d", __FUNCTION__, ret);
return ret;
}
void ssl_free(struct tp_ssl *ssl)
{
if (ssl)
{
if (ssl->ctx)
{
mbedtls_ssl_free(ssl->ctx);
free(ssl->ctx);
}
mbedtls_ssl_config_free(&ssl->ssl_config);
mbedtls_ctr_drbg_free(&ssl->ctr_drbg);
mbedtls_entropy_free(&ssl->entropy);
mbedtls_ssl_cache_free(&ssl->cache);
if (ssl->endpoint == MBEDTLS_SSL_IS_SERVER)
{
mbedtls_net_free(&ssl->client_fd);
}
if (ssl->endpoint == MBEDTLS_SSL_IS_CLIENT)
{
mbedtls_net_free(&ssl->server_fd);
}
buf_free_entries(&ssl->out);
ssl->verify_cn = 0;
ssl->verify_time = 0;
free(ssl);
ssl = NULL;
}
}
void ssl_shutdown(struct tp_ssl *ssl)
{
int ret;
if (NULL == ssl || NULL == ssl->ctx) return;
do {
ssl_log(SSL_DEBUG, "=========================================================== ->\n");
ret = mbedtls_ssl_close_notify(ssl->ctx);
ssl_log(SSL_DEBUG, "=========================================================== <-\n");
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
}
int ssl_reset(struct tp_ssl *ssl, const struct tls_root_ctx *ssl_ctx)
{
if (NULL == ssl || NULL == ssl->ctx) return -1;
//mbedtls_ssl_session_reset(ssl->ctx);
if (ssl->endpoint == MBEDTLS_SSL_IS_SERVER)
{
ssl_log(SSL_DEBUG, "close %d", ssl->client_fd.fd);
mbedtls_net_free(&ssl->client_fd);
}
if (ssl->endpoint == MBEDTLS_SSL_IS_CLIENT)
{
ssl_log(SSL_DEBUG, "close %d", ssl->server_fd.fd);
mbedtls_net_free(&ssl->server_fd);
}
ssl_init_stream(&ssl->stream);
//buf_reinit(&ssl->out);
buf_free_entries(&ssl->out); /* free the out buffer, not just reinit */
return 0;
}
#if defined (INCLUDE_DYNDNS_HTTPS) || defined(INCLUDE_NOIPDNS_HTTPS)
int ssl_connect(struct tp_ssl *ssl, int sockfd, int timeout, int needTrustedCA)
#else
int ssl_connect(struct tp_ssl *ssl, int sockfd, int timeout)
#endif /* INCLUDE_DYNDNS_HTTPS || INCLUDE_NOIPDNS_HTTPS */
{
int ret;
unsigned int flags;
long long time_remain = (long long)timeout;
long long time_begin = 0;
long long time_spend = 0;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ssl || NULL == ssl->ctx)
{
return -1;
}
mbedtls_net_init(&ssl->server_fd);
ssl_log(SSL_DEBUG, "mbedtls_ssl_set_bio");
ssl->server_fd.fd = sockfd;
//mbedtls_ssl_set_bio(ssl->ctx, &ssl->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_conf_read_timeout(&ssl->ssl_config, timeout);
mbedtls_ssl_set_bio(ssl->ctx, &ssl->server_fd, mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
ssl_log(SSL_DEBUG, "mbedtls_ssl_handshake");
ssl_init_hs_dbg_level();
while((ret = mbedtls_ssl_handshake(ssl->ctx)) != 0)
{
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_handshake returned -0x%x", -ret);
return -1;
}
time_begin = get_time_ms();
time_remain -= time_spend;
ssl_log(SSL_ERROR, "==> time_remain: %llu ms time_spend: %llu ms", time_remain, time_spend);
if (time_remain < 0)
{
ssl_log(SSL_ERROR, "==> mbedtls_ssl_handshake timeout %d ms", timeout);
return -1;
}
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
struct timeval tv;
tv.tv_sec = (long)(time_remain / 1000);
tv.tv_usec = (long)(time_remain % 1000) * 1000;
switch (ret)
{
case MBEDTLS_ERR_SSL_WANT_READ:
select(sockfd +1, &fds, NULL, NULL, &tv);
break;
case MBEDTLS_ERR_SSL_WANT_WRITE:
select(sockfd +1, NULL, &fds, NULL, &tv);
break;
default:
ssl_log(SSL_ERROR, "mbedtls_ssl_handshake returned -0x%x", -ret);
return -1;
}
time_spend = get_time_ms() - time_begin;
}
ssl_init_debug_level();
ssl_log(SSL_DEBUG, "mbedtls_ssl_get_verify_result");
if ((flags = mbedtls_ssl_get_verify_result(ssl->ctx)) != 0)
{
char vrfy_buf[512];
ssl_log(SSL_ERROR, "mbedtls_ssl_get_verify_result failed");
mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags);
ssl_log(SSL_ERROR, "%s", vrfy_buf);
ssl_log(SSL_ERROR, "verify flags: 0x%x", flags);
if ((ssl->verify_time && (MBEDTLS_X509_BADCERT_EXPIRED & flags))
|| (ssl->verify_cn && (MBEDTLS_X509_BADCERT_CN_MISMATCH & flags))
|| (MBEDTLS_X509_BADCERT_REVOKED & flags)
|| (MBEDTLS_X509_BADCERT_BAD_MD & flags))
{
return -1;
}
#if defined (INCLUDE_DYNDNS_HTTPS) || defined(INCLUDE_NOIPDNS_HTTPS)
if (needTrustedCA && (MBEDTLS_X509_BADCERT_NOT_TRUSTED & flags))
{
return -1;
}
#endif /* INCLUDE_DYNDNS_HTTPS || INCLUDE_NOIPDNS_HTTPS */
}
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int ssl_accept(struct tp_ssl *ssl, int sockfd)
{
int ret;
long long time_remain = (long long)g_accept_timeout;
long long time_begin = 0;
long long time_spend = 0;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ssl || NULL == ssl->ctx)
{
return -1;
}
mbedtls_net_init(&ssl->client_fd);
mbedtls_ssl_session_reset(ssl->ctx);
ssl->client_fd.fd = sockfd;
mbedtls_ssl_conf_read_timeout(&ssl->ssl_config, time_remain);
mbedtls_ssl_set_bio(ssl->ctx, &ssl->client_fd, mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
#ifdef SSL_DEBUG_TIME
struct timeval time_s;
struct timeval time_e;
int time = 0;
gettimeofday(&time_s, NULL);
#endif
ssl_init_hs_dbg_level();
while((ret = mbedtls_ssl_handshake(ssl->ctx)) != 0)
{
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_handshake returned -0x%x", -ret);
return -1;
}
time_begin = get_time_ms();
time_remain -= time_spend;
ssl_log(SSL_ERROR, "==> time_remain: %llu ms time_spend: %llu ms", time_remain, time_spend);
if (time_remain < 0)
{
ssl_log(SSL_ERROR, "==> mbedtls_ssl_handshake timeout %d ms", g_accept_timeout);
return -1;
}
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
struct timeval tv;
tv.tv_sec = (long)(time_remain / 1000);
tv.tv_usec = (long)(time_remain % 1000) * 1000;
switch (ret)
{
case MBEDTLS_ERR_SSL_WANT_READ:
select(sockfd +1, &fds, NULL, NULL, &tv);
break;
case MBEDTLS_ERR_SSL_WANT_WRITE:
select(sockfd +1, NULL, &fds, NULL, &tv);
break;
default:
ssl_log(SSL_ERROR, "mbedtls_ssl_handshake returned -0x%x", -ret);
return -1;
}
time_spend = get_time_ms() - time_begin;
}
ssl_init_debug_level();
#ifdef SSL_DEBUG_TIME
gettimeofday(&time_e, NULL);
time = ((time_e.tv_sec - time_s.tv_sec) * 1000000 + time_e.tv_usec - time_s.tv_usec);
printf("<<<<< ssl handshake: %d us %d >>>>>\n", time, sockfd);
#endif
ssl_log(SSL_DEBUG, "[ Protocol is %s ]\n[ Ciphersuite is %s ]",
mbedtls_ssl_get_version(ssl->ctx), mbedtls_ssl_get_ciphersuite(ssl->ctx));
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int ssl_read(struct tp_ssl *ssl, void *buf, int len)
{
int ret;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ssl || NULL == ssl->ctx || NULL == buf)
{
return -1;
}
long long time_out = (long long)g_read_timeout;
long long time_begin = get_time_ms();
do
{
ret = mbedtls_ssl_read(ssl->ctx, buf, len);
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
{
if (get_time_ms() - time_begin > time_out)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_read timeout: %llu ms", time_out);
return -1;
}
else
{
usleep(20 * 1000);
continue;
}
}
if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
{
ssl_log(SSL_ERROR, "MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY");
break;
}
if(ret == MBEDTLS_ERR_NET_CONN_RESET)
{
ssl_log(SSL_ERROR, "MBEDTLS_ERR_NET_CONN_RESET");
break;
}
if(ret <= 0)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_read returned %d", ret);
break;
}
if (ret > 0)
{
ssl_log(SSL_DEBUG, "read buf: len=%d [\n%s\n] ", len, (char*)buf);
break;
}
}while (1);
ssl_log(SSL_DEBUG, "leave %s ret=%d", __FUNCTION__, ret);
//printf("++++++ ssl_read %d %d ++++++\n", len, ret);
return ret;
}
int ssl_write(struct tp_ssl *ssl, void *buf, int len)
{
int ret = 0;
int written = 0;
int frags = 0;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == ssl || NULL == ssl->ctx || NULL == buf)
{
return -1;
}
for (written = 0, frags = 0; written < len; written += ret, frags++)
{
long long time_out = (long long)g_write_timeout;
long long time_begin = get_time_ms();
while ((ret = mbedtls_ssl_write(ssl->ctx, buf + written, len - written)) <= 0)
{
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_write returned %d", ret);
return ret;
}
if (get_time_ms() - time_begin > time_out)
{
ssl_log(SSL_ERROR, "mbedtls_ssl_write timeout: %llu ms", time_out);
return -1;
}
else
{
usleep(20 * 1000);
continue;
}
}
}
ssl_log(SSL_DEBUG, "leave %s ret=%d", __FUNCTION__, ret);
//printf("frags=%d\n", frags);
return written;
}
int bio_printf(struct tp_ssl *ssl, const char *format, ...)
{
va_list args;
int ret;
char buf[1024] = {0};
va_start(args, format);
ret = vsnprintf(buf, 1024, format, args);
va_end(args);
//printf("++++++ bio_printf %d ++++++\n", ret);
//printf("++ %s", buf);
return bio_write(ssl, buf, ret);
}
int bio_write(struct tp_ssl *ssl, void *buf, int len)
{
//printf("++++++ bio_write %d ++++++\n", len);
if (NULL == ssl || NULL == buf) return -1;
return buf_write_data(&ssl->out, buf, len);
}
int bio_flush(struct tp_ssl *ssl)
{
int ret;
int len;
char *buf;
if (NULL == ssl) return -1;
len = buf_get_data_len(&ssl->out);
if (0 == len) return 0;
buf = (char *)malloc(len);
if (NULL == buf) return -1;
ret = buf_read_data(&ssl->out, buf, len);
if (ret != len)
{
free(buf);
return -1;
}
//buf_info(&ssl->out);
ret = ssl_write(ssl, buf, len);
if (ret != len)
{
ssl_log(SSL_ERROR, "ssl_write len=%d ret=%d\n", len, ret);
}
free(buf);
buf_reinit(&ssl->out);
//buf_info(&ssl->out);
ssl_log(SSL_DEBUG, "++++++ bio_flush %d ++++++\n", len);
return ret;
}
int bio_read(struct tp_ssl *ssl, void *buf, int len)
{
int ret = 0;
if (NULL == ssl || NULL == buf) return -1;
struct tp_stream *stream = &ssl->stream;
if ((stream->end - stream->cur) == 0) return 0;
if (len <= (stream->end - stream->cur))
{
memcpy(buf, stream->cur, len);
ret = len;
}
else
{
memcpy(buf, stream->cur, (stream->end - stream->cur));
ret = (stream->end - stream->cur);
}
stream->cur += ret;
//printf("++++++ bio_read %d ++++++\n", len);
return ret;
}
int bio_gets(struct tp_ssl *ssl, void *buf, int len)
{
int ret = 0;
char *index = (char *)buf;
if (NULL == ssl || NULL == buf) return -1;
struct tp_stream *stream = &ssl->stream;
//printf("++++++ bio_gets %d ++++++\n", len);
while(--len)
{
if (stream->cur < stream->end)
{
if ((*index = *stream->cur++) == '\n')
{
if (index > (char *)buf && *(index - 1) == '\r')
{
index++;
break;
}
}
index++;
}
else
{
len++;
stream->cur = stream->buf;
ret = ssl_read(ssl, stream->buf, TP_STREAM_LEN);
if (ret == 0)
{
ssl_log(SSL_ERROR, "ssl_read returned %d", ret);
return 0;
}
if (ret < 0)
{
ssl_log(SSL_ERROR, "ssl_read returned %d", ret);
return -1;
}
stream->buf[ret] = '\0';
stream->end = stream->cur + ret;
continue;
}
}
if (index > (char *)buf)
{
*index = '\0';
//printf("-- %s", (char *)buf);
ssl_log(SSL_DEBUG, "bio_gets: %s", (char *)buf);
return (index - (char *)buf);
}
ssl_log(SSL_DEBUG, "bio_gets: \n%s", (char *)buf);
return ret;
}
static int gen_rand_bytes(unsigned char *buf, size_t len)
{
int ret;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_init( &ctr_drbg );
mbedtls_entropy_init( &entropy );
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *)"RANDOM_GEN", 10)) != 0)
{
ssl_log(SSL_ERROR, "failed in mbedtls_ctr_drbg_seed: %d", ret);
goto exit;
}
mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF);
if ((ret = mbedtls_ctr_drbg_random(&ctr_drbg, buf, len)) != 0)
{
ssl_log(SSL_ERROR, "failed in mbedtls_ctr_drbg_random: %d", ret);
goto exit;
}
ret = 0;
exit:
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
return ret;
}
unsigned long long gen_rand_num(int predicable)
{
int i;
unsigned char buf[8];
unsigned long long rand = 0;
if (gen_rand_bytes(buf, 8) != 0)
{
return 0;
}
for (i = 0; i < 8; i++)
{
rand = (rand << 8) | buf[i];
}
ssl_log(SSL_DEBUG, "gen rand: %llx\n", rand);
return rand;
}
#if 0
#define DEV_RANDOM_THRESHOLD 32
static int dev_random_entropy_poll( void *data, unsigned char *output,
size_t len, size_t *olen )
{
FILE *file;
size_t ret, left = len;
unsigned char *p = output;
((void) data);
ssl_log(SSL_DEBUG, "enter %s\n", __FUNCTION__);
*olen = 0;
file = fopen( "/dev/random", "rb" );
if (file == NULL)
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
while (left > 0)
{
/* /dev/random can return much less than requested. If so, try again */
ret = fread(p, 1, left, file);
if (ret == 0 && ferror( file))
{
fclose (file);
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
}
p += ret;
left -= ret;
sleep(1);
printf("ret=%d left=%d\n", ret, left);
}
fclose(file);
*olen = len;
ssl_log(SSL_DEBUG, "leave %s\n", __FUNCTION__);
return 0;
}
#endif
int gen_pkey(pkey_t **pkey, unsigned int bits)
{
int ret = -1;
mbedtls_pk_context *key;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const char *pers = "gen_key";
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == pkey) return -1;
key = (mbedtls_pk_context*)malloc(sizeof(mbedtls_pk_context));
if (NULL == key) return -1;
mbedtls_pk_init(key);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
#if 0
if ((ret = mbedtls_entropy_add_source(&entropy, dev_random_entropy_poll,
NULL, DEV_RANDOM_THRESHOLD,
MBEDTLS_ENTROPY_SOURCE_STRONG)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_entropy_add_source returned -0x%04x", -ret);
goto exit;
}
ssl_log(SSL_DEBUG, "mbedtls_entropy_add_source done");
#endif
if ((ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen(pers))) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_ctr_drbg_seed returned -0x%04x", -ret );
goto exit;
}
ssl_log(SSL_DEBUG, "mbedtls_ctr_drbg_seed done");
if ((ret = mbedtls_pk_setup(key,
mbedtls_pk_info_from_type((mbedtls_pk_type_t)MBEDTLS_PK_RSA))) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_pk_setup returned -0x%04x", -ret );
goto exit;
}
ssl_log(SSL_DEBUG, "mbedtls_pk_setup done");
ret = mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key), mbedtls_ctr_drbg_random, &ctr_drbg,
bits, 65537);
if(ret != 0)
{
ssl_log(SSL_ERROR, "mbedtls_rsa_gen_key returned -0x%04x", -ret );
goto exit;
}
ssl_log(SSL_DEBUG, "mbedtls_rsa_gen_key done");
ret = 0;
*pkey = key;
exit:
if (ret != 0) mbedtls_pk_free(key);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return ret;
}
static int print_pkey(pkey_t *key)
{
int ret = -1;
mbedtls_mpi N, P, Q, D, E, DP, DQ, QP;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
mbedtls_mpi_init(&D); mbedtls_mpi_init(&E); mbedtls_mpi_init(&DP);
mbedtls_mpi_init(&DQ); mbedtls_mpi_init(&QP);
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA)
{
mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
if ((ret = mbedtls_rsa_export(rsa, &N, &P, &Q, &D, &E)) != 0 ||
(ret = mbedtls_rsa_export_crt(rsa, &DP, &DQ, &QP)) != 0)
{
ssl_log(SSL_ERROR, "could not export RSA parameters");
goto exit;
}
mbedtls_mpi_write_file("N: ", &N, 16, NULL);
mbedtls_mpi_write_file("E: ", &E, 16, NULL);
mbedtls_mpi_write_file("D: ", &D, 16, NULL);
mbedtls_mpi_write_file("P: ", &P, 16, NULL);
mbedtls_mpi_write_file("Q: ", &Q, 16, NULL);
mbedtls_mpi_write_file("DP: ", &DP, 16, NULL);
mbedtls_mpi_write_file("DQ: ", &DQ, 16, NULL);
mbedtls_mpi_write_file("QP: ", &QP, 16, NULL);
}
else
{
ssl_log(SSL_ERROR, "error pk type.");
goto exit;
}
ret = 0;
exit:
mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
mbedtls_mpi_free(&D); mbedtls_mpi_free(&E); mbedtls_mpi_free(&DP);
mbedtls_mpi_free(&DQ); mbedtls_mpi_free(&QP);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return ret;
}
int write_private_key(pkey_t *key, const char *output_file)
{
int ret;
FILE *f = NULL;
unsigned char *output_buf = NULL;
size_t len = 0;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == key || NULL == output_file) return -1;
print_pkey(key);
output_buf = (unsigned char *)malloc(16000);
if (NULL == output_buf) return -1;
memset(output_buf, 0, 16000);
if((ret = mbedtls_pk_write_key_pem(key, output_buf, 16000)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_pk_write_key_pem returned -0x%04x", -ret );
goto exit;
}
len = strlen((char *)output_buf);
if((f = fopen(output_file, "wb")) == NULL)
{
ssl_log(SSL_ERROR, "open %s fail.", output_file);
goto exit;
}
if(fwrite(output_buf, 1, len, f) != len)
{
ssl_log(SSL_ERROR, "fwrite fail.");
goto exit;
}
ret = 0;
exit:
if (f) fclose(f);
if (output_buf) free(output_buf);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return ret;
}
void free_pkey(pkey_t *key)
{
if (key)
{
mbedtls_pk_free(key);
free(key);
key = NULL;
}
}
static int gen_cert(unsigned char *buf, size_t size, int self_sign,
int is_ca, x509_cert_t *issuer_cert, pkey_t *issuer_key,
pkey_t *subject_key, char *subject_name, char *issuer_name,
const char *not_before, const char *not_after, int pathlen,
const char *san)
{
int ret = 0;
mbedtls_x509write_cert crt;
mbedtls_mpi serial;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
char ca_subject_name[256];
pkey_t *set_subject_key, *set_issuer_key;
char *set_subject_name, *set_issuer_name;
int max_pathlen = pathlen;
const char *pers = "tp-link app";
unsigned long long serial_num;
char serial_str[20] = {0};
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == buf || NULL == issuer_key) return -1;
set_subject_key = subject_key;
set_issuer_key = issuer_key;
set_subject_name = subject_name;
set_issuer_name = issuer_name;
mbedtls_x509write_crt_init(&crt);
mbedtls_mpi_init(&serial);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen(pers))) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_ctr_drbg_seed fail.");
goto exit;
}
serial_num = gen_rand_num(0);
snprintf(serial_str, 20, "%llx", serial_num);
if ((ret = mbedtls_mpi_read_string(&serial, 16, serial_str)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_mpi_read_string fail.");
goto exit;
}
if(!self_sign)
{
if (NULL == issuer_cert)
{
ssl_log(SSL_ERROR, "issuer_cert should not be NULL.");
goto exit;
}
ret = mbedtls_x509_dn_gets(ca_subject_name, sizeof(ca_subject_name),
&issuer_cert->subject);
if( ret < 0 )
{
ssl_log(SSL_ERROR, "mbedtls_x509_dn_gets fail.");
goto exit;
}
set_issuer_name = ca_subject_name;
if (NULL == subject_key)
{
ssl_log(SSL_ERROR, "subject_key and issuer_key should not be NULL.");
goto exit;
}
}
if (issuer_cert)
{
if (mbedtls_pk_check_pair(&issuer_cert->pk, issuer_key) != 0)
{
ssl_log(SSL_ERROR, "issuer_key does not match issuer certificate.");
goto exit;
}
}
if (self_sign)
{
set_subject_name = set_issuer_name;
set_subject_key = set_issuer_key;
}
mbedtls_x509write_crt_set_subject_key(&crt, set_subject_key);
mbedtls_x509write_crt_set_issuer_key(&crt, set_issuer_key);
if ((ret = mbedtls_x509write_crt_set_subject_name(&crt, set_subject_name)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_subject_name "
"returned -0x%04x", -ret);
goto exit;
}
if ((ret = mbedtls_x509write_crt_set_issuer_name(&crt, set_issuer_name)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_issuer_name "
"returned -0x%04x", -ret);
goto exit;
}
mbedtls_x509write_crt_set_version(&crt, 2);
mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256);
if ((ret = mbedtls_x509write_crt_set_serial(&crt, &serial)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_serial "
"returned -0x%04x", -ret);
goto exit;
}
if ((ret = mbedtls_x509write_crt_set_validity(&crt, not_before, not_after)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_validity "
"returned -0x%04x", -ret);
goto exit;
}
if (is_ca)
{
max_pathlen = 0;
}
if ((ret = mbedtls_x509write_crt_set_basic_constraints(&crt, is_ca, max_pathlen)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_basic_constraints "
"returned -0x%04x", -ret);
goto exit;
}
if ((ret = mbedtls_x509write_crt_set_subject_key_identifier(&crt)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_subject_key_identifier "
"returned -0x%04x", -ret);
goto exit;
}
if ((ret = mbedtls_x509write_crt_set_authority_key_identifier(&crt)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_authority_key_identifier "
"returned -0x%04x", -ret);
goto exit;
}
if (!is_ca && san)
{
// set san
ssl_log(SSL_DEBUG, "san: %s", san);
ret = mbedtls_x509write_crt_set_subject_alt_name(&crt, (const unsigned char *)san, strlen(san));
//char *san_tmp = "DNS:tplinkmodem.net,DNS:192.168.1.1,IP:192.168.1.1";
//ret = mbedtls_x509write_crt_set_subject_alt_name(&crt, (const unsigned char *)san_tmp, strlen(san_tmp));
if (ret != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_set_subject_alt_name "
"returned -0x%04x", -ret);
goto exit;
}
}
if ((ret = mbedtls_x509write_crt_pem(&crt, buf, size,
mbedtls_ctr_drbg_random, &ctr_drbg)) < 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509write_crt_pem "
"returned -0x%04x", -ret);
goto exit;
}
ret = 0;
exit:
mbedtls_x509write_crt_free(&crt);
mbedtls_mpi_free(&serial);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return ret;
}
int gen_ca_cert_file(const char *cert_file, pkey_t *pkey,
const char *org, const char *orgUnit)
{
int ret = -1;
FILE *f = NULL;
unsigned char *output_buf = NULL;
char issuer_name[256] = {0};
size_t len = 0;
const char *not_before = "20010101000000";
const char *not_after = "20371231235959";
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == cert_file || NULL == pkey ||
NULL == org || NULL == orgUnit) return -1;
output_buf = (unsigned char *)malloc(4096);
if (NULL == output_buf) return -1;
snprintf(issuer_name, 256, "CN=%s,O=%s,OU=%s", "TP-Link SOHO Router CA",
org, orgUnit);
memset(output_buf, 0, 4096);
if (gen_cert(output_buf, 4096, 1, 1, NULL, pkey, NULL, NULL, issuer_name,
not_before, not_after, 0, NULL) != 0)
{
ssl_log(SSL_ERROR, "gen_cert fail.");
ret = -1;
goto exit;
}
len = strlen((char *)output_buf);
f = fopen(cert_file, "w");
if (f == NULL)
{
ssl_log(SSL_ERROR, "open %s fail.", cert_file);
ret = -1;
goto exit;
}
if (fwrite(output_buf, 1, len, f) != len)
{
ssl_log(SSL_ERROR, "fwrite fail.");
ret = -1;
goto exit;
}
ret = 0;
exit:
if (f) fclose(f);
if (output_buf) free(output_buf);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return ret;
}
int gen_ca_cert_buf(void *cert_buf, size_t len, pkey_t *pkey,
const char *org, const char *orgUnit)
{
char issuer_name[256] = {0};
const char *not_before = "20010101000000";
const char *not_after = "20371231235959";
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
snprintf(issuer_name, 256, "CN=%s,O=%s,OU=%s", "TP-Link SOHO Router CA",
org, orgUnit);
if (gen_cert(cert_buf, len, 1, 1, NULL, pkey, NULL, NULL, issuer_name,
not_before, not_after, 0, NULL) != 0)
{
ssl_log(SSL_ERROR, "gen_cert fail.");
return -1;
}
ssl_log(SSL_DEBUG, "cert buf: \n%s\n", (char *)cert_buf);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int gen_server_cert_file(const char *cert_file, pkey_t *pkey,
x509_cert_t *issuer_cert, pkey_t *issuer_key,
const char *cn, char *san)
{
FILE *f;
unsigned char output_buf[4096];
char subject_name[256] = {0};
size_t len = 0;
char not_before[20] = {0};
char not_after[20] = {0};
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
snprintf(subject_name, 256, "CN=%s", cn);
snprintf(not_before, 20, "%04d%02d%02d%02d%02d%02d",
issuer_cert->valid_from.year, issuer_cert->valid_from.mon,
issuer_cert->valid_from.day, issuer_cert->valid_from.hour,
issuer_cert->valid_from.min, issuer_cert->valid_from.sec );
snprintf(not_after, 20, "%04d%02d%02d%02d%02d%02d",
issuer_cert->valid_to.year, issuer_cert->valid_to.mon,
issuer_cert->valid_to.day, issuer_cert->valid_to.hour,
issuer_cert->valid_to.min, issuer_cert->valid_to.sec );
memset(output_buf, 0, 4096);
if (gen_cert(output_buf, 4096, 0, 0, issuer_cert, issuer_key, pkey,
subject_name, NULL, not_before, not_after, 1, san) != 0)
{
ssl_log(SSL_ERROR, "gen_cert fail.");
return -1;
}
len = strlen((char *)output_buf);
if ((f = fopen(cert_file, "w")) == NULL)
{
ssl_log(SSL_ERROR, "open %s fail.", cert_file);
return -1;
}
if (fwrite(output_buf, 1, len, f) != len)
{
ssl_log(SSL_ERROR, "fwrite fail.");
fclose(f);
return -1;
}
fclose(f);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
void free_cert(x509_cert_t *cert)
{
if (cert)
{
mbedtls_x509_crt_free(cert);
free(cert);
cert = NULL;
}
}
int load_cert_from_file(const char *cert_file, x509_cert_t **cert)
{
int ret = 0;
x509_cert_t *tmp = NULL;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == cert_file || NULL == cert) return -1;
if (access(cert_file, 0) != 0)
{
ssl_log(SSL_ERROR, "File %s is not exist.", cert_file);
return -1;
}
tmp = (x509_cert_t *)malloc(sizeof(x509_cert_t));
if (NULL == tmp) return -1;
mbedtls_x509_crt_init(tmp);
if ((ret = mbedtls_x509_crt_parse_file(tmp, cert_file)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509_crt_parse_file fail. ret=%d", ret);
free(tmp);
return -1;
}
*cert = tmp;
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int load_pkey_from_file(const char *key_file, pkey_t **pkey)
{
int ret = 0;
pkey_t *tmp = NULL;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == key_file || NULL == pkey) return -1;
if (access(key_file, 0) != 0)
{
ssl_log(SSL_ERROR, "File %s is not exist.", key_file);
return -1;
}
tmp = (pkey_t *)malloc(sizeof(pkey_t));
if (NULL == tmp) return -1;
mbedtls_pk_init(tmp);
if ((ret = mbedtls_pk_parse_keyfile(tmp, key_file, NULL)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_pk_parse_keyfile fail. ret=%d", ret);
free(tmp);
return -1;
}
*pkey = tmp;
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int load_cert_from_buf(const void *cert_buf, size_t len, x509_cert_t **cert)
{
int ret = 0;
x509_cert_t *tmp = NULL;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == cert_buf || NULL == cert) return -1;
tmp = (x509_cert_t *)malloc(sizeof(x509_cert_t));
if (NULL == tmp) return -1;
ssl_log(SSL_DEBUG, "cert buf: \n%s\n", (char *)cert_buf);
mbedtls_x509_crt_init(tmp);
ssl_log(SSL_DEBUG, "buf len: %d %d", len, strlen(cert_buf));
if ((ret = mbedtls_x509_crt_parse(tmp, cert_buf, len)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_x509_crt_parse fail. ret=%d", ret);
free(tmp);
return -1;
}
*cert = tmp;
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int load_pkey_from_buf(const void *key_buf, size_t len, pkey_t **pkey)
{
int ret = 0;
pkey_t *tmp = NULL;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == key_buf || NULL == pkey) return -1;
tmp = (pkey_t *)malloc(sizeof(pkey_t));
if (NULL == tmp) return -1;
ssl_log(SSL_DEBUG, "key buf: \n%s\n", (char *)key_buf);
mbedtls_pk_init(tmp);
ssl_log(SSL_DEBUG, "buf len: %d %d", len, strlen(key_buf));
if (mbedtls_pk_parse_key(tmp, key_buf, len, NULL, 0) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_pk_parse_key fail. ret=%d", ret);
free(tmp);
return -1;
}
*pkey = tmp;
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
int write_cert_to_buf(x509_cert_t *cert, void *cert_buf, size_t len)
{
return -1;
}
int write_pkey_to_buf(pkey_t *pkey, void *key_buf, size_t len)
{
int ret = 0;
ssl_log(SSL_DEBUG, "enter %s", __FUNCTION__);
if (NULL == pkey || NULL == key_buf) return -1;
if ((ret = mbedtls_pk_write_key_pem(pkey, key_buf, len)) != 0)
{
ssl_log(SSL_ERROR, "mbedtls_pk_write_key_pem failed. ret=%d", ret);
return -1;
}
ssl_log(SSL_DEBUG, "key buf: \n%s\n", (char *)key_buf);
ssl_log(SSL_DEBUG, "leave %s", __FUNCTION__);
return 0;
}
#endif /* INCLUDE_SSL && INCLUDE_SSL_MBEDTLS */
我可以利用这个来将代码改为 mbedtls 版本吗