diff --git a/CMakeLists.txt b/CMakeLists.txt index 9805a2e1..175c60c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,7 +652,8 @@ endif() if (LWS_WITH_SSL) list(APPEND SOURCES - lib/ssl.c) + lib/ssl.c + lib/lws-genhash.c) if (NOT LWS_WITHOUT_SERVER) list(APPEND SOURCES @@ -1031,6 +1032,8 @@ if (LWS_WITH_SSL) if (LWS_SSL_SERVER_WITH_ECDH_CERT AND NOT LWS_HAVE_OPENSSL_ECDH_H) message(FATAL_ERROR "Missing openssl/ecdh.h, so cannot use LWS_SSL_SERVER_WITH_ECDH_CERT") endif() + else() + unset(LWS_HAVE_OPENSSL_ECDH_H) endif(NOT LWS_USE_MBEDTLS) endif() diff --git a/component.mk b/component.mk index 2caa7c19..7f472418 100644 --- a/component.mk +++ b/component.mk @@ -1,3 +1,4 @@ +COMPONENT_DEPENDS:=mbedtls openssl COMPONENT_ADD_INCLUDEDIRS := ../../../../../../../../../../../../../../../../../../$(COMPONENT_BUILD_DIR)/include COMPONENT_OWNBUILDTARGET:= 1 @@ -18,13 +19,13 @@ CROSS_PATH:= $(shell dirname $(CROSS_PATH1) )/.. build: cd $(COMPONENT_BUILD_DIR) ; \ echo "doing lws cmake" ; \ - cmake $(COMPONENT_PATH) -DLWS_C_FLAGS="$(CFLAGS) -DNDEBUG=1" \ + cmake $(COMPONENT_PATH) -DLWS_C_FLAGS="$(CFLAGS) -DNDEBUG=1 " \ -DIDF_PATH=$(IDF_PATH) \ -DCROSS_PATH=$(CROSS_PATH) \ -DBUILD_DIR_BASE=$(BUILD_DIR_BASE) \ -DCMAKE_TOOLCHAIN_FILE=$(COMPONENT_PATH)/cross-esp32.cmake \ -DCMAKE_BUILD_TYPE=RELEASE \ - -DLWS_MBEDTLS_INCLUDE_DIRS=${IDF_PATH}/components/openssl/include \ + -DLWS_MBEDTLS_INCLUDE_DIRS="${IDF_PATH}/components/openssl/include;${IDF_PATH}/components/mbedtls/include;${IDF_PATH}/components/mbedtls/port/include" \ -DLWS_WITH_STATS=0 \ -DZLIB_LIBRARY=$(BUILD_DIR_BASE)/zlib/libzlib.a \ -DZLIB_INCLUDE_DIR=$(COMPONENT_PATH)/../zlib \ diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 857a8b7e..bb1d8a5f 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -203,6 +203,14 @@ typedef unsigned long long lws_intptr_t; #include #endif /* not USE_OLD_CYASSL */ #else +#if defined(LWS_USE_MBEDTLS) +#if defined(LWS_WITH_ESP32) +/* this filepath is passed to us but without quotes or <> */ +#undef MBEDTLS_CONFIG_FILE +#define MBEDTLS_CONFIG_FILE +#endif +#include +#endif #include #if !defined(LWS_USE_MBEDTLS) #include @@ -1398,6 +1406,91 @@ lws_callback_function(struct lws *wsi, enum lws_callback_reasons reason, #define LWS_CB_REASON_AUX_BF__CGI_HEADERS 8 ///@} +/*! \defgroup generic hash + * ## Generic Hash related functions + * + * Lws provides generic hash / digest accessors that abstract the ones + * provided by whatever OpenSSL library you are linking against. + * + * It lets you use the same code if you build against mbedtls or OpenSSL + * for example. + */ +///@{ + +#ifdef LWS_OPENSSL_SUPPORT + +#if defined(LWS_USE_MBEDTLS) +#include +#include +#include +#endif + +#define LWS_GENHASH_TYPE_SHA1 0 +#define LWS_GENHASH_TYPE_SHA256 1 +#define LWS_GENHASH_TYPE_SHA512 2 + +struct lws_genhash_ctx { + uint8_t type; +#if defined(LWS_USE_MBEDTLS) + union { + mbedtls_sha1_context sha1; + mbedtls_sha256_context sha256; + mbedtls_sha512_context sha512; + } u; +#else + const EVP_MD *evp_type; + EVP_MD_CTX *mdctx; +#endif +}; + +/** lws_genhash_size() - get hash size in bytes + * + * \param type: one of LWS_GENHASH_TYPE_... + * + * Returns number of bytes in this type of hash + */ +LWS_VISIBLE LWS_EXTERN size_t LWS_WARN_UNUSED_RESULT +lws_genhash_size(int type); + +/** lws_genhash_init() - prepare your struct lws_genhash_ctx for use + * + * \param ctx: your struct lws_genhash_ctx + * \param type: one of LWS_GENHASH_TYPE_... + * + * Initializes the hash context for the type you requested + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_genhash_init(struct lws_genhash_ctx *ctx, int type); + +/** lws_genhash_update() - digest len bytes of the buffer starting at in + * + * \param ctx: your struct lws_genhash_ctx + * \param in: start of the bytes to digest + * \param len: count of bytes to digest + * + * Updates the state of your hash context to reflect digesting len bytes from in + */ +LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT +lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len); + +/** lws_genhash_destroy() - copy out the result digest and destroy the ctx + * + * \param ctx: your struct lws_genhash_ctx + * \param result: NULL, or where to copy the result hash + * + * Finalizes the hash and copies out the digest. Destroys any allocations such + * that ctx can safely go out of scope after calling this. + * + * NULL result is supported so that you can destroy the ctx cleanly on error + * conditions, where there is no valid result. + */ +LWS_VISIBLE LWS_EXTERN int +lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result); + +#endif + +///@} + /*! \defgroup extensions * * ##Extension releated functions diff --git a/lib/lws-genhash.c b/lib/lws-genhash.c new file mode 100644 index 00000000..2c26c1f1 --- /dev/null +++ b/lib/lws-genhash.c @@ -0,0 +1,149 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2017 Andy Green + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation: + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + * + * lws_genhash provides a hash abstraction api in lws that works the same + * whether you are using openssl or mbedtls hash functions underneath. + */ +#include "libwebsockets.h" + +size_t +lws_genhash_size(int type) +{ + switch(type) { + case LWS_GENHASH_TYPE_SHA1: + return 20; + case LWS_GENHASH_TYPE_SHA256: + return 32; + case LWS_GENHASH_TYPE_SHA512: + return 64; + } + + return 0; +} + +int +lws_genhash_init(struct lws_genhash_ctx *ctx, int type) +{ + ctx->type = type; + +#if defined(LWS_USE_MBEDTLS) + switch (ctx->type) { + case LWS_GENHASH_TYPE_SHA1: + mbedtls_sha1_init(&ctx->u.sha1); + mbedtls_sha1_starts(&ctx->u.sha1); + break; + case LWS_GENHASH_TYPE_SHA256: + mbedtls_sha256_init(&ctx->u.sha256); + mbedtls_sha256_starts(&ctx->u.sha256, 0); + break; + case LWS_GENHASH_TYPE_SHA512: + mbedtls_sha512_init(&ctx->u.sha512); + mbedtls_sha512_starts(&ctx->u.sha512, 0); + break; + default: + return 1; + } +#else + ctx->mdctx = EVP_MD_CTX_create(); + if (!ctx->mdctx) + return 1; + + switch (ctx->type) { + case LWS_GENHASH_TYPE_SHA1: + ctx->evp_type = EVP_sha1(); + break; + case LWS_GENHASH_TYPE_SHA256: + ctx->evp_type = EVP_sha256(); + break; + case LWS_GENHASH_TYPE_SHA512: + ctx->evp_type = EVP_sha512(); + break; + default: + return 1; + } + + if (EVP_DigestInit_ex(ctx->mdctx, ctx->evp_type, NULL) != 1) { + EVP_MD_CTX_destroy(ctx->mdctx); + + return 1; + } + +#endif + return 0; +} + +int +lws_genhash_update(struct lws_genhash_ctx *ctx, const void *in, size_t len) +{ +#if defined(LWS_USE_MBEDTLS) + switch (ctx->type) { + case LWS_GENHASH_TYPE_SHA1: + mbedtls_sha1_update(&ctx->u.sha1, in, len); + break; + case LWS_GENHASH_TYPE_SHA256: + mbedtls_sha256_update(&ctx->u.sha256, in, len); + break; + case LWS_GENHASH_TYPE_SHA512: + mbedtls_sha512_update(&ctx->u.sha512, in, len); + break; + } +#else + return EVP_DigestUpdate(ctx->mdctx, in, len) != 1; +#endif + + return 0; +} + +int +lws_genhash_destroy(struct lws_genhash_ctx *ctx, void *result) +{ +#if defined(LWS_USE_MBEDTLS) + switch (ctx->type) { + case LWS_GENHASH_TYPE_SHA1: + mbedtls_sha1_finish(&ctx->u.sha1, result); + mbedtls_sha1_free(&ctx->u.sha1); + break; + case LWS_GENHASH_TYPE_SHA256: + mbedtls_sha256_finish(&ctx->u.sha256, result); + mbedtls_sha256_free(&ctx->u.sha256); + break; + case LWS_GENHASH_TYPE_SHA512: + mbedtls_sha512_finish(&ctx->u.sha512, result); + mbedtls_sha512_free(&ctx->u.sha512); + break; + } + + return 0; +#else + unsigned int len; + int ret = 0; + + if (result) + ret = EVP_DigestFinal_ex(ctx->mdctx, result, &len) != 1; + + (void)len; + + EVP_MD_CTX_destroy(ctx->mdctx); + + return ret; +#endif +} + + diff --git a/lib/ssl-server.c b/lib/ssl-server.c index 0e2d60c6..c06818cc 100644 --- a/lib/ssl-server.c +++ b/lib/ssl-server.c @@ -104,7 +104,7 @@ static int lws_context_ssl_init_ecdh_curve(struct lws_context_creation_info *info, struct lws_vhost *vhost) { -#ifdef LWS_HAVE_OPENSSL_ECDH_H +#if defined(LWS_HAVE_OPENSSL_ECDH_H) && !defined(LWS_USE_MBEDTLS) EC_KEY *ecdh; int ecdh_nid; const char *ecdh_curve = "prime256v1";