SSL

JAVA 双向SSL,SOCKET客户端/服务端
[size=x-small][/size][size=small][/size]
实现技术:
JSSE(Java Security Socket Extension)
Server需要:
1)KeyStore: 其中保存服务端的私钥
2)Trust KeyStore:其中保存客户端的授权证书
Client需要:
1)KeyStore:其中保存客户端的私钥
2)Trust KeyStore:其中保存服务端的授权证书


使用Java自带的keytool命令,去生成这样信息文件:

1)生成服务端私钥,并且导入到服务端KeyStore文件中

2)根据私钥,导出服务端证书

3)将服务端证书,导入到客户端的Trust KeyStore中

采用同样的方法,生成客户端的私钥,客户端的证书,并且导入到服务端的Trust KeyStore中
1)keytool -genkey -alias clientkey -keystore kclient.keystore
2)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt
3)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore


Server:
Java代码
public class Server implements Runnable{

private static final int DEFAULT_PORT = 7777;

private static final String SERVER_KEY_STORE_PASSWORD = "123456";
private static final String SERVER_TRUST_KEY_STORE_PASSWORD = "123456";

private SSLServerSocket serverSocket;

/**
* 启动程序
*
* @param args
*/
public static void main(String[] args) {
Server server = new Server();
server.init();
Thread thread = new Thread(server);
thread.start();
}

public synchronized void start() {
if (serverSocket == null) {
System.out.println("ERROR");
return;
}
while (true) {
try {
Socket s = serverSocket.accept();
InputStream input = s.getInputStream();
OutputStream output = s.getOutputStream();

BufferedInputStream bis = new BufferedInputStream(input);
BufferedOutputStream bos = new BufferedOutputStream(output);

byte[] buffer = new byte[20];
bis.read(buffer);
System.out.println("------receive:--------"+new String(buffer).toString());

bos.write("yes".getBytes());
bos.flush();

s.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
public void init() {
try {
SSLContext ctx = SSLContext.getInstance("SSL");

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

KeyStore ks = KeyStore.getInstance("JKS");
KeyStore tks = KeyStore.getInstance("JKS");

ks.load(new FileInputStream("src/ssl/kserver.keystore"), SERVER_KEY_STORE_PASSWORD.toCharArray());
tks.load(new FileInputStream("src/ssl/tserver.keystore"), SERVER_TRUST_KEY_STORE_PASSWORD.toCharArray());

kmf.init(ks, SERVER_KEY_STORE_PASSWORD.toCharArray());
tmf.init(tks);

ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

serverSocket = (SSLServerSocket) ctx.getServerSocketFactory().createServerSocket(DEFAULT_PORT);
serverSocket.setNeedClientAuth(true);
} catch (Exception e) {
System.out.println(e);
}
}

public void run() {
// TODO Auto-generated method stub
start();
}
}


Client:
Java代码
package ssl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;

/**
* SSL Client
*
* @author Leo
*/
public class Client {

private static final String DEFAULT_HOST = "127.0.0.1";
private static final int DEFAULT_PORT = 7777;

private static final String CLIENT_KEY_STORE_PASSWORD = "123456";
private static final String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";

private SSLSocket sslSocket;

/**
* 启动客户端程序
*
* @param args
*/
public static void main(String[] args) {
Client client = new Client();
client.init();
client.process();
}


public void process() {
if (sslSocket == null) {
System.out.println("ERROR");
return;
}
try {
InputStream input = sslSocket.getInputStream();
OutputStream output = sslSocket.getOutputStream();

BufferedInputStream bis = new BufferedInputStream(input);
BufferedOutputStream bos = new BufferedOutputStream(output);

bos.write("1234567890".getBytes());
bos.flush();

byte[] buffer = new byte[20];
bis.read(buffer);
System.out.println(new String(buffer));

sslSocket.close();
} catch (IOException e) {
System.out.println(e);
}
}


public void init() {
try {
SSLContext ctx = SSLContext.getInstance("SSL");

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

KeyStore ks = KeyStore.getInstance("JKS");
KeyStore tks = KeyStore.getInstance("JKS");

ks.load(new FileInputStream("src/ssl/kclient.keystore"), CLIENT_KEY_STORE_PASSWORD.toCharArray());
tks.load(new FileInputStream("src/ssl/tclient.keystore"), CLIENT_TRUST_KEY_STORE_PASSWORD.toCharArray());

kmf.init(ks, CLIENT_KEY_STORE_PASSWORD.toCharArray());
tmf.init(tks);

ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(DEFAULT_HOST, DEFAULT_PORT);
} catch (Exception e) {
System.out.println(e);
}
}

}


启动Server


启动Client,发送信息。

Server接收如下:正确解密
返回Client信息,

如此,就完成了服务端和客户端之间的基于身份认证的交互。

client采用kclient.keystore中的clientkey私钥进行数据加密,发送给server。
server采用tserver.keystore中的client.crt证书(包含了clientkey的公钥)对数据解密,如果解密成功,证明消息来自client,进行逻辑处理。

server采用kserver.keystore中的serverkey私钥进行数据加密,发送给client。
client采用tclient.keystore中的server.crt证书(包含了serverkey的公钥)对数据解密,如果解密成功,证明消息来自server,进行逻辑处理。

如果过程中,解密失败,那么证明消息来源错误。不进行逻辑处理。这样就完成了双向的身份认证。
/* 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值