【SSL1743】Debug

算法竞赛策略解析

Description

经过了一整夜的激战,rc的部队终于攻下了虫族的首都Bugzilla。现在,rc决定亲自带领一队突击队员在虫族庞大的地道中寻找他的宿命之敌—Bug。
  Bugzilla由N个基地组成。这N个基地被N-1段双向地道连接在一起,每段地道都连接两个基地,并且保证任意两个基地之间都可以通过地道互相到达。Bug就藏在其中的某段地道中。
  开始时rc可以乘坐运输机降落在任何一个基地。每次到达一个基地时,rc都可以选择呼叫运输机将他和他的部队运输到任意另一个基地,或者进入与这个基地相邻的一段地道进行搜索。但为了防止Bug跑进已经搜索过的地道,他在离开一个基地进入地道或登上运输机时一定会将这个基地炸毁。基地一旦被炸毁就不再和与它相邻的地道连接。但这样一来,如果进入的地道另一端的基地已经在之前被炸毁,rc和他的部下就将被永远困在地道中。因为地道生活并不有趣,所以在这种情况下rc是不会进入这段地道的。
  不过,这也带来了一个问题,就是rc也许不能搜索所有的地道了。现在rc想知道的是他最多能搜索多少段地道。作为有幸被留在运输机上看风景而不必冒着成为虫食的危险钻入地下的人,你必须完成这个任务!

Input

第一行一个整数N(2<=N<=100000),表示基地的个数。基地被编号为1~N的整数。
以下N-1行,每行两个整数A和B,表示编号为A的基地和编号为B的基地间有一段地道。

Output

一个整数,表示RC最多能搜索的地道的数目

Sample Input

6
1 2
3 2
2 4
4 5
4 6

Sample Output

4

题目大意:让你删除最少边,使得所有点的度小于等于2
思路:
首先,我们用数组记录一下每个点的度。
在一番激烈的讨论之后,我们得出:
在度数大于二时,优先删除和父节点连边在度数大于二时,优先删除和父节点连边
证明:
因为当这个点有大于1个叶子节点时,往下绝对会比往上更优,因为如果和父亲节点连边,必须要放弃它的所有儿子节点,而在儿子节点大于1个时,删除与父亲的边不可能比删除儿子的边更优。
过程:
我们可以开始记录一下现在还剩多少条边,也就是要炸毁的边,等量代换于要走的边。在DFS的时候只要有点的度数大于2,就删除它的父亲节点的边,如果还是大于2,就任选几条儿子删掉。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
using namespace std;

int n, m, v[100100], head[100100], tot, du[100100];
struct node{
	int to, next;
}a[1000010];

void VL_ljb(int x, int y)
{
	a[++tot]=(node){y, head[x]};
	head[x]=tot;
}
void VL_dp(int x, int fa)
{
	v[x]=1;
	if(du[x]==1&&a[head[x]].to==fa)return;
	for(int i=head[x]; i; i=a[i].next)
	{
		int y=a[i].to;
		if(v[y]==1)continue;
		VL_dp(y, x);
	}
	if(du[x]>2)
	{
		m=m-(du[x]-2);
		du[fa]--;
	}
}
int main(){
	scanf("%d", &n);
	m=n-1;
	for(int i=1; i<n; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		du[x]++;
		du[y]++;
		VL_ljb(x, y);
		VL_ljb(y, x);
	}
	VL_dp(1, 0);
	printf("%d", m);
	return 0;
}

/* 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 != &#39;\0&#39;; p++) if (*p == &#39;/&#39; || *p == &#39;\\&#39;) 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++) == &#39;\n&#39;) { if (index > (char *)buf && *(index - 1) == &#39;\r&#39;) { 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] = &#39;\0&#39;; stream->end = stream->cur + ret; continue; } } if (index > (char *)buf) { *index = &#39;\0&#39;; //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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值