From 76b12e0c6d75551dd49225502a70eb30385e7c65 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Jul 2020 07:45:05 +0200 Subject: [PATCH 1/6] Adding hidden string property OTA_SHA256 which will contain the SHA256 hash of MCU's flash in order for the cloud team to verify the correct download. --- src/ArduinoIoTCloudTCP.cpp | 2 ++ src/ArduinoIoTCloudTCP.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 1fef05472..e5726d2f5 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -94,6 +94,7 @@ ArduinoIoTCloudTCP::ArduinoIoTCloudTCP() , _ota_topic_in{""} #if OTA_ENABLED , _ota_error{static_cast(OTAError::None)} +, _ota_img_sha256{"Inv."} #endif /* OTA_ENABLED */ { @@ -229,6 +230,7 @@ void ArduinoIoTCloudTCP::printDebugInfo() void ArduinoIoTCloudTCP::setOTAStorage(OTAStorage & ota_storage) { addPropertyReal(_ota_error, "OTA_ERROR", Permission::Read); + addPropertyReal(_ota_img_sha256, "OTA_SHA256", Permission::Read); _ota_logic.setOTAStorage(ota_storage); } #endif /* OTA_ENABLED */ diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index 6bc6f0ca0..2006ee7de 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -127,6 +127,7 @@ class ArduinoIoTCloudTCP: public ArduinoIoTCloudClass #if OTA_ENABLED OTALogic _ota_logic; int _ota_error; + String _ota_img_sha256; #endif /* OTA_ENABLED */ inline String getTopic_stdin () { return String("/a/d/" + getDeviceId() + "/s/i"); } From cb959574b84bc2eecc6a6af4b9e0b25d6219c599 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Jul 2020 08:00:19 +0200 Subject: [PATCH 2/6] Adding class for calculating SHA256 using BearSSL --- src/tls/utility/SHA256.cpp | 41 +++++++++++++++++++++++++++++++++ src/tls/utility/SHA256.h | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/tls/utility/SHA256.cpp create mode 100644 src/tls/utility/SHA256.h diff --git a/src/tls/utility/SHA256.cpp b/src/tls/utility/SHA256.cpp new file mode 100644 index 000000000..bc443276b --- /dev/null +++ b/src/tls/utility/SHA256.cpp @@ -0,0 +1,41 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "SHA256.h" + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +void SHA256::begin() +{ + br_sha256_init(&_ctx); +} + +void SHA256::update(uint8_t const * data, size_t const len) +{ + br_sha256_update(&_ctx, data, len); +} + +void SHA256::finalize(char * hash) +{ + br_sha256_out(&_ctx, hash); +} diff --git a/src/tls/utility/SHA256.h b/src/tls/utility/SHA256.h new file mode 100644 index 000000000..4166616f5 --- /dev/null +++ b/src/tls/utility/SHA256.h @@ -0,0 +1,46 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +#ifndef ARDUINO_TLS_UTILITY_SHA256_H_ +#define ARDUINO_TLS_UTILITY_SHA256_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "../bearssl/bearssl_hash.h" + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class SHA256 +{ + +public: + + void begin (); + void update (uint8_t const * data, size_t const len); + void finalize(char * hash); + +private: + + br_sha256_context _ctx; + +}; + +#endif /* ARDUINO_TLS_UTILITY_SHA256_H_ */ From 85c87bbb617ee5cdd77c86e34314b52132e9e6f7 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Jul 2020 09:29:18 +0200 Subject: [PATCH 3/6] Refactoring debug outputs for better readability (removing unncessary clutter) --- src/utility/ota/OTALogic.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/utility/ota/OTALogic.cpp b/src/utility/ota/OTALogic.cpp index 60c9f9a38..b04b4d9f2 100644 --- a/src/utility/ota/OTALogic.cpp +++ b/src/utility/ota/OTALogic.cpp @@ -125,7 +125,7 @@ void OTALogic::onOTADataReceived(uint8_t const * const data, size_t const length OTAState OTALogic::handle_Init() { #ifndef HOST - DBG_VERBOSE(__PRETTY_FUNCTION__); + DBG_VERBOSE("OTALogic::%s", __FUNCTION__); #endif if (_ota_storage->init()) { return OTAState::Idle; @@ -146,7 +146,7 @@ OTAState OTALogic::handle_Idle() OTAState OTALogic::handle_StartDownload() { #ifndef HOST - DBG_VERBOSE(__PRETTY_FUNCTION__); + DBG_VERBOSE("OTALogic::%s", __FUNCTION__); #endif if(_ota_storage->open()) { return OTAState::WaitForHeader; @@ -159,7 +159,7 @@ OTAState OTALogic::handle_StartDownload() OTAState OTALogic::handle_WaitForHeader() { #ifndef HOST - DBG_VERBOSE(__PRETTY_FUNCTION__); + DBG_VERBOSE("OTALogic::%s", __FUNCTION__); #endif if(_mqtt_ota_buf.num_bytes >= OTA_BINARY_HEADER_SIZE) { return OTAState::HeaderReceived; @@ -190,8 +190,8 @@ OTAState OTALogic::handle_HeaderReceived() _ota_bin_data.hdr_crc32 = ota_header.header.crc32; #ifndef HOST - DBG_VERBOSE("%s: header length = %d", __PRETTY_FUNCTION__, _ota_bin_data.hdr_len); - DBG_VERBOSE("%s: header CRC32 = %d", __PRETTY_FUNCTION__, _ota_bin_data.hdr_crc32); + DBG_VERBOSE("OTALogic::%s: header length = %d", __FUNCTION__, _ota_bin_data.hdr_len); + DBG_VERBOSE("OTALogic::%s: header crc32 = %X", __FUNCTION__, _ota_bin_data.hdr_crc32); #endif /* Reset the counter which is responsible for keeping tabs on how many bytes have been received */ @@ -234,7 +234,7 @@ OTAState OTALogic::handle_BinaryReceived() _mqtt_ota_buf.num_bytes = 0; #ifndef HOST - DBG_VERBOSE("%s: %d bytes written", __PRETTY_FUNCTION__, _ota_bin_data.bytes_received); + DBG_VERBOSE("OTALogic::%s: %d bytes written", __FUNCTION__, _ota_bin_data.bytes_received); #endif if(_ota_bin_data.bytes_received >= _ota_bin_data.hdr_len) { @@ -249,7 +249,7 @@ OTAState OTALogic::handle_BinaryReceived() OTAState OTALogic::handle_Verify() { #ifndef HOST - DBG_VERBOSE(__PRETTY_FUNCTION__); + DBG_VERBOSE("OTALogic::%s", __FUNCTION__); #endif if(_ota_bin_data.crc32 == _ota_bin_data.hdr_crc32) { return OTAState::Rename; @@ -263,7 +263,7 @@ OTAState OTALogic::handle_Verify() OTAState OTALogic::handle_Rename() { #ifndef HOST - DBG_VERBOSE(__PRETTY_FUNCTION__); + DBG_VERBOSE("OTALogic::%s", __FUNCTION__); #endif if(_ota_storage->rename()) { _ota_storage->deinit(); @@ -286,7 +286,7 @@ OTAState OTALogic::handle_Reset() * is started directly. */ #ifndef HOST - DBG_VERBOSE(__PRETTY_FUNCTION__); + DBG_VERBOSE("OTALogic::%s", __FUNCTION__); delay(250); #endif NVIC_SystemReset(); From dea0e104c3e19f3036f5d5d563b50be7794bcc4a Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Jul 2020 09:55:55 +0200 Subject: [PATCH 4/6] First draft on SHA256 calculation, needs a bit of cleanup --- src/ArduinoIoTCloudTCP.cpp | 86 ++++++++++++++++++++++++++++++++++++++ src/tls/utility/SHA256.cpp | 8 +++- src/tls/utility/SHA256.h | 4 +- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index e5726d2f5..ee4699b3d 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -27,8 +27,13 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" #include "tls/utility/CryptoUtil.h" + #include "tls/utility/SHA256.h" #endif +#undef max +#undef min +#include + #include "utility/ota/OTAStorage_SNU.h" #include "utility/ota/OTAStorage_SFU.h" #include "utility/ota/OTAStorage_SSU.h" @@ -119,6 +124,85 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _brokerAddress = brokerAddress; _brokerPort = brokerPort; +#ifdef OTA_ENABLED + /* Calculate the SHA256 checksum over the firmware stored in the flash of the + * MCU. Note: As we don't know the length per-se we read chunks of the flash + * until we detect one containing only 0xFF (= flash erased). This only works + * for firmware updated via OTA and second stage bootloaders (SxU family) + * because only those erase the complete flash before performing an update. + * Since the SHA256 firmware image is only required for the cloud servers to + * perform a version check after the OTA update this is a acceptable trade off. + */ + SHA256 sha256; + sha256.begin(); + + uint32_t const APP_START_ADDR = 0x2000; /* Start after the bootloader. */ + #undef FLASH_SIZE + uint32_t const FLASH_READ_SIZE = 0x40000 - APP_START_ADDR; + uint32_t const FLASH_READ_CHUNK_SIZE = 64; + + uint32_t flash_addr = APP_START_ADDR; + for(; flash_addr < FLASH_READ_SIZE; flash_addr += FLASH_READ_CHUNK_SIZE) + { + /* Read from the MCU's flash. */ + uint8_t buf[FLASH_READ_CHUNK_SIZE]; + memcpy(buf, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); + + /* Check if the next segment is erased, that is if all bytes within + * a read segment are 0xFF -> then we've reached the end of the + * firmware. + */ + uint8_t buf_2[FLASH_READ_CHUNK_SIZE]; + memcpy(buf_2, reinterpret_cast(flash_addr + FLASH_READ_CHUNK_SIZE), FLASH_READ_CHUNK_SIZE); + size_t valid_bytes_in_buf = 0; + DBG_VERBOSE("[%X]", flash_addr); + char msg[4]; + for(size_t i=0; i 0; valid_bytes_in_buf--) { + if (buf[valid_bytes_in_buf-1] != 0xFF) + break; + } + /* Update with the remaining bytes. */ + DBG_VERBOSE("End of firmware, %d valid bytes in last read segment", valid_bytes_in_buf); + sha256.update(buf, valid_bytes_in_buf); + break; + } + else + { + /* Otherwise update the SHA256 hash. */ + sha256.update(buf, FLASH_READ_CHUNK_SIZE); + } + } + Serial.println(); + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + /* Update the property. */ + _ota_img_sha256 = sha256_str; + /* Do some debug printout. */ + DBG_VERBOSE("SHA256: %d bytes read", flash_addr); + DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); +#endif /* OTA_ENABLED */ + #ifdef BOARD_HAS_ECCX08 if (!ECCX08.begin()) { DBG_ERROR("Cryptography processor failure. Make sure you have a compatible board."); return 0; } if (!CryptoUtil::readDeviceId(ECCX08, getDeviceId(), ECCX08Slot::DeviceId)) { DBG_ERROR("Cryptography processor read failure."); return 0; } @@ -187,6 +271,8 @@ void ArduinoIoTCloudTCP::update() _mqtt_data_request_retransmit = false; } + //DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); + // MTTQClient connected!, poll() used to retrieve data from MQTT broker _mqttClient.poll(); diff --git a/src/tls/utility/SHA256.cpp b/src/tls/utility/SHA256.cpp index bc443276b..ffed6e587 100644 --- a/src/tls/utility/SHA256.cpp +++ b/src/tls/utility/SHA256.cpp @@ -21,6 +21,12 @@ #include "SHA256.h" +/****************************************************************************** + * STATIC MEMBER DECLARATION + ******************************************************************************/ + +constexpr size_t SHA256::HASH_SIZE; + /****************************************************************************** * PUBLIC MEMBER FUNCTIONS ******************************************************************************/ @@ -35,7 +41,7 @@ void SHA256::update(uint8_t const * data, size_t const len) br_sha256_update(&_ctx, data, len); } -void SHA256::finalize(char * hash) +void SHA256::finalize(uint8_t * hash) { br_sha256_out(&_ctx, hash); } diff --git a/src/tls/utility/SHA256.h b/src/tls/utility/SHA256.h index 4166616f5..ed0ce1d5a 100644 --- a/src/tls/utility/SHA256.h +++ b/src/tls/utility/SHA256.h @@ -33,9 +33,11 @@ class SHA256 public: + static constexpr size_t HASH_SIZE = 32; + void begin (); void update (uint8_t const * data, size_t const len); - void finalize(char * hash); + void finalize(uint8_t * hash); private: From 63e85b2e1b0f1b5ec16ddaa29d63dc326c9a34ef Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Jul 2020 14:42:37 +0200 Subject: [PATCH 5/6] Extracting calculation of firmware SHA256 value into class FlashSHA256 --- src/ArduinoIoTCloudTCP.cpp | 79 ++--------------------- src/utility/ota/FlashSHA256.cpp | 109 ++++++++++++++++++++++++++++++++ src/utility/ota/FlashSHA256.h | 51 +++++++++++++++ 3 files changed, 164 insertions(+), 75 deletions(-) create mode 100644 src/utility/ota/FlashSHA256.cpp create mode 100644 src/utility/ota/FlashSHA256.h diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index ee4699b3d..a9cf45d69 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -27,13 +27,9 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" #include "tls/utility/CryptoUtil.h" - #include "tls/utility/SHA256.h" #endif -#undef max -#undef min -#include - +#include "utility/ota/FlashSHA256.h" #include "utility/ota/OTAStorage_SNU.h" #include "utility/ota/OTAStorage_SFU.h" #include "utility/ota/OTAStorage_SSU.h" @@ -132,75 +128,10 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) * because only those erase the complete flash before performing an update. * Since the SHA256 firmware image is only required for the cloud servers to * perform a version check after the OTA update this is a acceptable trade off. + * The bootloader is excluded from the calculation and occupies flash address + * range 0 to 0x2000, total flash size of 0x40000 bytes (256 kByte). */ - SHA256 sha256; - sha256.begin(); - - uint32_t const APP_START_ADDR = 0x2000; /* Start after the bootloader. */ - #undef FLASH_SIZE - uint32_t const FLASH_READ_SIZE = 0x40000 - APP_START_ADDR; - uint32_t const FLASH_READ_CHUNK_SIZE = 64; - - uint32_t flash_addr = APP_START_ADDR; - for(; flash_addr < FLASH_READ_SIZE; flash_addr += FLASH_READ_CHUNK_SIZE) - { - /* Read from the MCU's flash. */ - uint8_t buf[FLASH_READ_CHUNK_SIZE]; - memcpy(buf, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); - - /* Check if the next segment is erased, that is if all bytes within - * a read segment are 0xFF -> then we've reached the end of the - * firmware. - */ - uint8_t buf_2[FLASH_READ_CHUNK_SIZE]; - memcpy(buf_2, reinterpret_cast(flash_addr + FLASH_READ_CHUNK_SIZE), FLASH_READ_CHUNK_SIZE); - size_t valid_bytes_in_buf = 0; - DBG_VERBOSE("[%X]", flash_addr); - char msg[4]; - for(size_t i=0; i 0; valid_bytes_in_buf--) { - if (buf[valid_bytes_in_buf-1] != 0xFF) - break; - } - /* Update with the remaining bytes. */ - DBG_VERBOSE("End of firmware, %d valid bytes in last read segment", valid_bytes_in_buf); - sha256.update(buf, valid_bytes_in_buf); - break; - } - else - { - /* Otherwise update the SHA256 hash. */ - sha256.update(buf, FLASH_READ_CHUNK_SIZE); - } - } - Serial.println(); - /* Retrieve the final hash string. */ - uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; - sha256.finalize(sha256_hash); - String sha256_str; - std::for_each(sha256_hash, - sha256_hash + SHA256::HASH_SIZE, - [&sha256_str](uint8_t const elem) - { - char buf[4]; - snprintf(buf, 4, "%02X", elem); - sha256_str += buf; - }); - /* Update the property. */ - _ota_img_sha256 = sha256_str; - /* Do some debug printout. */ - DBG_VERBOSE("SHA256: %d bytes read", flash_addr); - DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); + _ota_img_sha256 = FlashSHA256::calc(0x2000, 0x40000 - 0x2000); #endif /* OTA_ENABLED */ #ifdef BOARD_HAS_ECCX08 @@ -271,8 +202,6 @@ void ArduinoIoTCloudTCP::update() _mqtt_data_request_retransmit = false; } - //DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(_ota_img_sha256.c_str()), _ota_img_sha256.c_str()); - // MTTQClient connected!, poll() used to retrieve data from MQTT broker _mqttClient.poll(); diff --git a/src/utility/ota/FlashSHA256.cpp b/src/utility/ota/FlashSHA256.cpp new file mode 100644 index 000000000..6c3173774 --- /dev/null +++ b/src/utility/ota/FlashSHA256.cpp @@ -0,0 +1,109 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#if OTA_ENABLED + +#include "FlashSHA256.h" + +#include "../../tls/utility/SHA256.h" + +#include + +#undef max +#undef min +#include + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + +String FlashSHA256::calc(uint32_t const start_addr, uint32_t const max_flash_size) +{ + SHA256 sha256; + uint8_t chunk [FLASH_READ_CHUNK_SIZE], + next_chunk[FLASH_READ_CHUNK_SIZE]; + + sha256.begin(); + + /* Read the first two chunks of flash. */ + uint32_t flash_addr = start_addr; + memcpy(chunk, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); + flash_addr += FLASH_READ_CHUNK_SIZE; + + for(; flash_addr < max_flash_size; flash_addr += FLASH_READ_CHUNK_SIZE) + { + /* Read the next chunk of memory. */ + memcpy(next_chunk, reinterpret_cast(flash_addr), FLASH_READ_CHUNK_SIZE); + + /* Check if the next segment is erased, that is if all bytes within + * a read segment are 0xFF -> then we've reached the end of the firmware. + */ + bool const next_chunk_is_erased_flash = std::all_of(next_chunk, + next_chunk+FLASH_READ_CHUNK_SIZE, + [](uint8_t const elem) { return (elem == 0xFF); }); + /* Determine how many bytes at the end of the current chunk are + * already set to 0xFF and therefore erased/non-written flash + * memory. + */ + if (next_chunk_is_erased_flash) + { + /* Eliminate trailing 0xFF. */ + size_t valid_bytes_in_chunk = 0; + for(valid_bytes_in_chunk = FLASH_READ_CHUNK_SIZE; valid_bytes_in_chunk > 0; valid_bytes_in_chunk--) + { + if (chunk[valid_bytes_in_chunk-1] != 0xFF) + break; + } + DBG_VERBOSE("FlashSHA256::calc: end of firmware, %d valid bytes in last read chunk", valid_bytes_in_chunk); + /* Update with the remaining bytes. */ + sha256.update(chunk, valid_bytes_in_chunk); + break; + } + + /* We've read a normal segment with the next segment not containing + * any erased elements, just update the SHA256 hash calcultion. + */ + sha256.update(chunk, FLASH_READ_CHUNK_SIZE); + + /* Copy next_chunk to chunk. */ + memcpy(chunk, next_chunk, FLASH_READ_CHUNK_SIZE); + } + + /* Retrieve the final hash string. */ + uint8_t sha256_hash[SHA256::HASH_SIZE] = {0}; + sha256.finalize(sha256_hash); + String sha256_str; + std::for_each(sha256_hash, + sha256_hash + SHA256::HASH_SIZE, + [&sha256_str](uint8_t const elem) + { + char buf[4]; + snprintf(buf, 4, "%02X", elem); + sha256_str += buf; + }); + /* Do some debug printout. */ + DBG_VERBOSE("SHA256: %d bytes read", flash_addr); + DBG_VERBOSE("SHA256: HASH(%d) = %s", strlen(sha256_str.c_str()), sha256_str.c_str()); + return sha256_str; +} + +#endif /* OTA_ENABLED */ diff --git a/src/utility/ota/FlashSHA256.h b/src/utility/ota/FlashSHA256.h new file mode 100644 index 000000000..a3125f717 --- /dev/null +++ b/src/utility/ota/FlashSHA256.h @@ -0,0 +1,51 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +#ifndef ARDUINO_OTA_FLASH_SHA256_H_ +#define ARDUINO_OTA_FLASH_SHA256_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#if OTA_ENABLED + +#include + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class FlashSHA256 +{ +public: + + static String calc(uint32_t const start_addr, uint32_t const max_flash_size); + +private: + + FlashSHA256() { } + FlashSHA256(FlashSHA256 const &) { } + + static constexpr uint32_t FLASH_READ_CHUNK_SIZE = 64; + +}; + +#endif /* OTA_ENABLED */ + +#endif /* ARDUINO_OTA_FLASH_SHA256_H_ */ From 2130a9a4b8688e6b6f2b013b61c84e903281a5c5 Mon Sep 17 00:00:00 2001 From: Alexander Entinger Date: Mon, 20 Jul 2020 14:52:08 +0200 Subject: [PATCH 6/6] Changing #ifdef OTA_ENABLED to #if OTA_ENABLED since the evaluation of that line seems to be compiler version dependent --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index a9cf45d69..f195c41ca 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -120,7 +120,7 @@ int ArduinoIoTCloudTCP::begin(String brokerAddress, uint16_t brokerPort) _brokerAddress = brokerAddress; _brokerPort = brokerPort; -#ifdef OTA_ENABLED +#if OTA_ENABLED /* Calculate the SHA256 checksum over the firmware stored in the flash of the * MCU. Note: As we don't know the length per-se we read chunks of the flash * until we detect one containing only 0xFF (= flash erased). This only works