瀏覽代碼

WITH_MBEDTLS

ithewei 5 年之前
父節點
當前提交
4ffe7dd4ce
共有 7 個文件被更改,包括 201 次插入10 次删除
  1. 7 0
      CMakeLists.txt
  2. 5 0
      Makefile.in
  3. 2 3
      README.md
  4. 181 2
      base/hssl.c
  5. 4 3
      base/hssl.h
  6. 1 0
      config.mk
  7. 1 2
      readme_cn.md

+ 7 - 0
CMakeLists.txt

@@ -22,7 +22,9 @@ option(USE_MULTIMAP "MultiMap" OFF)
 
 
 option(WITH_CURL "with curl library" OFF)
 option(WITH_CURL "with curl library" OFF)
 option(WITH_NGHTTP2 "with nghttp2 library" OFF)
 option(WITH_NGHTTP2 "with nghttp2 library" OFF)
+
 option(WITH_OPENSSL "with openssl library" OFF)
 option(WITH_OPENSSL "with openssl library" OFF)
+option(WITH_MBEDTLS "with mbedtls library" OFF)
 
 
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 include(utils)
 include(utils)
@@ -102,6 +104,11 @@ if(WITH_OPENSSL)
     set(LIBS ${LIBS} ssl crypto)
     set(LIBS ${LIBS} ssl crypto)
 endif()
 endif()
 
 
+if(WITH_MBEDTLS)
+    add_definitions(-DWITH_MBEDTLS)
+    set(LIBS ${LIBS} mbedtls mbedx509 mbedcrypto)
+endif()
+
 if(WIN32)
 if(WIN32)
     add_definitions(-D_WIN32_WINNT=0x0600)
     add_definitions(-D_WIN32_WINNT=0x0600)
     set(LIBS ${LIBS} winmm iphlpapi ws2_32)
     set(LIBS ${LIBS} winmm iphlpapi ws2_32)

+ 5 - 0
Makefile.in

@@ -164,6 +164,11 @@ endif
 ifeq ($(WITH_OPENSSL), yes)
 ifeq ($(WITH_OPENSSL), yes)
 	CPPFLAGS += -DWITH_OPENSSL
 	CPPFLAGS += -DWITH_OPENSSL
 	LDFLAGS += -lssl -lcrypto
 	LDFLAGS += -lssl -lcrypto
+else
+ifeq ($(WITH_MBEDTLS), yes)
+	CPPFLAGS += -DWITH_MBEDTLS
+	LDFLAGS += -lmbedtls -lmbedx509 -lmbedcrypto
+endif
 endif
 endif
 
 
 LDFLAGS += $(addprefix -L, $(LIBDIRS))
 LDFLAGS += $(addprefix -L, $(LIBDIRS))

+ 2 - 3
README.md

@@ -12,7 +12,7 @@ but simpler apis and richer protocols.
 - event-loop (IO, timer, idle)
 - event-loop (IO, timer, idle)
 - ENABLE_IPV6
 - ENABLE_IPV6
 - ENABLE_UDS (Unix Domain Socket)
 - ENABLE_UDS (Unix Domain Socket)
-- WITH_OPENSSL
+- WITH_OPENSSL or WITH_MBEDTLS
 - http client/server (include https http1/x http2 grpc)
 - http client/server (include https http1/x http2 grpc)
 - http web service, indexof service, api service (support RESTful API)
 - http web service, indexof service, api service (support RESTful API)
 - protocols
 - protocols
@@ -188,8 +188,7 @@ bin/nc 127.0.0.1 10514
 ### compile options
 ### compile options
 
 
 #### compile WITH_OPENSSL
 #### compile WITH_OPENSSL
-libhv combines OpenSSL perfectly, something almost all asynchronous IO network libraries don't do.<br>
-And enable SSL in libhv is so easy, just only two apis:
+Enable SSL in libhv is so easy, just only two apis:
 ```
 ```
 // init ssl_ctx, see base/hssl.h
 // init ssl_ctx, see base/hssl.h
 hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param);
 hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param);

+ 181 - 2
base/hssl.c

@@ -1,5 +1,7 @@
 #include "hssl.h"
 #include "hssl.h"
 
 
