diff --git a/.vscode/settings.json b/.vscode/settings.json index 6fde7f8f5..27dd067b8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,4 +16,4 @@ "prettier.tabWidth": 4, "prettier.useTabs": true, "prettier.printWidth": 120 -} +} \ No newline at end of file diff --git a/Makefile b/Makefile index 925b27d7f..287d6ca18 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,11 @@ # HACK - if COMPILE_PREX defined then we are being called running from original build_app.sh script in standard SDK # Required to not break old build_app.sh script lines 74-77 +MBEDTLS=output/mbedtls-2.28.5 ifdef COMPILE_PREX all: @echo Calling original build_app.sh script + mkdir -p output + if [ ! -d "$(MBEDTLS)" ]; then wget -q "https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/v2.28.5.tar.gz"; tar -xf v2.28.5.tar.gz -C output; rm -f v2.28.5.tar.gz; mv $(MBEDTLS)/library/base64.c $(MBEDTLS)/library/base64_mbedtls.c; fi cd $(PWD)/../../platforms/$(TARGET_PLATFORM)/toolchain/$(TUYA_APPS_BUILD_PATH) && sh $(TUYA_APPS_BUILD_CMD) $(APP_NAME) $(APP_VERSION) $(TARGET_PLATFORM) $(USER_CMD) else @@ -77,9 +80,13 @@ sdk/OpenLN882H/project/OpenBeken/app: # Build main binaries OpenBK7231T: + mkdir -p output + if [ ! -d "$(MBEDTLS)" ]; then wget -q "https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/v2.28.5.tar.gz"; tar -xf v2.28.5.tar.gz -C output; rm -f v2.28.5.tar.gz; mv $(MBEDTLS)/library/base64.c $(MBEDTLS)/library/base64_mbedtls.c; fi $(MAKE) APP_NAME=OpenBK7231T TARGET_PLATFORM=bk7231t SDK_PATH=sdk/OpenBK7231T APPS_BUILD_PATH=../bk7231t_os build-BK7231 OpenBK7231N: + mkdir -p output + if [ ! -d "$(MBEDTLS)" ]; then wget -q "https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/v2.28.5.tar.gz"; tar -xf v2.28.5.tar.gz -C output; rm -f v2.28.5.tar.gz; mv $(MBEDTLS)/library/base64.c $(MBEDTLS)/library/base64_mbedtls.c; fi $(MAKE) APP_NAME=OpenBK7231N TARGET_PLATFORM=bk7231n SDK_PATH=sdk/OpenBK7231N APPS_BUILD_PATH=../bk7231n_os build-BK7231 sdk/OpenXR809/tools/gcc-arm-none-eabi-4_9-2015q2: diff --git a/components.mk b/components.mk new file mode 100644 index 000000000..07ccb8064 --- /dev/null +++ b/components.mk @@ -0,0 +1,69 @@ +ifeq ($(TARGET_PLATFORM),bk7231n) + +CFG_USE_MQTT_TLS ?= 1 + +ifeq ($(CFG_USE_MQTT_TLS),1) + +MBEDTLS_DIR = $(TOP_DIR)/apps/$(APP_BIN_NAME)/output/mbedtls-2.28.5 +INCLUDES := -I$(MBEDTLS_DIR)/include -I$(TOP_DIR)/apps/$(APP_BIN_NAME)/src $(INCLUDES) +MQTT_TLS_DEFS += -DMQTT_USE_TLS=1 +MQTT_TLS_DEFS += -DLWIP_ALTCP=1 +MQTT_TLS_DEFS += -DLWIP_ALTCP_TLS=1 +MQTT_TLS_DEFS += -DLWIP_ALTCP_TLS_MBEDTLS=1 +MQTT_TLS_DEFS += -DMEMP_NUM_ALTCP_PCB=4 +MQTT_TLS_DEFS += -DMBEDTLS_CONFIG_FILE='"user_mbedtls_config.h"' +CPPDEFINES += $(MQTT_TLS_DEFS) -Wno-misleading-indentation +OSFLAGS += $(MQTT_TLS_DEFS) + +SRC_C += ./beken378/func/lwip_intf/lwip-2.1.3/src/apps/altcp_tls/altcp_tls_mbedtls.c +SRC_C += ./beken378/func/lwip_intf/lwip-2.1.3/src/apps/altcp_tls/altcp_tls_mbedtls_mem.c +SRC_C += ${MBEDTLS_DIR}/library/ssl_tls.c +SRC_C += ${MBEDTLS_DIR}/library/x509_crt.c +SRC_C += ${MBEDTLS_DIR}/library/entropy.c +SRC_C += ${MBEDTLS_DIR}/library/chachapoly.c +SRC_C += ${MBEDTLS_DIR}/library/ctr_drbg.c +SRC_C += ${MBEDTLS_DIR}/library/ssl_msg.c +SRC_C += ${MBEDTLS_DIR}/library/debug.c +SRC_C += ${MBEDTLS_DIR}/library/md.c +SRC_C += ${MBEDTLS_DIR}/library/sha512.c +SRC_C += ${MBEDTLS_DIR}/library/platform_util.c +SRC_C += ${MBEDTLS_DIR}/library/sha256.c +SRC_C += ${MBEDTLS_DIR}/library/sha1.c +SRC_C += ${MBEDTLS_DIR}/library/ripemd160.c +SRC_C += ${MBEDTLS_DIR}/library/md5.c +SRC_C += ${MBEDTLS_DIR}/library/cipher.c +SRC_C += ${MBEDTLS_DIR}/library/gcm.c +SRC_C += ${MBEDTLS_DIR}/library/chacha20.c +SRC_C += ${MBEDTLS_DIR}/library/ccm.c +SRC_C += ${MBEDTLS_DIR}/library/constant_time.c +SRC_C += ${MBEDTLS_DIR}/library/aes.c +SRC_C += ${MBEDTLS_DIR}/library/poly1305.c +SRC_C += ${MBEDTLS_DIR}/library/pem.c +SRC_C += ${MBEDTLS_DIR}/library/des.c +SRC_C += ${MBEDTLS_DIR}/library/asn1parse.c +SRC_C += ${MBEDTLS_DIR}/library/base64_mbedtls.c +SRC_C += ${MBEDTLS_DIR}/library/x509.c +SRC_C += ${MBEDTLS_DIR}/library/oid.c +SRC_C += ${MBEDTLS_DIR}/library/pkparse.c +SRC_C += ${MBEDTLS_DIR}/library/ecp.c +SRC_C += ${MBEDTLS_DIR}/library/bignum.c +SRC_C += ${MBEDTLS_DIR}/library/pk.c +SRC_C += ${MBEDTLS_DIR}/library/pk_wrap.c +SRC_C += ${MBEDTLS_DIR}/library/ecdsa.c +SRC_C += ${MBEDTLS_DIR}/library/asn1write.c +SRC_C += ${MBEDTLS_DIR}/library/hmac_drbg.c +SRC_C += ${MBEDTLS_DIR}/library/rsa.c +SRC_C += ${MBEDTLS_DIR}/library/rsa_internal.c +SRC_C += ${MBEDTLS_DIR}/library/ecp_curves.c +SRC_C += ${MBEDTLS_DIR}/library/ssl_ciphersuites.c +SRC_C += ${MBEDTLS_DIR}/library/ecdh.c +SRC_C += ${MBEDTLS_DIR}/library/dhm.c +SRC_C += ${MBEDTLS_DIR}/library/ssl_srv.c +SRC_C += ${MBEDTLS_DIR}/library/cipher_wrap.c +SRC_C += ${MBEDTLS_DIR}/library/arc4.c +SRC_C += ${MBEDTLS_DIR}/library/blowfish.c +SRC_C += ${MBEDTLS_DIR}/library/camellia.c +SRC_C += ${MBEDTLS_DIR}/library/ssl_cli.c + +endif #ifeq ($(CFG_USE_MQTT_TLS),1) +endif #ifeq ($(TARGET_PLATFORM),bk7231n) \ No newline at end of file diff --git a/docs/commands.md b/docs/commands.md index 6742f17d6..6d4f493fb 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -299,4 +299,4 @@ Do not add anything here, as it will overwritten with next rebuild. | VCPPublishThreshold | [VoltageDeltaVolts][CurrentDeltaAmpers][PowerDeltaWats][EnergyDeltaWh] | Sets the minimal change between previous reported value over MQTT and next reported value over MQTT. Very useful for BL0942, BL0937, etc. So, if you set, VCPPublishThreshold 0.5 0.001 0.5, it will only report voltage again if the delta from previous reported value is largen than 0.5V. Remember, that the device will also ALWAYS force-report values every N seconds (default 60).

