From 676a62fecb8d1c07ff31a6c5662a418a74810e04 Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 12 Jun 2024 12:16:48 -0500 Subject: [PATCH] [OTA] Add Github Digicert cert hash check (#1965) to avoid loading a deprecated certificate --- main/User_config.h | 7 ++--- main/ZboardTheengs.ino | 3 +- main/certs/default_ota_cert.h | 2 +- main/main.ino | 52 +++++++++++++++++++++-------------- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/main/User_config.h b/main/User_config.h index 0da171a..7269422 100644 --- a/main/User_config.h +++ b/main/User_config.h @@ -82,12 +82,7 @@ # endif #endif -#if defined(ESP8266) || defined(ESP32) // for nodemcu, weemos and esp8266 //# define ESPWifiManualSetup true //uncomment you don't want to use wifimanager for your credential settings on ESP -#else // for arduino boards -const byte ip[] = {192, 168, 1, 99}; -const byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95}; //W5100 ethernet shield MAC address -#endif //#define ESP32_ETHERNET=true // Uncomment to use Ethernet module on ESP32 Ethernet gateway and adapt the settings to your board below, the default parameter are for OLIMEX ESP32 gateway #ifdef ESP32_ETHERNET @@ -217,6 +212,8 @@ const byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0x54, 0x95}; //W5100 ethernet shield # define AWS_IOT false #endif +#define GITHUB_OTA_SERVER_CERT_HASH "d4d211b4553af9fac371f24c2268d59d2b0fec6b9aa0fdbbde068f078d7daf86" // SHA256 fingerprint of the certificate used by the OTA server + #if AWS_IOT // Enable the use of ALPN for AWS IoT Core with the port 443 const char* alpnProtocols[] = {"x-amzn-mqtt-ca", NULL}; diff --git a/main/ZboardTheengs.ino b/main/ZboardTheengs.ino index abfa687..7428696 100644 --- a/main/ZboardTheengs.ino +++ b/main/ZboardTheengs.ino @@ -31,7 +31,7 @@ void addTestMessage(JsonArray& data, String name, String value, String result) { } void testDevice() { - StaticJsonDocument<1200> doc; + StaticJsonDocument<1280> doc; JsonArray data = doc.to(); addTestMessage(data, "Mac Address", String(WiFi.macAddress()), "OK"); @@ -46,6 +46,7 @@ void testDevice() { addTestMessage(data, "ETH Link Speed", String(ETH.linkSpeed()) + "Mbs", ETH.linkSpeed() ? "OK" : "NOK"); addTestMessage(data, "Build Date", String(__DATE__), "OK"); addTestMessage(data, "Build Time", String(__TIME__), "OK"); + Serial.println(); serializeJson(doc, Serial); Serial.println(); } diff --git a/main/certs/default_ota_cert.h b/main/certs/default_ota_cert.h index 1d5f55a..48385d1 100644 --- a/main/certs/default_ota_cert.h +++ b/main/certs/default_ota_cert.h @@ -1,5 +1,5 @@ // The certificate must be in PEM ascii format. -// The default certificate is for github. +// The default certificate is for ota.openmqttgateway.com const char* OTAserver_cert PROGMEM = R"EOF(" -----BEGIN CERTIFICATE----- MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF diff --git a/main/main.ino b/main/main.ino index 7fb9804..362df7f 100644 --- a/main/main.ino +++ b/main/main.ino @@ -446,11 +446,29 @@ bool handleJsonEnqueue(const StaticJsonDocument& jsonDoc, i return false; } } + +# include "mbedtls/sha256.h" + +std::string generateHash(const std::string& input) { + unsigned char hash[32]; + mbedtls_sha256((unsigned char*)input.c_str(), input.length(), hash, 0); + + char hashString[65]; // Room for null terminator + for (int i = 0; i < 32; ++i) { + sprintf(&hashString[i * 2], "%02x", hash[i]); + } + + return std::string(hashString); +} #else bool handleJsonEnqueue(const StaticJsonDocument& jsonDoc, int timeout) { enqueueJsonObject(jsonDoc); return true; } + +std::string generateHash(const std::string& input) { + return "Not implemented for ESP8266"; +} #endif // Semaphore check before enqueueing a document with default timeout QueueSemaphoreTimeOutLoop @@ -1805,7 +1823,20 @@ bool loadConfigFromFlash() { strcpy(key, "ota_server_cert"); strcat(key, index_suffix); if (json.containsKey(key)) { - cnt_parameters_array[i].ota_server_cert = json[key].as(); +# ifdef ESP32 + // Read hash from the file + std::string hash = generateHash(json["ota_server_cert"]); + // Compare the hash with the expected hash + if (hash == GITHUB_OTA_SERVER_CERT_HASH) { + // Do nothing + Log.warning(F("Old Github OTA server detected, skipping" CR)); + } else { + Log.notice(F("OTA server cert hash: %s" CR), hash.c_str()); + cnt_parameters_array[i].ota_server_cert = json["ota_server_cert"].as(); + } +# else + cnt_parameters_array[i].ota_server_cert = json["ota_server_cert"].as(); +# endif } strcpy(key, "mqtt_server"); strcat(key, index_suffix); @@ -2968,25 +2999,6 @@ void MQTTHttpsFWUpdate(char* topicOri, JsonObject& HttpsFwUpdateData) { } #endif -#ifdef ESP32 -# include "mbedtls/sha256.h" - -std::string generateHash(const std::string& input) { - unsigned char hash[32]; - mbedtls_sha256((unsigned char*)input.c_str(), input.length(), hash, 0); - - char hashString[65]; // Room for null terminator - for (int i = 0; i < 32; ++i) { - sprintf(&hashString[i * 2], "%02x", hash[i]); - } - - return std::string(hashString); -} -#else -std::string generateHash(const std::string& input) { - return "Not implemented for ESP8266"; -} -#endif /** * Read the certificates from the memory and publish a hash of the cert to the broker for identification purposes */