From c83e415a0f14f7bbea94123b98f4bc2f0d0bb765 Mon Sep 17 00:00:00 2001 From: TD-er Date: Sun, 29 Sep 2024 21:03:15 +0200 Subject: [PATCH] [MQTT-TLS] Switch to Tasmota's Light-Weight BearSSL lib --- lib/lib_ssl/tls_mini/src/StackThunk_light.cpp | 3 +- .../src/WiFiClientSecureLightBearSSL.cpp | 42 +- .../src/WiFiClientSecureLightBearSSL.h | 17 +- platformio.ini | 4 + src/src/CustomBuild/Certificate_CA.h | 202 ++++++ src/src/CustomBuild/define_plugin_sets.h | 9 + src/src/ESPEasyCore/Controller.cpp | 81 ++- src/src/Globals/ESPEasy_time.cpp | 6 +- src/src/Globals/ESPEasy_time.h | 2 + src/src/Globals/MQTT.cpp | 2 +- src/src/Globals/MQTT.h | 16 +- src/src/Helpers/ESPEasy_WiFiClientSecure.cpp | 441 -------------- src/src/Helpers/ESPEasy_WiFiClientSecure.h | 125 ---- src/src/Helpers/ESPEasy_ssl_client.cpp | 575 ------------------ src/src/Helpers/ESPEasy_ssl_client.h | 51 -- src/src/WebServer/ControllerPage.cpp | 10 +- 16 files changed, 320 insertions(+), 1266 deletions(-) create mode 100644 src/src/CustomBuild/Certificate_CA.h delete mode 100644 src/src/Helpers/ESPEasy_WiFiClientSecure.cpp delete mode 100644 src/src/Helpers/ESPEasy_WiFiClientSecure.h delete mode 100644 src/src/Helpers/ESPEasy_ssl_client.cpp delete mode 100644 src/src/Helpers/ESPEasy_ssl_client.h diff --git a/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp b/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp index 098752c88..daaed2d76 100644 --- a/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp +++ b/lib/lib_ssl/tls_mini/src/StackThunk_light.cpp @@ -25,9 +25,8 @@ Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) */ -#include "tasmota_options.h" -#if defined(ESP8266) && defined(USE_TLS) +#if defined(ESP8266) && FEATURE_TLS #include #include #include "StackThunk_light.h" diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp index 540d37420..27b2cdc24 100644 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp @@ -20,8 +20,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "tasmota_options.h" -#ifdef USE_TLS + +#if FEATURE_TLS // #define DEBUG_TLS // #define DEBUG_ESP_SSL @@ -33,8 +33,15 @@ #include #include "WiFiClientSecureLightBearSSL.h" // needs to be before "ESP8266WiFi.h" to avoid conflict with Arduino headers -#include "ESP8266WiFi.h" -#include "WiFiHelper.h" + +#ifdef ESP32 + #include +#endif + +#ifdef ESP8266 + #include +#endif + #include "WiFiClient.h" #include "StackThunk_light.h" #include "lwip/opt.h" @@ -68,9 +75,6 @@ void _Log_heap_size(const char *msg) { #define LOG_HEAP_SIZE(a) #endif -// get UTC time from Tasmota -extern uint32_t UtcTime(void); -extern uint32_t CfgTime(void); #ifdef ESP8266 // Stack thunk is not needed with ESP32 // Stack thunked versions of calls @@ -319,7 +323,7 @@ int WiFiClientSecure_light::connect(const char* name, uint16_t port, int32_t tim DEBUG_BSSL("connect(%s,%d)\n", name, port); IPAddress remote_addr; clearLastError(); - if (!WiFiHelper::hostByName(name, remote_addr)) { + if (WiFi.hostByName(name, remote_addr) != 1) { DEBUG_BSSL("connect: Name loopup failure\n"); setLastError(ERR_CANT_RESOLVE_IP); return 0; @@ -338,7 +342,7 @@ int WiFiClientSecure_light::connect(const char* name, uint16_t port) { DEBUG_BSSL("connect(%s,%d)\n", name, port); IPAddress remote_addr; clearLastError(); - if (!WiFiHelper::hostByName(name, remote_addr)) { + if (WiFi.hostByName(name, remote_addr, 1000) != 1) { DEBUG_BSSL("connect: Name loopup failure\n"); setLastError(ERR_CANT_RESOLVE_IP); return 0; @@ -1010,8 +1014,26 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { return false; } +uint32_t WiFiClientSecure_light::UtcTime(void) const +{ + if (_UtcTime == nullptr) { + return 0u; + } + return _UtcTime(); +} + +uint32_t WiFiClientSecure_light::CfgTime(void) const +{ + if (_CfgTime == nullptr) { + return 0u; + } + return _CfgTime(); +} + + }; #include "t_bearssl_tasmota_config.h" -#endif // USE_TLS + +#endif // FEATURE_MQTT diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h index 3f0a892a5..f62b5fdb0 100644 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h @@ -24,7 +24,7 @@ #ifndef wificlientlightbearssl_h #define wificlientlightbearssl_h -#ifdef USE_TLS +#if FEATURE_TLS #include #include "WiFiClient.h" #include @@ -33,9 +33,15 @@ namespace BearSSL { class WiFiClientSecure_light : public WiFiClient { public: + typedef std::function UtcTime_fcn; + typedef std::function CfgTime_fcn; + WiFiClientSecure_light(int recv, int xmit); ~WiFiClientSecure_light() override; + void setUtcTime_fcn(UtcTime_fcn fcn) { _UtcTime = fcn; } + void setCfgTime_fcn(CfgTime_fcn fcn) { _CfgTime = fcn; } + void allocateBuffers(void); #ifdef ESP32 // the method to override in ESP32 has timeout argument default #define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000) @@ -184,6 +190,13 @@ class WiFiClientSecure_light : public WiFiClient { const char ** _alpn_names; size_t _alpn_num; + uint32_t UtcTime(void) const; + uint32_t CfgTime(void) const; + + + UtcTime_fcn _UtcTime{nullptr}; + CfgTime_fcn _CfgTime{nullptr}; + }; #define ERR_OOM -1000 @@ -296,5 +309,5 @@ class WiFiClientSecure_light : public WiFiClient { }; -#endif // USE_TLS +#endif // FEATURE_MQTT #endif // wificlientlightbearssl_h diff --git a/platformio.ini b/platformio.ini index aa5f95c35..e7d477085 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,6 +28,7 @@ extra_configs = platformio_esp32c2_envs.ini platformio_esp32c6_envs.ini + ;default_envs = normal_ESP32_4M default_envs = max_ESP32_16M8M_LittleFS_ETH ;default_envs = normal_ESP32c6_4M316k_LittleFS_CDC @@ -107,3 +108,6 @@ src_filter = +<*> -<.git/> -<.svn/> - - - + +#if __has_include("../../Custom_CERTS.h") +#include "../../Custom_CERTS.h" +#else + +// Root Certificates taken from: +// https://github.com/arendst/Tasmota/blob/b2b839fa83b622c3d28324ac4d6db7ab133741c6/tasmota/tasmota_support/tasmota_ca.ino#L177 + + +#if ! defined(OMIT_LETS_ENCRYPT_CERT) + +/*********************************************************************************************\ + * LetsEncrypt ISRG Root X1 certificate, RSA 4096 bits SHA 256, valid until 20350604 + * + * https://letsencrypt.org/certificates/ + * Downloaded from https://letsencrypt.org/certs/isrgrootx1.pem + * + * to convert do: `bearssl ta isrgrootx1.pem` + * then copy and paste below, chain the generic names to the same as below + * remove "static" and add "PROGMEM" +\*********************************************************************************************/ + +static const unsigned char PROGMEM LetsEncrypt_ISRG_Root_X1_DN[] = { + 0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52, + 0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31 +}; + +static const unsigned char PROGMEM LetsEncrypt_ISRG_Root_X1_RSA_N[] = { + 0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57, + 0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C, + 0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E, + 0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6, + 0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B, + 0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3, + 0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69, + 0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22, + 0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99, + 0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53, + 0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C, + 0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21, + 0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB, + 0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF, + 0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C, + 0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE, + 0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE, + 0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B, + 0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90, + 0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1, + 0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7, + 0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96, + 0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03, + 0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9, + 0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F, + 0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77, + 0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72, + 0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5, + 0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99, + 0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12, + 0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D, + 0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12, + 0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA, + 0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36, + 0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98, + 0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83, + 0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2, + 0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC, + 0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38, + 0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2, + 0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7, + 0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51, + 0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F +}; + +static const unsigned char LetsEncrypt_ISRG_Root_X1_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +#endif + + +#if ! defined(OMIT_AWS_CERT) +/*********************************************************************************************\ + * Amazon Root CA, RSA 2048 bits SHA 256, valid until 20380117 + * + * https://www.amazontrust.com/repository/ + * Downloaded from https://www.amazontrust.com/repository/AmazonRootCA1.pem + * + * to convert do: "bearssl ta AmazonRootCA1.pem" + * then copy and paste below, chain the generic names to the same as below + * remove "static" and add "PROGMEM" +\*********************************************************************************************/ + + +const unsigned char PROGMEM AmazonRootCA1_DN[] = { + 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, + 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31 +}; + +const unsigned char PROGMEM AmazonRootCA1_RSA_N[] = { + 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80, + 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7, + 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86, + 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE, + 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23, + 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE, + 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5, + 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74, + 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C, + 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50, + 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9, + 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51, + 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3, + 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74, + 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73, + 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA, + 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E, + 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F, + 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0, + 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20, + 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C, + 0x9A, 0xC8, 0xAA, 0x0D +}; + +static const unsigned char PROGMEM AmazonRootCA1_RSA_E[] = { + 0x01, 0x00, 0x01 +}; + +#endif + + +// +// ========== cumulative CA ================= +// +const br_x509_trust_anchor PROGMEM Tasmota_TA[] = { +#if ! defined(OMIT_LETS_ENCRYPT_CERT) + { + { (unsigned char *)LetsEncrypt_ISRG_Root_X1_DN, sizeof LetsEncrypt_ISRG_Root_X1_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)LetsEncrypt_ISRG_Root_X1_RSA_N, sizeof LetsEncrypt_ISRG_Root_X1_RSA_N, + (unsigned char *)LetsEncrypt_ISRG_Root_X1_RSA_E, sizeof LetsEncrypt_ISRG_Root_X1_RSA_E, + } } + } + } + +#if ! defined(OMIT_AWS_CERT) || defined(INCLUDE_LOCAL_CERT) + , +#endif +#endif + +#if ! defined(OMIT_AWS_CERT) + { + { (unsigned char *)AmazonRootCA1_DN, sizeof AmazonRootCA1_DN }, + BR_X509_TA_CA, + { + BR_KEYTYPE_RSA, + { .rsa = { + (unsigned char *)AmazonRootCA1_RSA_N, sizeof AmazonRootCA1_RSA_N, + (unsigned char *)AmazonRootCA1_RSA_E, sizeof AmazonRootCA1_RSA_E, + } } + } + } + +#if defined(INCLUDE_LOCAL_CERT) + , +#endif +#endif + + +#if defined(INCLUDE_LOCAL_CERT) +#include +#endif + +}; + +constexpr size_t Tasmota_TA_size = sizeof(Tasmota_TA) / sizeof(br_x509_trust_anchor); + + +#endif + + +#endif + +#endif \ No newline at end of file diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index de01f7af7..14f6b5e81 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -2970,6 +2970,15 @@ To create/register a plugin, you have to : #endif #endif +#if FEATURE_MQTT_TLS + #if defined(FEATURE_TLS) && !FEATURE_TLS + #undef FEATURE_TLS + #endif + #ifndef FEATURE_TLS + #define FEATURE_TLS 1 + #endif +#endif + #ifdef USES_ESPEASY_NOW #if defined(LIMIT_BUILD_SIZE) || defined(ESP8266_1M) || (defined(ESP8266) && defined(PLUGIN_BUILD_IR)) // Will not fit on ESP8266 along with IR plugins included diff --git a/src/src/ESPEasyCore/Controller.cpp b/src/src/ESPEasyCore/Controller.cpp index 923add2de..5ecba1cd5 100644 --- a/src/src/ESPEasyCore/Controller.cpp +++ b/src/src/ESPEasyCore/Controller.cpp @@ -7,6 +7,8 @@ #include "../ControllerQueue/MQTT_queue_element.h" +#include "../CustomBuild/Certificate_CA.h" + #include "../DataStructs/ControllerSettingsStruct.h" #include "../DataStructs/ESPEasy_EventStruct.h" @@ -210,18 +212,24 @@ bool MQTTConnect(controllerIndex_t controller_idx) const TLS_types TLS_type = ControllerSettings->TLStype(); if ((TLS_type != TLS_types::NoTLS) && (nullptr == mqtt_tls)) { - # ifdef ESP32 - mqtt_tls = new ESPEasy_WiFiClientSecure; - # endif // ifdef ESP32 - # ifdef ESP8266 - mqtt_tls = new BearSSL::WiFiClientSecure; - # endif // ifdef ESP8266 +#ifdef ESP32 + #if MQTT_MAX_PACKET_SIZE > 2000 + mqtt_tls = new BearSSL::WiFiClientSecure_light(4096,4096); + #else + mqtt_tls = new BearSSL::WiFiClientSecure_light(2048,2048); + #endif +#else // ESP32 - ESP8266 + mqtt_tls = new BearSSL::WiFiClientSecure_light(1024,1024); +#endif mqtt_rootCA.clear(); if (mqtt_tls == nullptr) { mqtt_tls_last_errorstr = F("MQTT : Could not create TLS client, out of memory"); addLog(LOG_LEVEL_ERROR, mqtt_tls_last_errorstr); return false; + } else { + mqtt_tls->setUtcTime_fcn(getUnixTime); + mqtt_tls->setCfgTime_fcn(get_build_unixtime); } } @@ -257,24 +265,8 @@ bool MQTTConnect(controllerIndex_t controller_idx) case TLS_types::TLS_CA_CERT: { mqtt_rootCA.clear(); - /* - { - static int previousFree = FreeMem(); - const int freemem = FreeMem(); - - String analyse = F(" free memory: "); - analyse += freemem; - analyse += F(" largest free block: "); - analyse += getMaxFreeBlock(); - - analyse += F(" Difference: "); - analyse += previousFree - freemem; - - addLog(LOG_LEVEL_INFO, analyse); - previousFree = freemem; - } - */ + // FIXME TD-er: Must convert rootCA from file to format accepted by bearSSL if (mqtt_rootCA.isEmpty() && (mqtt_tls != nullptr)) { LoadCertificate(ControllerSettings->getCertificateFilename(), mqtt_rootCA); @@ -286,13 +278,14 @@ bool MQTTConnect(controllerIndex_t controller_idx) return false; } - # ifdef ESP32 - mqtt_tls->setCACert(mqtt_rootCA.c_str()); - # endif // ifdef ESP32 - # ifdef ESP8266 - mqtt_X509List.append(mqtt_rootCA.c_str()); - mqtt_tls->setTrustAnchors(&mqtt_X509List); - # endif // ifdef ESP8266 + + + //mqtt_X509List.append(mqtt_rootCA.c_str()); +// mqtt_tls->setTrustAnchors(&mqtt_X509List); + } + */ + if (mqtt_tls != nullptr) { + mqtt_tls->setTrustAnchor(Tasmota_TA, Tasmota_TA_size); } break; } @@ -451,15 +444,11 @@ bool MQTTConnect(controllerIndex_t controller_idx) if (mqtt_tls != nullptr) { - char buf[128] = { 0 }; - # ifdef ESP8266 - mqtt_tls_last_error = mqtt_tls->getLastSSLError(buf, 128); - # endif // ifdef ESP8266 # ifdef ESP32 - mqtt_tls_last_error = mqtt_tls->lastError(buf, 128); + mqtt_tls_last_error = mqtt_tls->getLastError(); mqtt_tls->clearLastError(); # endif // ifdef ESP32 - mqtt_tls_last_errorstr = buf; + //mqtt_tls_last_errorstr = buf; } # ifdef ESP32 @@ -489,6 +478,8 @@ bool MQTTConnect(controllerIndex_t controller_idx) dn.trim(); } + // FIXME TD-er: Must implement fingerprint verification + /* if (mqtt_tls != nullptr) { if (!mqtt_tls->verify( fp.c_str(), @@ -499,6 +490,7 @@ bool MQTTConnect(controllerIndex_t controller_idx) MQTTresult = false; } } + */ } } # endif // ifdef ESP32 @@ -538,6 +530,9 @@ bool MQTTConnect(controllerIndex_t controller_idx) # if FEATURE_MQTT_TLS # ifdef ESP32 + // FIXME TD-er: Must get certificate info + /* + if ((mqtt_tls != nullptr) && loglevelActiveFor(LOG_LEVEL_INFO)) { String log = F("MQTT : Peer certificate info: "); @@ -546,6 +541,7 @@ bool MQTTConnect(controllerIndex_t controller_idx) log += mqtt_tls->getPeerCertificateInfo(); addLogMove(LOG_LEVEL_INFO, log); } + */ # endif // ifdef ESP32 # endif // if FEATURE_MQTT_TLS @@ -902,13 +898,12 @@ bool GetTLSfingerprint(String& fp) # ifdef ESP32 if (MQTTclient_connected && (mqtt_tls != nullptr)) { - uint8_t sha256_result[32] = { 0 }; - - if (mqtt_tls->getFingerprintSHA256(sha256_result)) { + const uint8_t *recv_fingerprint = mqtt_tls->getRecvPubKeyFingerprint(); + if (recv_fingerprint != nullptr) { fp.reserve(64); - for (size_t i = 0; i < 32; ++i) { - const String tmp(sha256_result[i], HEX); + for (size_t i = 0; i < 21; ++i) { + const String tmp(recv_fingerprint[i], HEX); switch (tmp.length()) { case 0: @@ -933,6 +928,9 @@ bool GetTLS_Certificate(String& cert, bool caRoot) { # ifdef ESP32 + // FIXME TD-er: Implement retrieval of certificate + /* + if (MQTTclient_connected && (mqtt_tls != nullptr)) { String subject; @@ -940,6 +938,7 @@ bool GetTLS_Certificate(String& cert, bool caRoot) return true; } } + */ # endif // ifdef ESP32 return false; } diff --git a/src/src/Globals/ESPEasy_time.cpp b/src/src/Globals/ESPEasy_time.cpp index 67b8b78e7..2c528cbf2 100644 --- a/src/src/Globals/ESPEasy_time.cpp +++ b/src/src/Globals/ESPEasy_time.cpp @@ -1,3 +1,7 @@ #include "../Globals/ESPEasy_time.h" -ESPEasy_time node_time; \ No newline at end of file +ESPEasy_time node_time; + +uint32_t getUnixTime() { + return node_time.getUnixTime(); +} \ No newline at end of file diff --git a/src/src/Globals/ESPEasy_time.h b/src/src/Globals/ESPEasy_time.h index 74d1715ae..57bef991d 100644 --- a/src/src/Globals/ESPEasy_time.h +++ b/src/src/Globals/ESPEasy_time.h @@ -5,6 +5,8 @@ extern ESPEasy_time node_time; +// Global function needed for SSL +uint32_t getUnixTime(); #endif // GLOBALS_ESPEASY_TIME_H \ No newline at end of file diff --git a/src/src/Globals/MQTT.cpp b/src/src/Globals/MQTT.cpp index 65e752e75..672f13500 100644 --- a/src/src/Globals/MQTT.cpp +++ b/src/src/Globals/MQTT.cpp @@ -12,7 +12,7 @@ String mqtt_tls_last_errorstr; int32_t mqtt_tls_last_error = 0; # ifdef ESP32 -ESPEasy_WiFiClientSecure* mqtt_tls; +BearSSL::WiFiClientSecure_light* mqtt_tls; # endif // ifdef ESP32 # ifdef ESP8266 BearSSL::WiFiClientSecure* mqtt_tls; diff --git a/src/src/Globals/MQTT.h b/src/src/Globals/MQTT.h index 4422fdfe6..4ac2500f2 100644 --- a/src/src/Globals/MQTT.h +++ b/src/src/Globals/MQTT.h @@ -11,11 +11,7 @@ # include # if FEATURE_MQTT_TLS -# ifdef ESP32 -# include "../Helpers/ESPEasy_WiFiClientSecure.h" -# else -# include -# endif + #include # endif // if FEATURE_MQTT_TLS // MQTT client @@ -23,14 +19,8 @@ extern WiFiClient mqtt; # if FEATURE_MQTT_TLS extern String mqtt_tls_last_errorstr; extern int32_t mqtt_tls_last_error; -# ifdef ESP32 -extern ESPEasy_WiFiClientSecure* mqtt_tls; -# endif // ifdef ESP32 -# ifdef ESP8266 -extern BearSSL::WiFiClientSecure* mqtt_tls; -extern BearSSL::X509List mqtt_X509List; - -# endif // ifdef ESP8266 +extern BearSSL::WiFiClientSecure_light* mqtt_tls; +//extern BearSSL::X509List mqtt_X509List; extern String mqtt_rootCA; extern String mqtt_fingerprint; diff --git a/src/src/Helpers/ESPEasy_WiFiClientSecure.cpp b/src/src/Helpers/ESPEasy_WiFiClientSecure.cpp deleted file mode 100644 index 038839829..000000000 --- a/src/src/Helpers/ESPEasy_WiFiClientSecure.cpp +++ /dev/null @@ -1,441 +0,0 @@ -#include "../Helpers/ESPEasy_WiFiClientSecure.h" - -/* - ESPEasy_WiFiClientSecure.cpp - Client Secure class for ESP32 - Copyright (c) 2016 Hristo Gochkov All right reserved. - Additions Copyright (C) 2017 Evandro Luis Copercini. - 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; either - version 2.1 of the License, or (at your option) any later version. - 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 St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifdef ESP32 -#include -#include -#include - - -// FIXME TD-er: Feels wrong this needs to be included here to use mbedtls_pem_write_buffer -#include -#include - -#include - -#undef connect -#undef write -#undef read - - -ESPEasy_WiFiClientSecure::ESPEasy_WiFiClientSecure() -{ - _connected = false; - - sslclient = new ESPEasy_sslclient_context; - ssl_init(sslclient); - sslclient->socket = -1; - sslclient->handshake_timeout = 120000; - _use_insecure = false; - _CA_cert = NULL; - _cert = NULL; - _private_key = NULL; - _pskIdent = NULL; - _psKey = NULL; - next = NULL; - _alpn_protos = NULL; -} - - -ESPEasy_WiFiClientSecure::ESPEasy_WiFiClientSecure(int sock) -{ - _connected = false; - _timeout = 0; - - sslclient = new ESPEasy_sslclient_context; - ssl_init(sslclient); - sslclient->socket = sock; - sslclient->handshake_timeout = 120000; - - if (sock >= 0) { - _connected = true; - } - - _CA_cert = NULL; - _cert = NULL; - _private_key = NULL; - _pskIdent = NULL; - _psKey = NULL; - next = NULL; - _alpn_protos = NULL; -} - -ESPEasy_WiFiClientSecure::~ESPEasy_WiFiClientSecure() -{ - stop(); - delete sslclient; -} - -ESPEasy_WiFiClientSecure &ESPEasy_WiFiClientSecure::operator=(const ESPEasy_WiFiClientSecure &other) -{ - stop(); - sslclient->socket = other.sslclient->socket; - _connected = other._connected; - return *this; -} - -void ESPEasy_WiFiClientSecure::stop() -{ - if (sslclient->socket >= 0) { - close(sslclient->socket); - sslclient->socket = -1; - _connected = false; - _peek = -1; - } - stop_ssl_socket(sslclient, _CA_cert, _cert, _private_key); -} - -int ESPEasy_WiFiClientSecure::connect(IPAddress ip, uint16_t port) -{ - if (_pskIdent && _psKey) - return connect(ip, port, _pskIdent, _psKey); - return connect(ip, port, _CA_cert, _cert, _private_key); -} - -int ESPEasy_WiFiClientSecure::connect(IPAddress ip, uint16_t port, int32_t timeout){ - _timeout = timeout; - return connect(ip, port); -} - -int ESPEasy_WiFiClientSecure::connect(const char *host, uint16_t port) -{ - if (_pskIdent && _psKey) - return connect(host, port, _pskIdent, _psKey); - return connect(host, port, _CA_cert, _cert, _private_key); -} - -int ESPEasy_WiFiClientSecure::connect(const char *host, uint16_t port, int32_t timeout){ - _timeout = timeout; - return connect(host, port); -} - -int ESPEasy_WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *CA_cert, const char *cert, const char *private_key) -{ - return connect(ip.toString().c_str(), port, CA_cert, cert, private_key); -} - -int ESPEasy_WiFiClientSecure::connect(const char *host, uint16_t port, const char *CA_cert, const char *cert, const char *private_key) -{ - if(_timeout > 0){ - sslclient->handshake_timeout = _timeout; - } - int ret = start_ssl_client(sslclient, host, port, _timeout, CA_cert, cert, private_key, NULL, NULL, _use_insecure, _alpn_protos); - _lastError = ret; - if (ret < 0) { - log_e("start_ssl_client: %d", ret); - stop(); - return 0; - } - _connected = true; - return 1; -} - -int ESPEasy_WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) { - return connect(ip.toString().c_str(), port, pskIdent, psKey); -} - -int ESPEasy_WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) { - log_v("start_ssl_client with PSK"); - if(_timeout > 0){ - sslclient->handshake_timeout = _timeout; - } - int ret = start_ssl_client(sslclient, host, port, _timeout, NULL, NULL, NULL, pskIdent, psKey, _use_insecure, _alpn_protos); - _lastError = ret; - if (ret < 0) { - log_e("start_ssl_client: %d", ret); - stop(); - return 0; - } - _connected = true; - return 1; -} - -int ESPEasy_WiFiClientSecure::peek(){ - if(_peek >= 0){ - return _peek; - } - _peek = timedRead(); - return _peek; -} - -size_t ESPEasy_WiFiClientSecure::write(uint8_t data) -{ - return write(&data, 1); -} - -int ESPEasy_WiFiClientSecure::read() -{ - uint8_t data = -1; - int res = read(&data, 1); - if (res < 0) { - return res; - } - return data; -} - -size_t ESPEasy_WiFiClientSecure::write(const uint8_t *buf, size_t size) -{ - if (!_connected) { - return 0; - } - int res = send_ssl_data(sslclient, buf, size); - if (res < 0) { - stop(); - res = 0; - } - return res; -} - -int ESPEasy_WiFiClientSecure::read(uint8_t *buf, size_t size) -{ - int peeked = 0; - int avail = available(); - if ((!buf && size) || avail <= 0) { - return -1; - } - if(!size){ - return 0; - } - if(_peek >= 0){ - buf[0] = _peek; - _peek = -1; - size--; - avail--; - if(!size || !avail){ - return 1; - } - buf++; - peeked = 1; - } - - int res = get_ssl_receive(sslclient, buf, size); - if (res < 0) { - stop(); - return peeked?peeked:res; - } - return res + peeked; -} - -int ESPEasy_WiFiClientSecure::available() -{ - int peeked = (_peek >= 0); - if (!_connected) { - return peeked; - } - int res = data_to_read(sslclient); - if (res < 0) { - stop(); - return peeked?peeked:res; - } - return res+peeked; -} - -uint8_t ESPEasy_WiFiClientSecure::connected() -{ - uint8_t dummy = 0; - read(&dummy, 0); - - return _connected; -} - -void ESPEasy_WiFiClientSecure::setInsecure() -{ - _CA_cert = NULL; - _cert = NULL; - _private_key = NULL; - _pskIdent = NULL; - _psKey = NULL; - _use_insecure = true; -} - -void ESPEasy_WiFiClientSecure::setCACert (const char *rootCA) -{ - _CA_cert = rootCA; -} - -void ESPEasy_WiFiClientSecure::setCertificate (const char *client_ca) -{ - _cert = client_ca; -} - -void ESPEasy_WiFiClientSecure::setPrivateKey (const char *private_key) -{ - _private_key = private_key; -} - -void ESPEasy_WiFiClientSecure::setPreSharedKey(const char *pskIdent, const char *psKey) { - _pskIdent = pskIdent; - _psKey = psKey; -} - -bool ESPEasy_WiFiClientSecure::verify(const char* fp, const char* domain_name) -{ - if (!sslclient) - return false; - - return verify_ssl_fingerprint(sslclient, fp, domain_name); -} - -char *ESPEasy_WiFiClientSecure::_streamLoad(Stream& stream, size_t size) { - char *dest = (char*)malloc(size+1); - if (!dest) { - return nullptr; - } - if (size != stream.readBytes(dest, size)) { - free(dest); - dest = nullptr; - return nullptr; - } - dest[size] = '\0'; - return dest; -} - -bool ESPEasy_WiFiClientSecure::loadCACert(Stream& stream, size_t size) { - char *dest = _streamLoad(stream, size); - bool ret = false; - if (dest) { - setCACert(dest); - ret = true; - } - return ret; -} - -bool ESPEasy_WiFiClientSecure::loadCertificate(Stream& stream, size_t size) { - char *dest = _streamLoad(stream, size); - bool ret = false; - if (dest) { - setCertificate(dest); - ret = true; - } - return ret; -} - -bool ESPEasy_WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) { - char *dest = _streamLoad(stream, size); - bool ret = false; - if (dest) { - setPrivateKey(dest); - ret = true; - } - return ret; -} - -int ESPEasy_WiFiClientSecure::lastError(char *buf, const size_t size) -{ - if (!_lastError) { - return 0; - } - mbedtls_strerror(_lastError, buf, size); - return _lastError; -} - -void ESPEasy_WiFiClientSecure::setHandshakeTimeout(unsigned long handshake_timeout) -{ - sslclient->handshake_timeout = handshake_timeout * 1000; -} - -void ESPEasy_WiFiClientSecure::setAlpnProtocols(const char **alpn_protos) -{ - _alpn_protos = alpn_protos; -} - -String ESPEasy_WiFiClientSecure::getPeerCertificateInfo(const mbedtls_x509_crt* peer) -{ - if (peer == nullptr) { - peer = getPeerCertificate(); - } - String res; - if (peer != nullptr) { - char buf[1024] = {0}; - int l = mbedtls_x509_crt_info (buf, sizeof(buf), "", peer); - if (l > 0) { - if (res.reserve(l)) { - for (int i = 0; i < l; ++i) { - res += buf[i]; - } - } - } - } - return res; -} - -int ESPEasy_WiFiClientSecure::getPeerCertificate(String& pem, String& subject, bool caRoot) -{ - const mbedtls_x509_crt *chain; - - chain = getPeerCertificate(); - - int error {0}; - bool done = false; - while (chain != nullptr && error == 0 && !done) { - if (!caRoot || (chain->ca_istrue && chain->next == nullptr)) { - done = true; - error = ESPEasy_WiFiClientSecure::cert_to_pem(chain, pem, subject); - } - chain = chain->next; - } - return error; -} - -int ESPEasy_WiFiClientSecure::cert_to_pem(const mbedtls_x509_crt *crt, String& pem, String& subject) -{ - const String pem_begin_crt = F("-----BEGIN CERTIFICATE-----\n"); - const String pem_end_crt = F("-----END CERTIFICATE-----"); - pem.clear(); - subject.clear(); - - const mbedtls_asn1_named_data* common_name = &crt->subject; - while (common_name != nullptr) { - // While iterating through DN objects, check for CN object - if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &common_name->oid)) - { - - subject.reserve(common_name->val.len); - const unsigned char* p = common_name->val.p; - for (auto i = 0; i < common_name->val.len; ++i, ++p) { - subject += static_cast(*p); - } - } - - // Fetch next DN object - common_name = common_name->next; - } - - size_t written{}; - - const size_t buffer_size = - pem_begin_crt.length() + - pem_end_crt.length() + - 2* crt->raw.len; - - std::vector pem_buf; - pem_buf.resize(buffer_size, 0u); - int ret = mbedtls_pem_write_buffer( - pem_begin_crt.c_str(), pem_end_crt.c_str(), - crt->raw.p, crt->raw.len, - &pem_buf[0], buffer_size, &written); - if (ret == 0) { - pem.reserve(written); - for (auto i = 0; i < written; ++i) { - pem += static_cast(pem_buf[i]); - } - } - return ret; -} -#endif \ No newline at end of file diff --git a/src/src/Helpers/ESPEasy_WiFiClientSecure.h b/src/src/Helpers/ESPEasy_WiFiClientSecure.h deleted file mode 100644 index aa0bcc625..000000000 --- a/src/src/Helpers/ESPEasy_WiFiClientSecure.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - ESPEasy_WiFiClientSecure.h - Base class that provides Client SSL to ESP32 - Copyright (c) 2011 Adrian McEwen. All right reserved. - Additions Copyright (C) 2017 Evandro Luis Copercini. - 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; either - version 2.1 of the License, or (at your option) any later version. - 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 St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - Almost literal copy of https://github.com/brokentoaster/arduino-esp32/blob/master/libraries/WiFiClientSecure/src/WiFiClientSecure.h - Changed into "ESPEasy" version to incorporate some fixes - for memory leaks not yet present in the "older" core versions. -*/ - -#ifdef ESP32 - -#ifndef ESPEASY_WiFiClientSecure_h -#define ESPEASY_WiFiClientSecure_h -#include -#include -#include -#include "../Helpers/ESPEasy_ssl_client.h" - -class ESPEasy_WiFiClientSecure : public WiFiClient -{ -protected: - ESPEasy_sslclient_context *sslclient; - - int _lastError = 0; - int _peek = -1; - int _timeout = 0; - bool _use_insecure; - const char *_CA_cert; - const char *_cert; - const char *_private_key; - const char *_pskIdent; // identity for PSK cipher suites - const char *_psKey; // key in hex for PSK cipher suites - const char **_alpn_protos; - -public: - ESPEasy_WiFiClientSecure *next; - ESPEasy_WiFiClientSecure(); - ESPEasy_WiFiClientSecure(int socket); - ~ESPEasy_WiFiClientSecure(); - int connect(IPAddress ip, uint16_t port); - int connect(IPAddress ip, uint16_t port, int32_t timeout); - int connect(const char *host, uint16_t port); - int connect(const char *host, uint16_t port, int32_t timeout); - int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); - int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key); - int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey); - int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey); - int peek(); - size_t write(uint8_t data); - size_t write(const uint8_t *buf, size_t size); - int available(); - int read(); - int read(uint8_t *buf, size_t size); - void flush() {} - void stop(); - uint8_t connected(); - int lastError(char *buf, const size_t size); - void clearLastError() { _lastError = 0; } - void setInsecure(); // Don't validate the chain, just accept whatever is given. VERY INSECURE! - void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex - void setCACert(const char *rootCA); - void setCertificate(const char *client_ca); - void setPrivateKey (const char *private_key); - bool loadCACert(Stream& stream, size_t size); - bool loadCertificate(Stream& stream, size_t size); - bool loadPrivateKey(Stream& stream, size_t size); - bool verify(const char* fingerprint, const char* domain_name); - void setHandshakeTimeout(unsigned long handshake_timeout); - void setAlpnProtocols(const char **alpn_protos); - String getPeerCertificateInfo(const mbedtls_x509_crt* crt = nullptr); - const mbedtls_x509_crt* getPeerCertificate() { return mbedtls_ssl_get_peer_cert(&sslclient->ssl_ctx); }; - bool getFingerprintSHA256(uint8_t sha256_result[32]) { return get_peer_fingerprint(sslclient, sha256_result); }; - - int getPeerCertificate(String& pem, String& subject, bool caRoot); - - // See: https://stackoverflow.com/a/63730321/8708166 - static int cert_to_pem(const mbedtls_x509_crt *crt, String& pem, String& subject); - - operator bool() - { - return connected(); - } - ESPEasy_WiFiClientSecure &operator=(const ESPEasy_WiFiClientSecure &other); - bool operator==(const bool value) - { - return bool() == value; - } - bool operator!=(const bool value) - { - return bool() != value; - } - bool operator==(const ESPEasy_WiFiClientSecure &); - bool operator!=(const ESPEasy_WiFiClientSecure &rhs) - { - return !this->operator==(rhs); - }; - - int socket() - { - return sslclient->socket = -1; - } - -private: - char *_streamLoad(Stream& stream, size_t size); - - //friend class WiFiServer; - using Print::write; -}; - -#endif -#endif \ No newline at end of file diff --git a/src/src/Helpers/ESPEasy_ssl_client.cpp b/src/src/Helpers/ESPEasy_ssl_client.cpp deleted file mode 100644 index 7e20438a5..000000000 --- a/src/src/Helpers/ESPEasy_ssl_client.cpp +++ /dev/null @@ -1,575 +0,0 @@ -#include "../Helpers/ESPEasy_ssl_client.h" - -/* Provide SSL/TLS functions to ESP32 with Arduino IDE -* -* Adapted from the ssl_client1 example of mbedtls. -* -* Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License. -* Additions Copyright (C) 2017 Evandro Luis Copercini, Apache 2.0 License. -*/ - -#ifdef ESP32 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && !defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) -# warning "Please configure IDF framework to include mbedTLS -> Enable pre-shared-key ciphersuites and activate at least one cipher" -#else - - -const char *ESPEasy_pers = "esp32-tls"; - -static int _handle_error(int err, const char * function, int line) -{ - if(err == -30848){ - return err; - } -#ifdef MBEDTLS_ERROR_C - char error_buf[100]; - mbedtls_strerror(err, error_buf, 100); - log_e("[%s():%d]: (%d) %s", function, line, err, error_buf); -#else - log_e("[%s():%d]: code %d", function, line, err); -#endif - return err; -} - -#define handle_error(e) _handle_error(e, __FUNCTION__, __LINE__) - - -ESPEasy_sslclient_context::ESPEasy_sslclient_context() -{ - mbedtls_ssl_init(&ssl_ctx); - mbedtls_ssl_config_init(&ssl_conf); - mbedtls_ctr_drbg_init(&drbg_ctx); - - mbedtls_entropy_init(&entropy_ctx); - mbedtls_x509_crt_init(&ca_cert); - mbedtls_x509_crt_init(&client_cert); - mbedtls_pk_init(&client_key); -} - - -ESPEasy_sslclient_context::~ESPEasy_sslclient_context() -{ - free_ca_cert(); - free_client_cert(); - free_client_key(); -} - - -void ESPEasy_sslclient_context::free_ca_cert() -{ - mbedtls_x509_crt_free(&ca_cert); -} - -void ESPEasy_sslclient_context::free_client_cert() -{ - mbedtls_x509_crt_free(&client_cert); -} - -void ESPEasy_sslclient_context::free_client_key() -{ - mbedtls_pk_free(&client_key); -} - - -void ssl_init(ESPEasy_sslclient_context *ssl_client) -{ - mbedtls_ssl_free(&ssl_client->ssl_ctx); - mbedtls_ssl_config_free(&ssl_client->ssl_conf); - mbedtls_ctr_drbg_free(&ssl_client->drbg_ctx); - - mbedtls_ssl_init(&ssl_client->ssl_ctx); - mbedtls_ssl_config_init(&ssl_client->ssl_conf); - mbedtls_ctr_drbg_init(&ssl_client->drbg_ctx); -} - - -int start_ssl_client(ESPEasy_sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure, const char **alpn_protos) -{ - char buf[512]; - int ret, flags; - int enable = 1; - log_v("Free internal heap before TLS %u", ESP.getFreeHeap()); - - if (rootCABuff == NULL && pskIdent == NULL && psKey == NULL && !insecure) { - return -1; - } - - log_v("Starting socket"); - ssl_client->socket = -1; - - ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ssl_client->socket < 0) { - log_e("ERROR opening socket"); - return ssl_client->socket; - } - - IPAddress srv((uint32_t)0); - if(!WiFiGenericClass::hostByName(host, srv)){ - return -1; - } - - fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK ); - struct sockaddr_in serv_addr; - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = srv; - serv_addr.sin_port = htons(port); - - if(timeout <= 0){ - timeout = 30000; // Milli seconds. - } - - fd_set fdset; - struct timeval tv; - FD_ZERO(&fdset); - FD_SET(ssl_client->socket, &fdset); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - - int res = lwip_connect(ssl_client->socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); - if (res < 0 && errno != EINPROGRESS) { - log_e("connect on fd %d, errno: %d, \"%s\"", ssl_client->socket, errno, strerror(errno)); - close(ssl_client->socket); - return -1; - } - - res = select(ssl_client->socket + 1, nullptr, &fdset, nullptr, timeout<0 ? nullptr : &tv); - if (res < 0) { - log_e("select on fd %d, errno: %d, \"%s\"", ssl_client->socket, errno, strerror(errno)); - close(ssl_client->socket); - return -1; - } else if (res == 0) { - log_i("select returned due to timeout %d ms for fd %d", timeout, ssl_client->socket); - close(ssl_client->socket); - return -1; - } else { - int sockerr; - socklen_t len = (socklen_t)sizeof(int); - res = getsockopt(ssl_client->socket, SOL_SOCKET, SO_ERROR, &sockerr, &len); - - if (res < 0) { - log_e("getsockopt on fd %d, errno: %d, \"%s\"", ssl_client->socket, errno, strerror(errno)); - close(ssl_client->socket); - return -1; - } - - if (sockerr != 0) { - log_e("socket error on fd %d, errno: %d, \"%s\"", ssl_client->socket, sockerr, strerror(sockerr)); - close(ssl_client->socket); - return -1; - } - } - - -#define ROE(x,msg) { if (((x)<0)) { log_e("LWIP Socket config of " msg " failed."); return -1; }} - ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)),"SO_RCVTIMEO"); - ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),"SO_SNDTIMEO"); - - ROE(lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)),"TCP_NODELAY"); - ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)),"SO_KEEPALIVE"); - - - - log_v("Seeding the random number generator"); - mbedtls_entropy_free(&ssl_client->entropy_ctx); - mbedtls_entropy_init(&ssl_client->entropy_ctx); - - ret = mbedtls_ctr_drbg_seed(&ssl_client->drbg_ctx, mbedtls_entropy_func, - &ssl_client->entropy_ctx, (const unsigned char *) ESPEasy_pers, strlen(ESPEasy_pers)); - if (ret < 0) { - return handle_error(ret); - } - - log_v("Setting up the SSL/TLS structure..."); - - if ((ret = mbedtls_ssl_config_defaults(&ssl_client->ssl_conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - return handle_error(ret); - } - - if (alpn_protos != NULL) { - log_v("Setting ALPN protocols"); - if ((ret = mbedtls_ssl_conf_alpn_protocols(&ssl_client->ssl_conf, alpn_protos) ) != 0) { - return handle_error(ret); - } - } - - // MBEDTLS_SSL_VERIFY_REQUIRED if a CA certificate is defined on Arduino IDE and - // MBEDTLS_SSL_VERIFY_NONE if not. - - if (insecure) { - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE); - log_i("WARNING: Skipping SSL Verification. INSECURE!"); - } else if (rootCABuff != NULL) { - log_v("Loading CA cert"); - mbedtls_x509_crt_init(&ssl_client->ca_cert); - mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); - ret = mbedtls_x509_crt_parse(&ssl_client->ca_cert, (const unsigned char *)rootCABuff, strlen(rootCABuff) + 1); - mbedtls_ssl_conf_ca_chain(&ssl_client->ssl_conf, &ssl_client->ca_cert, NULL); - //mbedtls_ssl_conf_verify(&ssl_client->ssl_ctx, my_verify, NULL ); - if (ret < 0) { - // free the ca_cert in the case parse failed, otherwise, the old ca_cert still in the heap memory, that lead to "out of memory" crash. - ssl_client->free_ca_cert(); - return handle_error(ret); - } - } else if (pskIdent != NULL && psKey != NULL) { - log_v("Setting up PSK"); - // convert PSK from hex to binary - if ((strlen(psKey) & 1) != 0 || strlen(psKey) > 2*MBEDTLS_PSK_MAX_LEN) { - log_e("pre-shared key not valid hex or too long"); - return -1; - } - unsigned char psk[MBEDTLS_PSK_MAX_LEN]; - size_t psk_len = strlen(psKey)/2; - for (int j=0; j= '0' && c <= '9') c -= '0'; - else if (c >= 'A' && c <= 'F') c -= 'A' - 10; - else if (c >= 'a' && c <= 'f') c -= 'a' - 10; - else return -1; - psk[j/2] = c<<4; - c = psKey[j+1]; - if (c >= '0' && c <= '9') c -= '0'; - else if (c >= 'A' && c <= 'F') c -= 'A' - 10; - else if (c >= 'a' && c <= 'f') c -= 'a' - 10; - else return -1; - psk[j/2] |= c; - } - // set mbedtls config - ret = mbedtls_ssl_conf_psk(&ssl_client->ssl_conf, psk, psk_len, - (const unsigned char *)pskIdent, strlen(pskIdent)); - if (ret != 0) { - log_e("mbedtls_ssl_conf_psk returned %d", ret); - return handle_error(ret); - } - } else { - return -1; - } - - if (!insecure && cli_cert != NULL && cli_key != NULL) { - mbedtls_x509_crt_init(&ssl_client->client_cert); - mbedtls_pk_init(&ssl_client->client_key); - - log_v("Loading CRT cert"); - - ret = mbedtls_x509_crt_parse(&ssl_client->client_cert, (const unsigned char *)cli_cert, strlen(cli_cert) + 1); - if (ret < 0) { - // free the client_cert in the case parse failed, otherwise, the old client_cert still in the heap memory, that lead to "out of memory" crash. - ssl_client->free_client_cert(); - return handle_error(ret); - } - - log_v("Loading private key"); - ret = mbedtls_pk_parse_key(&ssl_client->client_key, (const unsigned char *)cli_key, strlen(cli_key) + 1, NULL, 0); - - if (ret != 0) { - return handle_error(ret); - } - - mbedtls_ssl_conf_own_cert(&ssl_client->ssl_conf, &ssl_client->client_cert, &ssl_client->client_key); - } - - log_v("Setting hostname for TLS session..."); - - // Hostname set here should match CN in server certificate - if((ret = mbedtls_ssl_set_hostname(&ssl_client->ssl_ctx, host)) != 0){ - return handle_error(ret); - } - - mbedtls_ssl_conf_rng(&ssl_client->ssl_conf, mbedtls_ctr_drbg_random, &ssl_client->drbg_ctx); - - if ((ret = mbedtls_ssl_setup(&ssl_client->ssl_ctx, &ssl_client->ssl_conf)) != 0) { - return handle_error(ret); - } - - mbedtls_ssl_set_bio(&ssl_client->ssl_ctx, &ssl_client->socket, mbedtls_net_send, mbedtls_net_recv, NULL ); - - log_v("Performing the SSL/TLS handshake..."); - unsigned long handshake_start_time=millis(); - while ((ret = mbedtls_ssl_handshake(&ssl_client->ssl_ctx)) != 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - // ++++++++++ ADDED TO FIX MEMORY LEAK ON FAILED CONNECTION ++++++++++ - ssl_client->free_client_key(); - ssl_client->free_ca_cert(); - ssl_client->free_client_cert(); - // ++++++++++ END ++++++++++ - return handle_error(ret); - } - if ((millis()-handshake_start_time) > ssl_client->handshake_timeout) { - // ++++++++++ ADDED TO FIX MEMORY LEAK ON FAILED CONNECTION ++++++++++ - ssl_client->free_client_key(); - ssl_client->free_ca_cert(); - ssl_client->free_client_cert(); - // ++++++++++ END ++++++++++ - return -1; - } - vTaskDelay(2);//2 ticks - } - - - if (cli_cert != NULL && cli_key != NULL) { - log_d("Protocol is %s Ciphersuite is %s", mbedtls_ssl_get_version(&ssl_client->ssl_ctx), mbedtls_ssl_get_ciphersuite(&ssl_client->ssl_ctx)); - if ((ret = mbedtls_ssl_get_record_expansion(&ssl_client->ssl_ctx)) >= 0) { - log_d("Record expansion is %d", ret); - } else { - log_w("Record expansion is unknown (compression)"); - } - } - - log_v("Verifying peer X.509 certificate..."); - - if ((flags = mbedtls_ssl_get_verify_result(&ssl_client->ssl_ctx)) != 0) { - memset(buf, 0, sizeof(buf)); - mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); - log_e("Failed to verify peer certificate! verification info: %s", buf); - stop_ssl_socket(ssl_client, rootCABuff, cli_cert, cli_key); //It's not safe continue. - // ++++++++++ ADDED TO FIX MEMORY LEAK ON FAILED CONNECTION ++++++++++ - ssl_client->free_client_key(); - ssl_client->free_ca_cert(); - ssl_client->free_client_cert(); - // ++++++++++ END ++++++++++ - - return handle_error(ret); - } else { - log_v("Certificate verified."); - } - - ssl_client->free_ca_cert(); - ssl_client->free_client_cert(); - ssl_client->free_client_key(); - - log_v("Free internal heap after TLS %u", ESP.getFreeHeap()); - - return ssl_client->socket; -} - - -void stop_ssl_socket(ESPEasy_sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key) -{ - log_v("Cleaning SSL connection."); - - if (ssl_client->socket >= 0) { - close(ssl_client->socket); - ssl_client->socket = -1; - } - - mbedtls_ssl_free(&ssl_client->ssl_ctx); - mbedtls_ssl_config_free(&ssl_client->ssl_conf); - mbedtls_ctr_drbg_free(&ssl_client->drbg_ctx); - mbedtls_entropy_free(&ssl_client->entropy_ctx); - ssl_client->free_ca_cert(); - ssl_client->free_client_cert(); - ssl_client->free_client_key(); -} - - -int data_to_read(ESPEasy_sslclient_context *ssl_client) -{ - int ret, res; - ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, NULL, 0); - //log_e("RET: %i",ret); //for low level debug - res = mbedtls_ssl_get_bytes_avail(&ssl_client->ssl_ctx); - //log_e("RES: %i",res); //for low level debug - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) { - return handle_error(ret); - } - - return res; -} - -int send_ssl_data(ESPEasy_sslclient_context *ssl_client, const uint8_t *data, size_t len) -{ - log_v("Writing HTTP request with %d bytes...", len); //for low level debug - int ret = -1; - - while ((ret = mbedtls_ssl_write(&ssl_client->ssl_ctx, data, len)) <= 0) { - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret < 0) { - log_v("Handling error %d", ret); //for low level debug - return handle_error(ret); - } - //wait for space to become available - vTaskDelay(2); - } - - return ret; -} - -int get_ssl_receive(ESPEasy_sslclient_context *ssl_client, uint8_t *data, int length) -{ - //log_d( "Reading HTTP response..."); //for low level debug - int ret = -1; - - ret = mbedtls_ssl_read(&ssl_client->ssl_ctx, data, length); - - //log_v( "%d bytes read", ret); //for low level debug - return ret; -} - -static bool parseHexNibble(char pb, uint8_t* res) -{ - if (pb >= '0' && pb <= '9') { - *res = (uint8_t) (pb - '0'); return true; - } else if (pb >= 'a' && pb <= 'f') { - *res = (uint8_t) (pb - 'a' + 10); return true; - } else if (pb >= 'A' && pb <= 'F') { - *res = (uint8_t) (pb - 'A' + 10); return true; - } - return false; -} - -// Compare a name from certificate and domain name, return true if they match -static bool matchName(const std::string& name, const std::string& domainName) -{ - size_t wildcardPos = name.find('*'); - if (wildcardPos == std::string::npos) { - // Not a wildcard, expect an exact match - return name == domainName; - } - - size_t firstDotPos = name.find('.'); - if (wildcardPos > firstDotPos) { - // Wildcard is not part of leftmost component of domain name - // Do not attempt to match (rfc6125 6.4.3.1) - return false; - } - if (wildcardPos != 0 || firstDotPos != 1) { - // Matching of wildcards such as baz*.example.com and b*z.example.com - // is optional. Maybe implement this in the future? - return false; - } - size_t domainNameFirstDotPos = domainName.find('.'); - if (domainNameFirstDotPos == std::string::npos) { - return false; - } - return domainName.substr(domainNameFirstDotPos) == name.substr(firstDotPos); -} - -// Verifies certificate provided by the peer to match specified SHA256 fingerprint -bool verify_ssl_fingerprint(ESPEasy_sslclient_context *ssl_client, const char* fp, const char* domain_name) -{ - // Convert hex string to byte array - uint8_t fingerprint_local[32]; - int len = strlen(fp); - int pos = 0; - for (size_t i = 0; i < sizeof(fingerprint_local); ++i) { - while (pos < len && ((fp[pos] == ' ') || (fp[pos] == ':'))) { - ++pos; - } - if (pos > len - 2) { - log_d("pos:%d len:%d fingerprint too short", pos, len); - return false; - } - uint8_t high, low; - if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) { - log_d("pos:%d len:%d invalid hex sequence: %c%c", pos, len, fp[pos], fp[pos+1]); - return false; - } - pos += 2; - fingerprint_local[i] = low | (high << 4); - } - - // Calculate certificate's SHA256 fingerprint - uint8_t fingerprint_remote[32]; - if(!get_peer_fingerprint(ssl_client, fingerprint_remote)) - return false; - - // Check if fingerprints match - if (memcmp(fingerprint_local, fingerprint_remote, 32)) - { - log_d("fingerprint doesn't match"); - return false; - } - - // Additionally check if certificate has domain name if provided - if (domain_name) - return verify_ssl_dn(ssl_client, domain_name); - else - return true; -} - -bool get_peer_fingerprint(ESPEasy_sslclient_context *ssl_client, uint8_t sha256[32]) -{ - if (!ssl_client) { - log_d("Invalid ssl_client pointer"); - return false; - }; - - const mbedtls_x509_crt* crt = mbedtls_ssl_get_peer_cert(&ssl_client->ssl_ctx); - if (!crt) { - log_d("Failed to get peer cert."); - return false; - }; - - mbedtls_sha256_context sha256_ctx; - mbedtls_sha256_init(&sha256_ctx); - mbedtls_sha256_starts(&sha256_ctx, false); - mbedtls_sha256_update(&sha256_ctx, crt->raw.p, crt->raw.len); - mbedtls_sha256_finish(&sha256_ctx, sha256); - - return true; -} - -// Checks if peer certificate has specified domain in CN or SANs -bool verify_ssl_dn(ESPEasy_sslclient_context *ssl_client, const char* domain_name) -{ - log_d("domain name: '%s'", (domain_name)?domain_name:"(null)"); - std::string domain_name_str(domain_name); - std::transform(domain_name_str.begin(), domain_name_str.end(), domain_name_str.begin(), ::tolower); - - // Get certificate provided by the peer - const mbedtls_x509_crt* crt = mbedtls_ssl_get_peer_cert(&ssl_client->ssl_ctx); - - // Check for domain name in SANs - const mbedtls_x509_sequence* san = &crt->subject_alt_names; - while (san != nullptr) - { - std::string san_str((const char*)san->buf.p, san->buf.len); - std::transform(san_str.begin(), san_str.end(), san_str.begin(), ::tolower); - - if (matchName(san_str, domain_name_str)) - return true; - - log_d("SAN '%s': no match", san_str.c_str()); - - // Fetch next SAN - san = san->next; - } - - // Check for domain name in CN - const mbedtls_asn1_named_data* common_name = &crt->subject; - while (common_name != nullptr) - { - // While iterating through DN objects, check for CN object - if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &common_name->oid)) - { - std::string common_name_str((const char*)common_name->val.p, common_name->val.len); - - if (matchName(common_name_str, domain_name_str)) - return true; - - log_d("CN '%s': not match", common_name_str.c_str()); - } - - // Fetch next DN object - common_name = common_name->next; - } - - return false; -} -#endif -#endif \ No newline at end of file diff --git a/src/src/Helpers/ESPEasy_ssl_client.h b/src/src/Helpers/ESPEasy_ssl_client.h deleted file mode 100644 index 7f6eebf03..000000000 --- a/src/src/Helpers/ESPEasy_ssl_client.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Provide SSL/TLS functions to ESP32 with Arduino IDE - * by Evandro Copercini - 2017 - Apache 2.0 License - */ -#ifdef ESP32 -#ifndef ESPEASY_ARD_SSL_H -#define ESPEASY_ARD_SSL_H -#include -#include -#include -#include -#include -#include -#include - -typedef struct ESPEasy_sslclient_context { - - ESPEasy_sslclient_context(); - - ~ESPEasy_sslclient_context(); - - void free_ca_cert(); - void free_client_cert(); - void free_client_key(); - - int socket = -1; - mbedtls_ssl_context ssl_ctx; - mbedtls_ssl_config ssl_conf; - - mbedtls_ctr_drbg_context drbg_ctx; - mbedtls_entropy_context entropy_ctx; - - mbedtls_x509_crt ca_cert; - mbedtls_x509_crt client_cert; - mbedtls_pk_context client_key; - - unsigned long handshake_timeout = 120000; -} ESPEasy_sslclient_context; - - -void ssl_init(ESPEasy_sslclient_context *ssl_client); -int start_ssl_client(ESPEasy_sslclient_context *ssl_client, const char *host, uint32_t port, int timeout, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey, bool insecure, const char **alpn_protos); -void stop_ssl_socket(ESPEasy_sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key); -int data_to_read(ESPEasy_sslclient_context *ssl_client); -int send_ssl_data(ESPEasy_sslclient_context *ssl_client, const uint8_t *data, size_t len); -int get_ssl_receive(ESPEasy_sslclient_context *ssl_client, uint8_t *data, int length); -bool verify_ssl_fingerprint(ESPEasy_sslclient_context *ssl_client, const char* fp, const char* domain_name); -bool verify_ssl_dn(ESPEasy_sslclient_context *ssl_client, const char* domain_name); -bool get_peer_fingerprint(ESPEasy_sslclient_context *ssl_client, uint8_t sha256[32]); - -#endif -#endif \ No newline at end of file diff --git a/src/src/WebServer/ControllerPage.cpp b/src/src/WebServer/ControllerPage.cpp index 096a5cb06..50e769c79 100644 --- a/src/src/WebServer/ControllerPage.cpp +++ b/src/src/WebServer/ControllerPage.cpp @@ -490,6 +490,9 @@ void handle_controllers_ControllerSettingsPage(controllerIndex_t controllerindex } else { LoadControllerSettings(controllerindex, *ControllerSettings); + // FIXME TD-er: Implement retrieval of certificate + /* + addFormSubHeader(F("Peer Certificate")); { @@ -522,10 +525,8 @@ void handle_controllers_ControllerSettingsPage(controllerIndex_t controllerindex int error {0}; while (chain != nullptr && error == 0) { - /* - const bool mustShow = !chain->ca_istrue || chain->next == nullptr; - if (mustShow) { - */ +// const bool mustShow = !chain->ca_istrue || chain->next == nullptr; +// if (mustShow) { String pem, subject; error = ESPEasy_WiFiClientSecure::cert_to_pem(chain, pem, subject); { @@ -567,6 +568,7 @@ void handle_controllers_ControllerSettingsPage(controllerIndex_t controllerindex chain = chain->next; } } + */ } } #endif