TLS fix ECDSA and add 'SetOption165 1' to enable ECDSA in addition to RSA (#24000)

This commit is contained in:
s-hadinger 2025-10-11 19:15:41 +02:00 committed by GitHub
parent 774b01fdcd
commit f6a488a84c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 38 additions and 5 deletions

View File

@ -29,6 +29,7 @@ All notable changes to this project will be documented in this file.
### Fixed
- Berry fixed 'be_top is non zero' warning when calling C mapped functions (#23989)
- Berry fixed 'be_top is non zero' when `Br` command fails (#23990)
- TLS fix ECDSA and add `SetOption165 1` to enable ECDSA in addition to RSA
## [15.0.1.4] 20251002
### Added

View File

@ -930,8 +930,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
}
@ -986,6 +986,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();

View File

@ -120,6 +120,9 @@ class WiFiClientSecure_light : public WiFiClient {
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;
}
@ -131,6 +134,9 @@ class WiFiClientSecure_light : public WiFiClient {
}
void setInsecure();
void setECDSA(bool ecdsa) {
_rsa_only = !ecdsa;
};
void setDomainName(const char * domain) {
_domain = domain;

View File

@ -199,7 +199,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t no_export_energy_today : 1; // bit 16 (v14.3.0.7) - SetOption162 - (Energy) Do not add export energy to energy today (1)
uint32_t gui_device_name : 1; // bit 17 (v14.4.1.1) - SetOption163 - GUI_NOSHOW_DEVICENAME - (GUI) Disable display of GUI device name (1)
uint32_t wizmote_enabled : 1; // bit 18 (v14.4.1.4) - SetOption164 - (WizMote) Enable WiZ Smart Remote support (1)
uint32_t spare19 : 1; // bit 19
uint32_t tls_use_ecdsa : 1; // bit 19 (v15.0.1.0) - SetOption165 - (TLS) Enable ECDSA validation in addition to RSA
uint32_t spare20 : 1; // bit 20
uint32_t spare21 : 1; // bit 21
uint32_t spare22 : 1; // bit 22

View File

@ -173,8 +173,9 @@
#define MQTT_INDEX_SEPARATOR false // [SetOption64] Enable "_" instead of "-" as sensor index separator
#define MQTT_TUYA_RECEIVED false // [SetOption66] Enable TuyaMcuReceived messages over Mqtt
#define MQTT_ONLY_JSON_OUTPUT false // [SetOption90] Disable non-json messages
#define MQTT_TLS_ENABLED false // [SetOption103] Enable TLS mode (requires TLS version)
#define MQTT_TLS_FINGERPRINT false // [SetOption132] Force TLS fingerprint validation instead of CA (requires TLS version)
#define MQTT_TLS_ENABLED false // [SetOption103] Enable TLS mode
#define MQTT_TLS_FINGERPRINT false // [SetOption132] Force TLS fingerprint validation instead of CA
#define MQTT_TLS_ECDSA false // [SetOption165] Enable TLS ECDSA validation in addition to RSA, false by default but automatically set to 'true' in case of a cipher error '296'
// -- HTTP ----------------------------------------
#define WEB_SERVER 2 // [WebServer] Web server (0 = Off, 1 = Start as User, 2 = Start as Admin)

View File

@ -1448,6 +1448,7 @@ void SettingsDefaultSet2(void) {
// Matter
flag6.matter_enabled |= MATTER_ENABLED;
flag6.tls_use_ecdsa |= MQTT_TLS_ECDSA;
Settings->flag = flag;
Settings->flag2 = flag2;

View File

@ -262,6 +262,7 @@ void MqttInit(void) {
if (!Settings->flag5.tls_use_fingerprint) {
tlsClient->setTrustAnchor(Tasmota_TA, nitems(Tasmota_TA));
}
tlsClient->setECDSA(Settings->flag6.tls_use_ecdsa);
MqttClient.setClient(*tlsClient);
} else {
@ -1391,6 +1392,14 @@ void MqttReconnect(void) {
120 : 376 : BR_ALERT_NO_APPLICATION_PROTOCOL
*/
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connection error: %d"), tlsClient->getLastError());
if (tlsClient->getLastError() == 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
Settings->flag6.tls_use_ecdsa = true;
tlsClient->setECDSA(Settings->flag6.tls_use_ecdsa);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS now enabling ECDSA 'SetOption165 1'"), tlsClient->getLastError());
}
}
#endif
/*
@ -1408,6 +1417,18 @@ void MqttReconnect(void) {
*/
MqttDisconnected(MqttClient.state());
}
#ifdef USE_MQTT_TLS
if (Mqtt.mqtt_tls) {
int32_t cipher_suite = tlsClient->getLastCipherSuite();
if (BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 == cipher_suite) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "TLS cipher suite: %s"), PSTR("ECDHE_RSA_AES_128_GCM_SHA256"));
} else if (BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 == cipher_suite) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "TLS cipher suite: %s"), PSTR("ECDHE_ECDSA_AES_128_GCM_SHA256"));
} else if (0 != cipher_suite) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "TLS cipher suite: 0x%04X"), cipher_suite);
}
}
#endif // USE_MQTT_TLS
}
void MqttCheck(void) {