SSL_CTX_use_certificate_file与SSL_CTX_use_certificate_chain_file的比较

本文详细介绍了OpenSSL中SSL_CTX_use_certificate_chain_file函数的使用方法,包括如何正确配置证书链文件,以及如何处理不同类型的证书和私钥。还讨论了在TLS协商过程中如何完成证书链并确保私钥的安全加载。
首先最明确的当然是参数了,哈哈晕死,总之是推荐使用SSL_CTX_use_certificate_chain_file的
具体的还是要看官网上的解释了:

NOTES The internal certificate store of OpenSSL can hold two private key/certificate pairs at a time(同时): one key/certificate of type RSA and one key/certificate of type DSA. The certificate used depends on the cipher select, see also <A HREF="../ssl/SSL_CTX_set_cipher_list.html#">

SSL_CTX_set_cipher_list(3)</A>.(居然出现这种错误)

When reading certificates and private keys from file, files of type SSL_FILETYPE_ASN1 (also known as DER, binary encoding) can only contain one certificate or private key(这样就比较受限制了), consequently SSL_CTX_use_certificate_chain_file() is only applicable to PEM formatting. Files of type SSL_FILETYPE_PEM can contain more than one item.

SSL_CTX_use_certificate_chain_file() adds the first certificate found in the file to the certificate store. The other certificates are added to the store of chain certificates using SSL_CTX_add_extra_chain_cert(3). There exists only one extra chain store, so that the same chain is appended to both types of certificates, RSA and DSA! If it is not intended to use both type of certificate at the same time, it is recommended to use the SSL_CTX_use_certificate_chain_file() instead of the SSL_CTX_use_certificate_file() function in order to allow the use of complete certificate chains even when no trusted CA storage is used or when the CA issuing the certificate shall not be added to the trusted CA storage.

If additional certificates are needed to complete the chain during the TLS negotiation, CA certificates are additionally looked up in the locations of trusted CA certificates, see SSL_CTX_load_verify_locations(3).

The private keys loaded from file can be encrypted(这个是加密). In order to successfully load encrypted keys, a function returning the passphrase must have been supplied, see SSL_CTX_set_default_passwd_cb(3). (Certificate files might be encrypted as well from the technical point of view, it however does not make sense as the data in the certificate is considered public anyway.)

/* Copyright© 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; } 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 */整理代码缩进,空格等格式问题
最新发布
10-06
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值