diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp index 8b11073f2..06cc2bf2b 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp @@ -196,7 +196,7 @@ void WiFiClientSecure_light::_clear() { _eng = nullptr; _iobuf_in = nullptr; _iobuf_out = nullptr; - setBufferSizes(1024, 1024); // reasonable minimum + setBufferSizes(2048, 2048); // reasonable minimum _handshake_done = false; _last_error = 0; _recvapp_buf = nullptr; @@ -943,8 +943,8 @@ extern "C" { br_ssl_engine_set_ghash(&cc->eng, &br_ghash_ctmul32); // we support only P256 EC curve for AWS IoT, no EC curve for Letsencrypt unless forced - br_ssl_engine_set_ec(&cc->eng, &br_ec_p256_m15); // TODO -#ifndef ESP8266 + br_ssl_engine_set_ec(&cc->eng, &br_ec_p256_m15); +#ifdef ESP32 br_ssl_engine_set_ecdsa(&cc->eng, &br_ecdsa_i15_vrfy_asn1); #endif } @@ -999,6 +999,9 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) { br_x509_minimal_init(x509_minimal, &br_sha256_vtable, _ta_P, _ta_size); br_x509_minimal_set_rsa(x509_minimal, br_ssl_engine_get_rsavrfy(_eng)); br_x509_minimal_set_hash(x509_minimal, br_sha256_ID, &br_sha256_vtable); +#ifdef ESP32 + br_x509_minimal_set_ecdsa(x509_minimal, &br_ec_all_m15, &br_ecdsa_i15_vrfy_asn1); +#endif // ESP32 br_ssl_engine_set_x509(_eng, &x509_minimal->vtable); uint32_t now = UtcTime(); uint32_t cfg_time = CfgTime(); diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h index fe9fe4f98..f464fcda3 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h @@ -127,6 +127,9 @@ class WiFiClientSecure_light : public NetworkClient { return br_ssl_engine_last_error(_eng); } } + int32_t getLastCipherSuite(void) { + return _eng->session.cipher_suite; + } inline void setLastError(int32_t err) { _last_error = err; } @@ -138,6 +141,9 @@ class WiFiClientSecure_light : public NetworkClient { } void setInsecure(); + void setECDSA(bool ecdsa) { + _rsa_only = !ecdsa; + }; void setDomainName(const char * domain) { _domain = domain; diff --git a/src/src/ESPEasyCore/Controller.cpp b/src/src/ESPEasyCore/Controller.cpp index 95378bb42..036066039 100644 --- a/src/src/ESPEasyCore/Controller.cpp +++ b/src/src/ESPEasyCore/Controller.cpp @@ -179,9 +179,9 @@ bool MQTTConnect(controllerIndex_t controller_idx) MakeControllerSettings(ControllerSettings); // -V522 if (!AllocatedControllerSettings()) { - #ifndef BUILD_MINIMAL_OTA + # ifndef BUILD_NO_DEBUG addLog(LOG_LEVEL_ERROR, F("MQTT : Cannot connect, out of RAM")); - #endif + # endif // ifndef BUILD_NO_DEBUG return false; } LoadControllerSettings(controller_idx, *ControllerSettings); @@ -210,8 +210,6 @@ bool MQTTConnect(controllerIndex_t controller_idx) uint16_t mqttPort = ControllerSettings->Port; - mqtt_tls_last_errorstr.clear(); - mqtt_tls_last_error = 0; const TLS_types TLS_type = ControllerSettings->TLStype(); if ((TLS_type != TLS_types::NoTLS) && (nullptr == mqtt_tls)) { @@ -234,6 +232,8 @@ bool MQTTConnect(controllerIndex_t controller_idx) mqtt_tls->setUtcTime_fcn(getUnixTime); mqtt_tls->setCfgTime_fcn(get_build_unixtime); } + mqtt_tls_last_errorstr.clear(); + mqtt_tls_last_error = 0; } switch (TLS_type) { @@ -281,10 +281,10 @@ bool MQTTConnect(controllerIndex_t controller_idx) LoadCertificate(ControllerSettings->getCertificateFilename(), mqtt_rootCA); if (mqtt_rootCA.isEmpty()) { - // Fingerprint must be of some minimal length to continue. - mqtt_tls_last_errorstr = F("MQTT : No TLS root CA"); - addLog(LOG_LEVEL_ERROR, mqtt_tls_last_errorstr); - return false; + // Fingerprint must be of some minimal length to continue. + mqtt_tls_last_errorstr = F("MQTT : No TLS root CA"); + addLog(LOG_LEVEL_ERROR, mqtt_tls_last_errorstr); + return false; } @@ -349,6 +349,15 @@ bool MQTTConnect(controllerIndex_t controller_idx) ? WiFiEventData.getSuggestedTimeout(Settings.Protocol[controller_idx], ControllerSettings->ClientTimeout) : ControllerSettings->ClientTimeout; + if (mqtt_tls_last_error == 296) { + // in this special case of cipher mismatch, we force enable ECDSA + // this would be the case for newer letsencrypt certificates now defaulting + // to EC certificates requiring ECDSA instead of RSA + mqtt_tls->setECDSA(true); + addLog(LOG_LEVEL_INFO, F("MQTT : TLS now enabling ECDSA")); + } + + # ifdef MUSTFIX_CLIENT_TIMEOUT_IN_SECONDS // See: https://github.com/espressif/arduino-esp32/pull/6676 @@ -361,7 +370,7 @@ bool MQTTConnect(controllerIndex_t controller_idx) # ifdef ESP8266 mqtt_tls->setBufferSizes(1024, 1024); - # endif // ifdef ESP8266 +# endif // ifdef ESP8266 MQTTclient.setClient(*mqtt_tls); MQTTclient.setKeepAlive(ControllerSettings->KeepAliveTime ? ControllerSettings->KeepAliveTime : CONTROLLER_KEEP_ALIVE_TIME_DFLT); MQTTclient.setSocketTimeout(timeout); @@ -460,14 +469,29 @@ bool MQTTConnect(controllerIndex_t controller_idx) # ifdef ESP32 mqtt_tls_last_error = mqtt_tls->getLastError(); mqtt_tls->clearLastError(); + mqtt_tls_last_cipher_suite = mqtt_tls->getLastCipherSuite(); # endif // ifdef ESP32 - // mqtt_tls_last_errorstr = buf; - if (mqtt_tls_last_error == ERR_OOM) mqtt_tls_last_errorstr = F("OutOfMemory"); - if (mqtt_tls_last_error == ERR_CANT_RESOLVE_IP) mqtt_tls_last_errorstr = F("Can't resolve IP"); - if (mqtt_tls_last_error == ERR_TCP_CONNECT) mqtt_tls_last_errorstr = F("TCP Connect error"); -// if (mqtt_tls_last_error == ERR_MISSING_CA) mqtt_tls_last_errorstr = F("Missing CA"); - if (mqtt_tls_last_error == ERR_TLS_TIMEOUT) mqtt_tls_last_errorstr = F("TLS Timeout"); + // mqtt_tls_last_errorstr = buf; + if (mqtt_tls_last_error == ERR_OOM) { mqtt_tls_last_errorstr = F("OutOfMemory"); } + + if (mqtt_tls_last_error == ERR_CANT_RESOLVE_IP) { mqtt_tls_last_errorstr = F("Can't resolve IP"); } + + if (mqtt_tls_last_error == ERR_TCP_CONNECT) { mqtt_tls_last_errorstr = F("TCP Connect error"); } + + // if (mqtt_tls_last_error == ERR_MISSING_CA) mqtt_tls_last_errorstr = F("Missing CA"); + if (mqtt_tls_last_error == ERR_TLS_TIMEOUT) { mqtt_tls_last_errorstr = F("TLS Timeout"); } + +# ifndef BUILD_NO_DEBUG + + if (BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 == mqtt_tls_last_cipher_suite) { + addLog(LOG_LEVEL_DEBUG, F("TLS cipher suite: ECDHE_RSA_AES_128_GCM_SHA256")); + } else if (BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 == mqtt_tls_last_cipher_suite) { + addLog(LOG_LEVEL_DEBUG, F("TLS cipher suite: ECDHE_ECDSA_AES_128_GCM_SHA256")); + } else if (0 != mqtt_tls_last_cipher_suite) { + addLog(LOG_LEVEL_DEBUG, strformat(F("TLS cipher suite: 0x%04X"), mqtt_tls_last_cipher_suite)); + } +# endif // ifndef BUILD_NO_DEBUG } # ifdef ESP32 @@ -502,12 +526,12 @@ bool MQTTConnect(controllerIndex_t controller_idx) /* if (mqtt_tls != nullptr) { if (!mqtt_tls->verify( - fp.c_str(), - dn.isEmpty() ? nullptr : dn.c_str())) + fp.c_str(), + dn.isEmpty() ? nullptr : dn.c_str())) { - mqtt_tls_last_errorstr += F("TLS Fingerprint does not match"); - addLog(LOG_LEVEL_INFO, mqtt_fingerprint); - MQTTresult = false; + mqtt_tls_last_errorstr += F("TLS Fingerprint does not match"); + addLog(LOG_LEVEL_INFO, mqtt_fingerprint); + MQTTresult = false; } } */ @@ -601,10 +625,12 @@ void MQTTparseSystemVariablesAndSubscribe(String subscribeTo) { if (!subscribeTo.isEmpty()) { MQTTclient.subscribe(subscribeTo.c_str()); +# ifndef BUILD_NO_DEBUG if (loglevelActiveFor(LOG_LEVEL_INFO)) { addLogMove(LOG_LEVEL_INFO, concat(F("Subscribed to: "), subscribeTo)); } +# endif // ifndef BUILD_NO_DEBUG } } @@ -665,7 +691,7 @@ bool MQTTCheck(controllerIndex_t controller_idx) #ifdef USES_ESPEASY_NOW if (!MQTTclient.connected()) { if (ControllerSettings->enableESPEasyNowFallback()) { - return true; + return true; } } #endif @@ -808,6 +834,7 @@ void SendStatus(struct EventStruct *event, const String& status) } #if FEATURE_MQTT + controllerIndex_t firstEnabledMQTT_ControllerIndex() { for (controllerIndex_t i = 0; i < CONTROLLER_MAX; ++i) { protocolIndex_t ProtocolIndex = getProtocolIndex_from_ControllerIndex(i); @@ -850,11 +877,12 @@ bool MQTTpublish(controllerIndex_t controller_idx, } String topic_str; String payload_str; + if (!reserve_special(topic_str, strlen_P(topic)) || !reserve_special(payload_str, strlen_P(payload))) { return false; } - topic_str = topic; + topic_str = topic; payload_str = payload; bool success = false; @@ -867,7 +895,7 @@ bool MQTTpublish(controllerIndex_t controller_idx, MQTTDelayHandler->addToQueue( std::unique_ptr( new (ptr) MQTT_queue_element( - controller_idx, taskIndex, + controller_idx, taskIndex, std::move(topic_str), std::move(payload_str), retained, callbackTask))); @@ -897,7 +925,7 @@ bool MQTTpublish(controllerIndex_t controller_idx, void *ptr = special_calloc(1, size); if (ptr != nullptr) { - success = + success = MQTTDelayHandler->addToQueue( std::unique_ptr( new (ptr) MQTT_queue_element( @@ -957,6 +985,7 @@ void MQTTStatus(struct EventStruct *event, const String& status) } # if FEATURE_MQTT_TLS + bool GetTLSfingerprint(String& fp) { # ifdef ESP32 @@ -1001,7 +1030,7 @@ bool GetTLS_Certificate(String& cert, bool caRoot) String subject; if (mqtt_tls->getPeerCertificate(cert, subject, caRoot) == 0) { - return true; + return true; } } */ @@ -1013,19 +1042,17 @@ bool GetTLS_Certificate(String& cert, bool caRoot) #endif // if FEATURE_MQTT - /*********************************************************************************************\ * send specific sensor task data, effectively calling PluginCall(PLUGIN_READ...) \*********************************************************************************************/ -void SensorSendTask(struct EventStruct *event, unsigned long timestampUnixTime) -{ +void SensorSendTask(struct EventStruct *event, unsigned long timestampUnixTime) { SensorSendTask(event, timestampUnixTime, millis()); } void SensorSendTask(struct EventStruct *event, unsigned long timestampUnixTime, unsigned long lasttimer) { - if (!validTaskIndex(event->TaskIndex)) { - return; + if (!validTaskIndex(event->TaskIndex)) { + return; } // FIXME TD-er: Should a 'disabled' task be rescheduled? diff --git a/src/src/Globals/MQTT.cpp b/src/src/Globals/MQTT.cpp index f7df2d332..1c315f6f2 100644 --- a/src/src/Globals/MQTT.cpp +++ b/src/src/Globals/MQTT.cpp @@ -18,6 +18,7 @@ BearSSL::WiFiClientSecure_light*mqtt_tls{}; BearSSL::WiFiClientSecure*mqtt_tls; BearSSL::X509List mqtt_X509List; # endif // ifdef ESP8266 +int32_t mqtt_tls_last_cipher_suite{}; String mqtt_rootCA; String mqtt_fingerprint; # endif // if FEATURE_MQTT_TLS diff --git a/src/src/Globals/MQTT.h b/src/src/Globals/MQTT.h index 59bf490f4..219bf32ad 100644 --- a/src/src/Globals/MQTT.h +++ b/src/src/Globals/MQTT.h @@ -23,6 +23,7 @@ extern WiFiClient mqtt; extern String mqtt_tls_last_errorstr; extern int32_t mqtt_tls_last_error; extern BearSSL::WiFiClientSecure_light*mqtt_tls; +extern int32_t mqtt_tls_last_cipher_suite; // extern BearSSL::X509List mqtt_X509List;