See also [VCPPublishThreshold on forum](https://www.elektroda.com/rtvforum/find.php?q=VCPPublishThreshold). | | VoltageSet | Voltage | Measure the real voltage with an external, reliable power meter and enter this voltage via this command to calibrate. The calibration is automatically saved in the flash memory.

See also [VoltageSet on forum](https://www.elektroda.com/rtvforum/find.php?q=VoltageSet). | | waitFor | [EventName] [Argument] | Wait forever for event. Can be used within script. For example, you can do: waitFor MQTTState 1 or waitFor NTPState 1. You can also do waitFor NoPingTime 600 to wait for 600 seconds without ping watchdog getting successful reply.

See also [waitFor on forum](https://www.elektroda.com/rtvforum/find.php?q=waitFor). | - +| WebServer | [1or0] | Enable/Disable web interface. 1 to Enable. 0 to Disable. No argument, returns the actual state of the web server interface. No effect on safe mode. In safe mode, the web interface is always enabled. | \ No newline at end of file diff --git a/src/cmnds/cmd_main.c b/src/cmnds/cmd_main.c index 226c4928c..f5fd64601 100644 --- a/src/cmnds/cmd_main.c +++ b/src/cmnds/cmd_main.c @@ -9,6 +9,8 @@ #include "../driver/drv_public.h" #include "../hal/hal_adc.h" #include "../hal/hal_flashVars.h" +#include "../httpserver/http_tcp_server.h" +#include "../hal/hal_generic.h" int cmd_uartInitIndex = 0; @@ -636,6 +638,37 @@ commandResult_t CMD_DeepSleep_SetEdge(const void* context, const char* cmd, cons return CMD_RES_OK; } +#if MQTT_USE_TLS +static commandResult_t CMD_WebServer(const void* context, const char* cmd, const char* args, int cmdFlags) { + int arg_count; + Tokenizer_TokenizeString(args, 0); + arg_count = Tokenizer_GetArgsCount(); + if (arg_count == 0) + { + ADDLOG_INFO(LOG_FEATURE_CMD, "WebServer:%d", !CFG_GetDisableWebServer()); + return CMD_RES_OK; + } + if (arg_count == 1) { + if (strcmp(Tokenizer_GetArg(0) , "0") == 0) { + ADDLOG_INFO(LOG_FEATURE_CMD, "Stop WebServer"); + CFG_SetDisableWebServer(true); + CFG_Save_IfThereArePendingChanges(); + HTTPServer_Stop(); + return CMD_RES_OK; + } + else if (strcmp(Tokenizer_GetArg(0), "1") == 0) { + ADDLOG_INFO(LOG_FEATURE_CMD, "Enable WebServer and restart"); + CFG_SetDisableWebServer(false); + CFG_Save_IfThereArePendingChanges(); + HAL_RebootModule(); + return CMD_RES_OK; + } + } + ADDLOG_ERROR(LOG_FEATURE_CMD, "Invalid Argument"); + return CMD_RES_BAD_ARGUMENT; +} +#endif + void CMD_Init_Early() { //cmddetail:{"name":"alias","args":"[Alias][Command with spaces]", //cmddetail:"descr":"add an aliased command, so a command with spaces can be called with a short, nospaced alias", @@ -767,7 +800,14 @@ void CMD_Init_Early() { //cmddetail:"fn":"NULL);","file":"cmnds/cmd_main.c","requires":"", //cmddetail:"examples":""} CMD_RegisterCommand("Choice", CMD_Choice, NULL); +#if MQTT_USE_TLS //CMD_RegisterCommand("FindPattern", CMD_FindPattern, NULL); + //cmddetail:{"name":"WebServer","args":"[0 - Stop / 1 - Start]", + //cmddetail:"descr":"Setting state of WebServer", + //cmddetail:"fn":"CMD_WebServer","file":"cmnds/cmd_main.c","requires":"", + //cmddetail:"examples":""} + CMD_RegisterCommand("WebServer", CMD_WebServer, NULL); +#endif CMD_RegisterCommand("TimeSize", CMD_TimeSize, NULL); diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c index e7629a592..ddcfbb842 100644 --- a/src/httpserver/http_fns.c +++ b/src/httpserver/http_fns.c @@ -18,6 +18,9 @@ #include #include "../driver/drv_ntp.h" #include "../driver/drv_local.h" +#ifdef PLATFORM_BEKEN +#include "start_type_pub.h" +#endif static char SUBMIT_AND_END_FORM[] = "
"; @@ -947,7 +950,24 @@ int http_fn_cfg_mqtt(http_request_t* request) { add_label_text_field(request, "Host", "host", CFG_GetMQTTHost(), "
"); add_label_numeric_field(request, "Port", "port", CFG_GetMQTTPort(), "
"); - add_label_text_field(request, "Client Topic (Base Topic)", "client", CFG_GetMQTTClientId(), "

"); + +#if MQTT_USE_TLS + hprintf255(request, ""); + } + hprintf255(request, "
"); + + hprintf255(request, ""); + } + hprintf255(request, "
"); + + add_label_text_field(request, "Certificate File (CA Root or Public Certificate PEM format)", "mqtt_cert_file", CFG_GetMQTTCertFile(), "
"); +#endif + + add_label_text_field(request, "Client Topic (Base Topic)", "client", CFG_GetMQTTClientId(), "
"); add_label_text_field(request, "Group Topic (Secondary Topic to only receive cmnds)", "group", CFG_GetMQTTGroupTopic(), "
"); add_label_text_field(request, "User", "user", CFG_GetMQTTUserName(), "
"); add_label_password_field(request, "Password", "password", CFG_GetMQTTPass(), "
"); @@ -1017,6 +1037,14 @@ int http_fn_cfg_mqtt_set(http_request_t* request) { if (http_getArg(request->url, "port", tmpA, sizeof(tmpA))) { CFG_SetMQTTPort(atoi(tmpA)); } + +#if MQTT_USE_TLS + CFG_SetMQTTUseTls(http_getArg(request->url, "mqtt_use_tls", tmpA, sizeof(tmpA))); + CFG_SetMQTTVerifyTlsCert(http_getArg(request->url, "mqtt_verify_tls_cert", tmpA, sizeof(tmpA))); + http_getArg(request->url, "mqtt_cert_file", tmpA, sizeof(tmpA)); + CFG_SetMQTTCertFile(tmpA); +#endif + if (http_getArg(request->url, "user", tmpA, sizeof(tmpA))) { CFG_SetMQTTUserName(tmpA); } @@ -1047,6 +1075,15 @@ int http_fn_cfg_webapp(http_request_t* request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set Webapp"); add_label_text_field(request, "URL of the Webapp", "url", CFG_GetWebappRoot(), ""); + +#if MQTT_USE_TLS + hprintf255(request, ""); + } + hprintf255(request, "
"); +#endif + poststr(request, SUBMIT_AND_END_FORM); poststr(request, htmlFooterReturnToCfgOrMainPage); http_html_end(request); @@ -1068,6 +1105,14 @@ int http_fn_cfg_webapp_set(http_request_t* request) { poststr(request, "Webapp url not set because you didn't specify the argument."); } +#if MQTT_USE_TLS + CFG_SetDisableWebServer(!http_getArg(request->url, "enable_web_server", tmpA, sizeof(tmpA))); + if (CFG_GetDisableWebServer()) { + poststr(request, "
"); + poststr(request, "Webapp will be disabled on next boot!"); + } +#endif + poststr(request, "
"); poststr(request, htmlFooterReturnToCfgOrMainPage); http_html_end(request); diff --git a/src/httpserver/http_tcp_server.c b/src/httpserver/http_tcp_server.c index de186e8db..64a2b8599 100644 --- a/src/httpserver/http_tcp_server.c +++ b/src/httpserver/http_tcp_server.c @@ -54,6 +54,17 @@ void HTTPServer_Start() } } +void HTTPServer_Stop() +{ + OSStatus err = kNoErr; + + err = rtos_delete_thread(&g_http_thread); + + if (err != kNoErr) + { + ADDLOG_ERROR(LOG_FEATURE_HTTP, "stop \"TCP_server\" thread failed with %i!\r\n", err); + } +} int sendfn(int fd, char* data, int len) { if (fd) { diff --git a/src/httpserver/http_tcp_server.h b/src/httpserver/http_tcp_server.h index ba803a6c8..e39e579b6 100644 --- a/src/httpserver/http_tcp_server.h +++ b/src/httpserver/http_tcp_server.h @@ -1,2 +1,3 @@ void HTTPServer_Start(); +void HTTPServer_Stop(); \ No newline at end of file diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c index e893bc280..79d217d58 100644 --- a/src/mqtt/new_mqtt.c +++ b/src/mqtt/new_mqtt.c @@ -14,6 +14,36 @@ #define BUILD_AND_VERSION_FOR_MQTT "Open" PLATFORM_MCU_NAME " " USER_SW_VER " " __DATE__ " " __TIME__ +#if MQTT_USE_TLS +#include "lwip/altcp_tls.h" +#include "lwip/apps/mqtt_priv.h" +#include "apps/altcp_tls/altcp_tls_mbedtls_structs.h" +#include "mbedtls/ssl.h" +struct altcp_tls_config { + mbedtls_ssl_config conf; + mbedtls_x509_crt* cert; + mbedtls_pk_context* pkey; + u8_t cert_count; + u8_t cert_max; + u8_t pkey_count; + u8_t pkey_max; + mbedtls_x509_crt* ca; +#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_USE_SESSION_CACHE + struct mbedtls_ssl_cache_context cache; +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && ALTCP_MBEDTLS_USE_SESSION_TICKETS + mbedtls_ssl_ticket_context ticket_ctx; +#endif +}; +#if ALTCP_MBEDTLS_DEBUG + #include "mbedtls/ssl_internal.h" + #include "mbedtls/debug.h" + static int mbedtls_verify_cb(void* data, mbedtls_x509_crt* crt, int depth, uint32_t* flags); + static void mbedtls_debug_cb(void* ctx, int level, const char* file, int line, const char* str); + void mbedtls_dump_conf(mbedtls_ssl_config* conf, mbedtls_ssl_context* ssl); +#endif +#endif + #ifndef LWIP_MQTT_EXAMPLE_IPADDR_INIT #if LWIP_IPV4 #define LWIP_MQTT_EXAMPLE_IPADDR_INIT = IPADDR4_INIT(PP_HTONL(IPADDR_LOOPBACK)) @@ -1067,6 +1097,15 @@ static void mqtt_connection_cb(mqtt_client_t* client, void* arg, mqtt_connection { addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_connection_cb: Successfully connected\n"); +#if LWIP_ALTCP_TLS_MBEDTLS + if (CFG_GetMQTTUseTls() && client && client->conn && client->conn->state) { + altcp_mbedtls_state_t* state = client->conn->state; + mbedtls_ssl_context* ssl = &state->ssl_context; + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT TLS VERSION: %s\n", mbedtls_ssl_get_version(ssl)); + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "MQTT TLS CIPHER : %s\n", mbedtls_ssl_get_ciphersuite(ssl)); + } +#endif + //LOCK_TCPIP_CORE(); mqtt_set_inpub_callback(mqtt_client, mqtt_incoming_publish_cb, @@ -1130,6 +1169,7 @@ static int MQTT_do_connect(mqtt_client_t* client) int res; struct hostent* hostEntry; char will_topic[CGF_MQTT_CLIENT_ID_SIZE + 16]; + bool mqtt_use_tls, mqtt_verify_tls_cert; mqtt_host = CFG_GetMQTTHost(); @@ -1143,6 +1183,10 @@ static int MQTT_do_connect(mqtt_client_t* client) mqtt_pass = CFG_GetMQTTPass(); mqtt_clientID = CFG_GetMQTTClientId(); mqtt_port = CFG_GetMQTTPort(); +#if MQTT_USE_TLS + mqtt_use_tls = CFG_GetMQTTUseTls(); + mqtt_verify_tls_cert = CFG_GetMQTTVerifyTlsCert(); +#endif addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "mqtt_userName %s\r\nmqtt_pass %s\r\nmqtt_clientID %s\r\nmqtt_host %s:%d\r\n", mqtt_userName, @@ -1190,6 +1234,60 @@ static int MQTT_do_connect(mqtt_client_t* client) return 0; } + /* Includes for MQTT over TLS */ +#if MQTT_USE_TLS + /* Free old configuration */ + if (mqtt_client_info.tls_config) { + altcp_tls_free_config(mqtt_client_info.tls_config); + altcp_tls_free_entropy(); + mqtt_client_info.tls_config = NULL; + } + if (mqtt_use_tls) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Secure TLS connection enabled"); + size_t ca_len = 0; + u8_t* ca = NULL; + if (mqtt_verify_tls_cert) { + if (strlen(CFG_GetMQTTCertFile()) > 0) { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Load certificate %s", CFG_GetMQTTCertFile()); + ca = LFS_ReadFile(CFG_GetMQTTCertFile()); + if (ca) { + ca_len = strlen((char*)ca)+1; + } + } + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Verify certificate disabled"); + } + mqtt_client_info.tls_config = altcp_tls_create_config_client(ca, ca_len); + if (ca) { + free(ca); + ca = NULL; + } + if (mqtt_client_info.tls_config) { +#if ALTCP_MBEDTLS_DEBUG + mbedtls_ssl_conf_verify(&mqtt_client_info.tls_config->conf, mbedtls_verify_cb, NULL); +#if MBEDTLS_DEBUG_C + mbedtls_ssl_conf_dbg(&mqtt_client_info.tls_config->conf, mbedtls_debug_cb, NULL); + mbedtls_debug_set_threshold(1); +#endif + if (mqtt_client_info.tls_config->ca){ + mbedtls_dump_conf(&mqtt_client_info.tls_config->conf, NULL); + } +#endif + + if (mqtt_verify_tls_cert) { + mbedtls_ssl_conf_authmode(&mqtt_client_info.tls_config->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + } + else { + mbedtls_ssl_conf_authmode(&mqtt_client_info.tls_config->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); + } + } + else { + addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Secure TLS config fail. Try connect anyway."); + } + } +#endif + // host name/ip //ipaddr_aton(mqtt_host,&mqtt_ip); @@ -2245,3 +2343,202 @@ bool MQTT_IsReady() { return mqtt_client && res; } +#if MQTT_USE_TLS +#ifdef MBEDTLS_ENTROPY_HARDWARE_ALT +#include "fake_clock_pub.h" +#include "mbedtls/error.h" +int mbedtls_hardware_poll(void* data, unsigned char* output, size_t len, size_t* olen) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void)data); + *olen = 0; + + if (len < sizeof(unsigned char)) { + return 0; + } + + if (output) { + srand(fclk_get_second()); + for (size_t n = 0; n < len; n++) { + output[n] = rand() % 255; + } + *olen = len; + ret = 0; + } + return ret; +} +int mbedtls_hardclock_poll(void* data, unsigned char* output, size_t len, size_t* olen) { + return mbedtls_hardware_poll(data, output, len, olen); +} +#endif //MBEDTLS_ENTROPY_HARDWARE_ALT + +#ifdef MBEDTLS_PLATFORM_GMTIME_R_ALT +struct tm* cvt_date(char const* date, char const* time, struct tm* t); +struct tm* cvt_date(char const* date, char const* time, struct tm* t) +{ + char s_month[5]; + int year; + static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; + sscanf(date, "%s %d %d", s_month, &t->tm_mday, &year); + sscanf(time, "%2d %*c %2d %*c %2d", &t->tm_hour, &t->tm_min, &t->tm_sec); + // Find where is s_month in month_names. Deduce month value. + t->tm_mon = (strstr(month_names, s_month) - month_names) / 3; + t->tm_year = year - 1900; + return t; +} +struct tm* mbedtls_platform_gmtime_r(const mbedtls_time_t* tt, struct tm* tm_buf) { + // If NTP time not synced return compile time + struct tm* ltm; + if (!NTP_IsTimeSynced()) { + ltm = cvt_date(__DATE__, __TIME__, tm_buf); + //addLogAdv(LOG_INFO, LOG_FEATURE_NTP, "MBEDTLS Time : %04d/%02d/%02d %02d:%02d:%02d", + // ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec); + return ltm; + } + return gmtime_r((time_t*)&g_ntpTime, tm_buf); +} +#endif //MBEDTLS_PLATFORM_GMTIME_R_ALT + + +#if ALTCP_MBEDTLS_DEBUG +static int mbedtls_verify_cb(void* data, mbedtls_x509_crt* crt, int depth, uint32_t* flags) +{ + ((void)data); + char buf[1024]; + + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "Verify requested for (Depth% d) : \n", depth); + mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "\n%s", buf); + + if ((*flags) == 0) { + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " This certificate has no flags\n"); + } + else { + mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", *flags); + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "%s\n", buf); + } + return 0; +} + +static void mbedtls_debug_cb(void* ctx, int level, const char* file, int line, const char* str) +{ + const char* p, * basename; + (void)ctx; + + if (level == 2) + return; + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + } + + addLogAdv(LOG_ERROR, LOG_FEATURE_MQTT, "%s:%04d: |%d| %s", basename, line, level, str); +} + +void mbedtls_dump_conf(mbedtls_ssl_config* conf, mbedtls_ssl_context* ssl) { + if (ssl && ssl->handshake) { + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE CIPHER SUITE: %s", ssl->handshake->ciphersuite_info->name); + switch (ssl->handshake->ciphersuite_info->key_exchange) + { + case MBEDTLS_KEY_EXCHANGE_NONE: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_NONE"); + break; + case MBEDTLS_KEY_EXCHANGE_RSA: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_RSA"); + break; + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_DHE_RSA"); + break; + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_ECDHE_RSA"); + break; + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA"); + break; + case MBEDTLS_KEY_EXCHANGE_PSK: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_PSK"); + break; + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_DHE_PSK"); + break; + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_RSA_PSK"); + break; + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_ECDHE_PSK"); + break; + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_ECDH_RSA"); + break; + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA"); + break; + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "HANDSHAKE KEY EXCHANGE: MBEDTLS_KEY_EXCHANGE_ECJPAKE"); + break; + } + } + + if (conf) { + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "AVAILABLE CIPHERS:"); + int len = sizeof(conf->ciphersuite_list) / (sizeof(conf->ciphersuite_list[0])); + for (int s = 0; s < len; s++) { + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " %s", + mbedtls_ssl_get_ciphersuite_name(*conf->ciphersuite_list[s])); + } + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, "AVAILABLE CURVES:"); + len = sizeof(conf->curve_list) / (sizeof(mbedtls_ecp_group_id)); + const mbedtls_ecp_group_id* c = conf->curve_list; + for (; *c; c++) { + switch (*c) + { + case MBEDTLS_ECP_DP_NONE: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_NONE"); + break; + case MBEDTLS_ECP_DP_SECP192R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP192R1"); + break; + case MBEDTLS_ECP_DP_SECP224R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP224R1"); + break; + case MBEDTLS_ECP_DP_SECP256R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP256R1"); + break; + case MBEDTLS_ECP_DP_SECP384R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP384R1"); + break; + case MBEDTLS_ECP_DP_SECP521R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP521R1"); + break; + case MBEDTLS_ECP_DP_BP256R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_BP256R1"); + break; + case MBEDTLS_ECP_DP_BP384R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_BP384R1"); + break; + case MBEDTLS_ECP_DP_BP512R1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_BP512R1"); + break; + case MBEDTLS_ECP_DP_CURVE25519: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_CURVE25519"); + break; + case MBEDTLS_ECP_DP_SECP192K1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP192K1"); + break; + case MBEDTLS_ECP_DP_SECP224K1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP224K1"); + break; + case MBEDTLS_ECP_DP_SECP256K1: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_SECP256K1"); + break; + case MBEDTLS_ECP_DP_CURVE448: + addLogAdv(LOG_DEBUG, LOG_FEATURE_MQTT, " MBEDTLS_ECP_DP_CURVE448"); + break; + } + } + } +} +#endif //ALTCP_MBEDTLS_DEBUG +#endif //MQTT_USE_TLS \ No newline at end of file diff --git a/src/new_cfg.c b/src/new_cfg.c index 23ce98e44..818abd281 100644 --- a/src/new_cfg.c +++ b/src/new_cfg.c @@ -172,6 +172,13 @@ void CFG_SetDefaultConfig() { CFG_SetDefaultLEDCorrectionTable(); +#if MQTT_USE_TLS + CFG_SetMQTTUseTls(0); + CFG_SetMQTTVerifyTlsCert(0); + CFG_SetMQTTCertFile(""); + CFG_SetDisableWebServer(0); +#endif + g_cfg_pendingChanges++; } @@ -706,6 +713,52 @@ uint32_t CFG_GetLFS_Size() { } #endif +#if MQTT_USE_TLS +byte CFG_GetMQTTUseTls() { + return g_cfg.mqtt_use_tls; +} +byte CFG_GetMQTTVerifyTlsCert() { + return g_cfg.mqtt_verify_tls_cert; +} +const char* CFG_GetMQTTCertFile() { + return g_cfg.mqtt_cert_file; +} +void CFG_SetMQTTUseTls(byte value) { + // is there a change? + if (g_cfg.mqtt_use_tls != value) { + g_cfg.mqtt_use_tls = value; + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} +void CFG_SetMQTTVerifyTlsCert(byte value) { + // is there a change? + if (g_cfg.mqtt_verify_tls_cert != value) { + g_cfg.mqtt_verify_tls_cert = value; + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} +void CFG_SetMQTTCertFile(const char* s) { + // this will return non-zero if there were any changes + if (strcpy_safe_checkForChanges(g_cfg.mqtt_cert_file, s, sizeof(g_cfg.mqtt_cert_file))) { + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} +byte CFG_GetDisableWebServer() { + return g_cfg.disable_web_server; +} +void CFG_SetDisableWebServer(byte value) { + // is there a change? + if (g_cfg.disable_web_server != value) { + g_cfg.disable_web_server = value; + // mark as dirty (value has changed) + g_cfg_pendingChanges++; + } +} +#endif + void CFG_InitAndLoad() { byte chkSum; diff --git a/src/new_cfg.h b/src/new_cfg.h index ec1bcc12a..a01d0a02c 100644 --- a/src/new_cfg.h +++ b/src/new_cfg.h @@ -93,9 +93,20 @@ const char *CFG_GetWebPassword(); void CFG_SetWebPassword(const char *s); #if ENABLE_LITTLEFS - void CFG_SetLFS_Size(uint32_t value); - uint32_t CFG_GetLFS_Size(); +void CFG_SetLFS_Size(uint32_t value); +uint32_t CFG_GetLFS_Size(); #endif +#if MQTT_USE_TLS +void CFG_SetMQTTUseTls(byte value); +void CFG_SetMQTTVerifyTlsCert(byte value); +void CFG_SetMQTTCertFile(const char* s); +byte CFG_GetMQTTUseTls(); +byte CFG_GetMQTTVerifyTlsCert(); +const char* CFG_GetMQTTCertFile(); +byte CFG_GetDisableWebServer(); +void CFG_SetDisableWebServer(byte value); +#endif + #endif diff --git a/src/new_pins.h b/src/new_pins.h index 294ded357..6eacf6be2 100644 --- a/src/new_pins.h +++ b/src/new_pins.h @@ -1239,9 +1239,17 @@ typedef struct mainConfig_s { // offset 0x00000C84 (3204 decimal) char webPassword[33]; // offset 0x00000CA5 (3237 decimal) - char unused[347]; + byte mqtt_use_tls; + // offset 0x00000CA6 (3238 decimal) + byte mqtt_verify_tls_cert; + // offset 0x00000CA7 (3239 decimal) + char mqtt_cert_file[20]; + // offset 0x00000CBB (3259 decimal) + byte disable_web_server; + // offset 0x00000CBC (3260 decimal) + char unused[324]; #endif -} mainConfig_t; +} mainConfig_t; // one sector is 4096 so it we still have some expand possibility #define MAGIC_CONFIG_SIZE_V3 2016 diff --git a/src/user_main.c b/src/user_main.c index 2aec490ac..17e7c76c7 100644 --- a/src/user_main.c +++ b/src/user_main.c @@ -44,6 +44,8 @@ #include #include #include "temp_detect_pub.h" +#include "BkDriverWdg.h" + void bg_register_irda_check_func(FUNCPTR func); #elif PLATFORM_BL602 #include @@ -1303,8 +1305,14 @@ void Main_Init_After_Delay() // NOT WORKING, I done it other way, see ethernetif.c //net_dhcp_hostname_set(g_shortDeviceName); - HTTPServer_Start(); - ADDLOGF_DEBUG("Started http tcp server\r\n"); +#if MQTT_USE_TLS + if (!CFG_GetDisableWebServer() || bSafeMode) { +#endif + HTTPServer_Start(); + ADDLOGF_DEBUG("Started http tcp server\r\n"); +#if MQTT_USE_TLS + } +#endif // only initialise certain things if we are not in AP mode if (!bSafeMode) diff --git a/src/user_mbedtls_config.h b/src/user_mbedtls_config.h new file mode 100644 index 000000000..2deadf633 --- /dev/null +++ b/src/user_mbedtls_config.h @@ -0,0 +1,176 @@ +/****************************************************************************** + * @version V1.0.0 + * @date 05-Oct-2023 + * + * This file contains specific configuration for mbedtls + * Due to environment limitations there is only one version of TSL + * and only one cipher enabled: + * TSL VERSION: TLSv1.2 + * TSL CIPHER : TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 + * + * This is a common configuration supported by the mosquitto MQTT server + * + * Tested only with LWIP MQTT client application on BK7231N platform + * It's possible that it will also work on other platforms, + * but I don't have specific hardware to test. + * + * The web server MQTT page has been updated to specify whether MQTT + * uses TSL and if the certificate needs to be validated. + * The CA certificate or public certificate (in case of self-signed) + * must be uploaded in PEM format to LFS + * + * To validate the certificate dates, the NTP driver must be enabled, + * otherwise the build date will be used to validate. + * + * You can use Mqtt TSL without a CA or public certificate if you disable + * validation, but this is not recommended. + * Your client will be vulnerable to the MIT attack. + * + * Additionally, an option to disable the web app has been added to + * strengthen security. After connected to mqtt use + * cmnd//WebServer 0 to disable web interface + * cmnd//WebServer 1 to enable web interface + * Communication only with secure mqtt connection + * + * Author: alexsandroz@gmail.com + * + ******************************************************************************/ + + +#ifndef USER_MBEDTLS_CONFIG_H +#define USER_MBEDTLS_CONFIG_H + +#if MQTT_USE_TLS + +#include "mbedtls/config.h" + +// Plataform specific +#undef MBEDTLS_FS_IO +#undef MBEDTLS_NET_C +#define MBEDTLS_TIMING_C +#define MBEDTLS_HAVE_TIME_DATE +#define MBEDTLS_PLATFORM_GMTIME_R_ALT +#define MBEDTLS_NO_PLATFORM_ENTROPY +#define MBEDTLS_ENTROPY_HARDWARE_ALT +#define MBEDTLS_MPI_WINDOW_SIZE 1 +#define MBEDTLS_MPI_MAX_SIZE 512 +#define MBEDTLS_ECP_WINDOW_SIZE 2 +#define MBEDTLS_SSL_MAX_CONTENT_LEN 4096 + +// Modes +#define MBEDTLS_SSL_CLI_C // Only client enabled +#undef MBEDTLS_SSL_SRV_C + +// Protos +#undef MBEDTLS_SSL_PROTO_SSL3 +#undef MBEDTLS_SSL_PROTO_TLS1 +#undef MBEDTLS_SSL_PROTO_TLS1_1 +#define MBEDTLS_SSL_PROTO_TLS1_2 // Only TLS1.2 enabled +#undef MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL +#undef MBEDTLS_SSL_PROTO_DTLS +#undef MBEDTLS_SSL_DTLS_ANTI_REPLAY + +// Enabled Ciphers +#define MBEDTLS_RSA_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA256_SMALLER +#define MBEDTLS_AES_C +#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_AES_FEWER_TABLES +#define MBEDTLS_ENTROPY_FORCE_SHA256 + +//Disabled ciphers +#undef MBEDTLS_ARC4_C +#undef MBEDTLS_BLOWFISH_C +#undef MBEDTLS_CAMELLIA_C +#undef MBEDTLS_ARIA_C +#undef MBEDTLS_DES_C +#undef MBEDTLS_CCM_C +#undef MBEDTLS_MD2_C +#undef MBEDTLS_MD4_C +#undef MBEDTLS_MD5_C +#undef MBEDTLS_RIPEMD160_C +#undef MBEDTLS_SHA1_C +#undef MBEDTLS_SHA512_C +#define MBEDTLS_SHA512_NO_SHA384 +#undef MBEDTLS_CHACHA20_C +#undef MBEDTLS_CHACHAPOLY_C +#undef MBEDTLS_POLY1305_C +#undef MBEDTLS_CIPHER_NULL_CIPHER +#undef MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define MBEDTLS_REMOVE_3DES_CIPHERSUITES +#undef MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +// Curves // +#undef MBEDTLS_ECP_DP_SECP192R1_ENABLED +#undef MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED //Only SECP256R1 +#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED +#undef MBEDTLS_ECP_DP_SECP521R1_ENABLED +#undef MBEDTLS_ECP_DP_SECP192K1_ENABLED +#undef MBEDTLS_ECP_DP_SECP224K1_ENABLED +#undef MBEDTLS_ECP_DP_SECP256K1_ENABLED +#undef MBEDTLS_ECP_DP_BP256R1_ENABLED +#undef MBEDTLS_ECP_DP_BP384R1_ENABLED +#undef MBEDTLS_ECP_DP_BP512R1_ENABLED +#undef MBEDTLS_ECP_DP_CURVE25519_ENABLED +#undef MBEDTLS_ECP_DP_CURVE448_ENABLED + +// Block mode +#define MBEDTLS_GCM_C //Only GCM +#undef MBEDTLS_CIPHER_MODE_CBC +#undef MBEDTLS_CIPHER_MODE_CFB +#undef MBEDTLS_CIPHER_MODE_CTR +#undef MBEDTLS_CIPHER_MODE_OFB +#undef MBEDTLS_CIPHER_MODE_XTS + +// Exchange Key // +#define MBEDTLS_DHM_C +#define MBEDTLS_ECDH_C +#undef MBEDTLS_ECDSA_C +#undef MBEDTLS_ECJPAKE_C +#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +// Define only on development // +#if 0 +#define MBEDTLS_DEBUG_C +#define MBEDTLS_SELF_TEST +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define MBEDTLS_SSL_RECORD_CHECKING +#define MBEDTLS_SSL_CONTEXT_SERIALIZATION +#define MBEDTLS_SSL_DEBUG_ALL +#define MBEDTLS_VERSION_FEATURES +#define MBEDTLS_CERTS_C +#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define MBEDTLS_MEMORY_BACKTRACE +#else +#undef MBEDTLS_DEBUG_C +#undef MBEDTLS_SELF_TEST +#undef MBEDTLS_SSL_ALL_ALERT_MESSAGES +#undef MBEDTLS_SSL_RECORD_CHECKING +#undef MBEDTLS_SSL_CONTEXT_SERIALIZATION +#undef MBEDTLS_SSL_DEBUG_ALL +#undef MBEDTLS_VERSION_FEATURES +#undef MBEDTLS_CERTS_C +#undef MBEDTLS_MEMORY_BUFFER_ALLOC_C +#undef MBEDTLS_MEMORY_BACKTRACE +#endif + +//Disabled functions +#undef MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +#undef MBEDTLS_PKCS1_V21 +#undef MBEDTLS_GENPRIME +#undef MBEDTLS_X509_RSASSA_PSS_SUPPORT + +#endif //MQTT_USE_TLS +#endif //USER_MBEDTLS_CONFIG_H \ No newline at end of file