+#include "hplatform.h"
+
 static hssl_ctx_t s_ssl_ctx = 0;
 static hssl_ctx_t s_ssl_ctx = 0;
 
 
 hssl_ctx_t hssl_ctx_instance() {
 hssl_ctx_t hssl_ctx_instance() {
@@ -135,9 +137,186 @@ int hssl_close(hssl_t ssl) {
     return 0;
     return 0;
 }
 }
 
 
-#else
+#elif defined(WITH_MBEDTLS)
 
 
-#include "hplatform.h"
+
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/certs.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/net.h"
+#include "mbedtls/error.h"
+#include "mbedtls/debug.h"
+
+#if defined(MBEDTLS_SSL_CACHE_C)
+#include "mbedtls/ssl_cache.h"
+#endif
+
+#ifdef _MSC_VER
+//#pragma comment(lib, "libmbedtls.a")
+//#pragma comment(lib, "libmbedx509.a")
+//#pragma comment(lib, "libmbedcrypto.a")
+#endif
+
+struct mbedtls_ctx {
+    mbedtls_entropy_context     entropy;
+    mbedtls_ctr_drbg_context    ctr_drbg;
+    mbedtls_ssl_config          conf;
+    mbedtls_x509_crt            cert;
+    mbedtls_pk_context          pkey;
+#if defined(MBEDTLS_SSL_CACHE_C)
+    mbedtls_ssl_cache_context   cache;
+#endif
+};
+
+hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param) {
+    struct mbedtls_ctx* ctx = (struct mbedtls_ctx*)malloc(sizeof(struct mbedtls_ctx));
+    if (ctx == NULL) return NULL;
+
+    mbedtls_ssl_config_init(&ctx->conf);
+#if defined(MBEDTLS_SSL_CACHE_C)
+    mbedtls_ssl_cache_init(&ctx->cache);
+#endif
+    mbedtls_x509_crt_init(&ctx->cert);
+    mbedtls_pk_init(&ctx->pkey);
+    mbedtls_entropy_init(&ctx->entropy);
+    mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
+
+    int mode = MBEDTLS_SSL_VERIFY_NONE;
+    int endpoint = MBEDTLS_SSL_IS_CLIENT;
+    bool check = false;
+    if (param) {
+        if (param->crt_file && *param->crt_file) {
+            if (mbedtls_x509_crt_parse_file(&ctx->cert, param->crt_file) != 0) {
+                fprintf(stderr, "ssl crt_file error!\n");
+                goto error;
+            }
+        }
+        if (param->key_file && *param->key_file) {
+            if (mbedtls_pk_parse_keyfile(&ctx->pkey, param->key_file, NULL) != 0) {
+                fprintf(stderr, "ssl key_file error!\n");
+                goto error;
+            }
+            check = true;
+        }
+        if (param->verify_peer) {
+            mode = MBEDTLS_SSL_VERIFY_REQUIRED;
+        }
+        if (param->endpoint == 0) {
+            endpoint = MBEDTLS_SSL_IS_SERVER;
+        }
+    }
+    mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, NULL, 0);
+    if (mbedtls_ssl_config_defaults(&ctx->conf, endpoint,
+        MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
+        fprintf(stderr, "ssl config error!\n");
+        goto error;
+    }
+    mbedtls_ssl_conf_authmode(&ctx->conf, mode);
+    mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg);
+
+#if defined(MBEDTLS_SSL_CACHE_C)
+    mbedtls_ssl_conf_session_cache(&ctx->conf, &ctx->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
+#endif
+
+    if (check) {
+        mbedtls_ssl_conf_ca_chain(&ctx->conf, ctx->cert.next, NULL);
+        if (mbedtls_ssl_conf_own_cert(&ctx->conf, &ctx->cert, &ctx->pkey) != 0) {
+            fprintf(stderr, "ssl key_file check failed!\n");
+            goto error;
+        }
+    }
+
+    s_ssl_ctx = ctx;
+    return ctx;
+error:
+    free(ctx);
+    return NULL;
+}
+
+void hssl_ctx_cleanup(hssl_ctx_t ssl_ctx) {
+    if (!ssl_ctx) return;
+    if (ssl_ctx == s_ssl_ctx) {
+        s_ssl_ctx = NULL;
+    }
+    struct mbedtls_ctx *mctx = (struct mbedtls_ctx *)ssl_ctx;
+    mbedtls_x509_crt_free(&mctx->cert);
+    mbedtls_pk_free(&mctx->pkey);
+    mbedtls_ssl_config_free(&mctx->conf);
+#if defined(MBEDTLS_SSL_CACHE_C)
+    mbedtls_ssl_cache_free(&mctx->cache);
+#endif
+    mbedtls_ctr_drbg_free(&mctx->ctr_drbg);
+    mbedtls_entropy_free(&mctx->entropy);
+    free(mctx);
+}
+
+static int __mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len) {
+    int fd = (intptr_t)ctx;
+    int n = write(fd, buf, len);
+    if (n >= 0) return n;
+    return ((errno == EAGAIN || errno == EINPROGRESS) ? MBEDTLS_ERR_SSL_WANT_WRITE : -1);
+}
+
+static int __mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) {
+    int fd = (intptr_t)ctx;
+    int n = read(fd, buf, len);
+    if (n >= 0) return n;
+    return ((errno == EAGAIN || errno == EINPROGRESS) ? MBEDTLS_ERR_SSL_WANT_READ : -1);
+}
+
+hssl_t hssl_new(hssl_ctx_t ssl_ctx, int fd) {
+    struct mbedtls_ctx* mctx = (struct mbedtls_ctx*)ssl_ctx;
+    mbedtls_ssl_context* ssl = (mbedtls_ssl_context*)malloc(sizeof(mbedtls_ssl_context));
+    if (ssl == NULL) return NULL;
+    mbedtls_ssl_init(ssl);
+    mbedtls_ssl_setup(ssl, &mctx->conf);
+    mbedtls_ssl_set_bio(ssl, (void*)(intptr_t)fd, __mbedtls_net_send, __mbedtls_net_recv, NULL);
+    return ssl;
+}
+
+void hssl_free(hssl_t ssl) {
+    if (ssl) {
+        mbedtls_ssl_free(ssl);
+        ssl = NULL;
+    }
+}
+
+static int hssl_handshake(hssl_t ssl) {
+    int ret = mbedtls_ssl_handshake(ssl);
+    if (ret != 0) {
+        if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
+            return HSSL_WANT_READ;
+        }
+        else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
+            return HSSL_WANT_WRITE;
+        }
+    }
+    return ret;
+}
+
+int hssl_accept(hssl_t ssl) {
+    return hssl_handshake(ssl);
+}
+
+int hssl_connect(hssl_t ssl) {
+    return hssl_handshake(ssl);
+}
+
+int hssl_read(hssl_t ssl, void* buf, int len) {
+    return mbedtls_ssl_read(ssl, buf, len);
+}
+
+int hssl_write(hssl_t ssl, const void* buf, int len) {
+    return mbedtls_ssl_write(ssl, buf, len);
+}
+
+int hssl_close(hssl_t ssl) {
+    return 0;
+}
+
+#else
 
 
 hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param) {
 hssl_ctx_t hssl_ctx_init(hssl_ctx_init_param_t* param) {
     fprintf(stderr, "Please recompile WITH_SSL.\n");
     fprintf(stderr, "Please recompile WITH_SSL.\n");

+ 4 - 3
base/hssl.h

@@ -8,15 +8,16 @@ typedef void* hssl_t; ///> SSL
 
 
 enum {
 enum {
     HSSL_OK = 0,
     HSSL_OK = 0,
-    HSSL_WANT_READ = 2,
-    HSSL_WANT_WRITE = 3,
+    HSSL_WANT_READ = -2,
+    HSSL_WANT_WRITE = -3,
 };
 };
 
 
 typedef struct {
 typedef struct {
     const char* crt_file;
     const char* crt_file;
     const char* key_file;
     const char* key_file;
     const char* ca_file;
     const char* ca_file;
-    int         verify_peer;
+    short       verify_peer;
+    short       endpoint; // 0: server 1: client
 } hssl_ctx_init_param_t;
 } hssl_ctx_init_param_t;
 
 
 BEGIN_EXTERN_C
 BEGIN_EXTERN_C

+ 1 - 0
config.mk

@@ -26,3 +26,4 @@ WITH_CURL=no
 WITH_NGHTTP2=no
 WITH_NGHTTP2=no
 # for SSL/TLS
 # for SSL/TLS
 WITH_OPENSSL=no
 WITH_OPENSSL=no
+WITH_MBEDTLS=no

+ 1 - 2
readme_cn.md

@@ -10,7 +10,7 @@
 - event-loop (IO, timer, idle)
 - event-loop (IO, timer, idle)
 - ENABLE_IPV6
 - ENABLE_IPV6
 - ENABLE_UDS (Unix Domain Socket)
 - ENABLE_UDS (Unix Domain Socket)
-- WITH_OPENSSL
+- WITH_OPENSSL or WITH_MBEDTLS
 - http client/server (include https http1/x http2 grpc)
 - http client/server (include https http1/x http2 grpc)
 - http web service, indexof service, api service (support RESTful API)
 - http web service, indexof service, api service (support RESTful API)
 - protocols
 - protocols
@@ -186,7 +186,6 @@ bin/nc 127.0.0.1 10514
 ### 编译选项
 ### 编译选项
 
 
 #### 编译WITH_OPENSSL
 #### 编译WITH_OPENSSL
-libhv完美结合了OpenSSL库,这是几乎所有的异步IO库没有做的一点。
 在libhv中开启SSL非常简单,仅需要两个API接口:
 在libhv中开启SSL非常简单,仅需要两个API接口:
 ```
 ```
 // init ssl_ctx, see base/hssl.h
 // init ssl_ctx, see base/hssl.h