MultiGeiger icon indicating copy to clipboard operation
MultiGeiger copied to clipboard

Firmware Updates

Open ThomasWaldmann opened this issue 5 years ago • 17 comments

Need for a practicable firmware upgrade procedure

Context

  • MultiGeiger likely sits in a sealed tube and the USB port can't be accessed easily without disassembling the device / breaking the seal / resealing it.
  • We need to also consider users who are not very technical, so doing manual upgrades (no matter how) might be an issue.
  • Guess we would like to keep the devices up-to-date with the latest stable compatible firmware version (for bug fixes and features).

Upgrade options

Considering this, manual upgrades via USB cable or manual via WiFi using a browser are no good options.

What's left are automated upgrades via WiFi from a internet server.

Ideas

If the update file is cryptographically signed by a release manager, its integrity and its authenticity can be verified after it is downloaded, before it is flashed (it could be even verified again after flashing [reading it from flash] before switching to it to verify the flash procedure).

That way, the security of the transmission channel or of the server does not matter at all (as long as the signing key[s] are kept secret). We would never flash a tampered firmware.

Also, as long as the device sometimes manages to correctly transfer the file, it would work ok. We would never flash a corrupted firmware (but just retry later).

Priority

Rather high as it is a pain to upgrade the devices by other means (see "Context").

ThomasWaldmann avatar Jan 05 '20 09:01 ThomasWaldmann

Implementation ideas

ESP IDF based

Check signed code (on update / on boot):

https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html#signed-app-verification-without-hardware-secure-boot

https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html#config-secure-signed-on-boot-no-secure-boot

https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#custom-sdkconfig-defaults

https://github.com/espressif/esp-idf/blob/master/examples/system/ota/native_ota_example/main/native_ota_example.c#L228

https://github.com/espressif/esp-idf/blob/master/components/app_update/include/esp_ota_ops.h

Run arduino code as an idf component:

https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md

This pretty much is what we want, I guess.

some https updater code:

https://blog.classycode.com/secure-over-the-air-updates-for-esp32-ec25ae00db43

Arduino based

Update

https://github.com/espressif/arduino-esp32/tree/master/libraries/Update/

This is part of the arduino esp32 port, so we could just use that (without using the IDF). Sadly, there is no security inside Update, only a md5 check to detect random corruption.

HTTPUpdate

https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPUpdate https://github.com/espressif/arduino-esp32/tree/master/libraries/HTTPUpdate/examples

Download via http / https (using a hardcoded CA cert) and flash.

Optionally(?) needs a server side app that evaluates some client http headers to choose the right update and sets some response http headers (e.g. with the MD5 checksum).

ArduinoOTA

https://github.com/espressif/arduino-esp32/tree/master/libraries/ArduinoOTA

  • BasicOTA - update via espota.py -- needs to open a port on the PC to serve the update file to the client on the esp32 -- problematic with firewalls/complex setups -- cli script, problematic for end users
  • OTAWebUpdater: update via web-browser upload -- works. http, no firewall issues. -- one needs to know IP addr of esp32 or mdns needs to work. -- ok for end users (still manual though).

IotWebConf (added 2020-01-12)

This has some own code, making it simpler to use than the similar OTAWebUpdater from ArduinoOTA.

https://github.com/prampec/IotWebConf https://github.com/prampec/IotWebConf/blob/master/examples/IotWebConf04UpdateServer/IotWebConf04UpdateServer.ino

Other libs

https://github.com/kmackay/micro-ecc ecdsa for authentication, see also there: https://github.com/pcbreflux/espressif/blob/master/esp32/app/ESP32_micro-ecc/main/ecc_task.c

ThomasWaldmann avatar Jan 05 '20 15:01 ThomasWaldmann

There was the idea to seal the device completly using silica gel to reduce humidity. Currently it looks like if this is not necessary. So the current housing-design is extremly easy to open and not sealed at all. So you have access to the device and its Micro-USB-Connector in just some seconds.

Please check: https://github.com/ecocurious/MultiGeiger/blob/master/docs/Bauanleitung/Aufbauanleitung_2019_13_09.pdf Page 8

I think Reinhard has alredy looked into OTA and found out that there are different memory sizes available on the Heltec-PCBs, which is problematic for OTA. But anyway. Probably its worth to check it again.

WwwBoehriDe avatar Jan 07 '20 19:01 WwwBoehriDe

Even if you can reach the USB plug, it is still uncomfortable that way (and unlikely that all/most people frequently do that). Of course one does not need to install all the updates, but maintaining a lot of differently outdated or buggy versions likely is also not fun for the developers.

Reinhard told me that the overall code size might be problematic (see also #84 about that) for the 4MB flash size (but not for the 8MB devices) when using dual partitions for OTA.

BTW, if the flash size can be just chosen, I would of course go for 8MB devices, the price difference should be small enough to be not worth sacrificing OTA for it.

ThomasWaldmann avatar Jan 08 '20 09:01 ThomasWaldmann

Arduino's partition scheme "Minimal SPIFFS" offers 1.9 MB max. "APP" partitions (two of them, for OTA updates) and 190kB SPIFFS.

@rexfue Some questions:

  • do we use a significant SPIFFS amount or are 190kB sufficient?
  • what is the maximum binary size / app size you've seen yet? I've seen 0.8MB, but I do not have LoRa.

BTW, our own code is no way that large, most of that are libraries and likely that part could be optimized (not sure if that can be done with Arduino framework though).

ThomasWaldmann avatar Jan 09 '20 18:01 ThomasWaldmann

We don't use SPIFFS (at the moment) Currently program size is a little bit more than 1 MB in both versions, so this partition scheme should work

rexfue avatar Jan 09 '20 19:01 rexfue

I just wondered where it stores the data one enters via the web interface.

ThomasWaldmann avatar Jan 09 '20 19:01 ThomasWaldmann

It will be saved in "NVS" (or "preferences"), starting at 0x9000 and 0x5000 long (this depends on partition scheme). So its enough for our parameters.

rexfue avatar Jan 09 '20 20:01 rexfue

OK, I'll now work on implementing a simple solution based on OTAWebUpdater.

It won't be very secure, but the point is just having anything that does not require plugging into USB.

This won't be the desired state of OTA for MultiGeiger, but a start.

It should be superseded by a server based update mechanism with cryptographically signed firmware.

ThomasWaldmann avatar Jan 11 '20 19:01 ThomasWaldmann

The code from #137 was merged into master, so we now have a simple browser based way to update.

ThomasWaldmann avatar Jan 12 '20 19:01 ThomasWaldmann

@rexfue noted that IOTWebConf also has an Updater.

I had a look at that and the code looks quite similar, except that they do not have the "progress indication" which requires JQuery and makes troubles if you do not have an internet connection (because your laptop's wifi is connected to the esp32).

ThomasWaldmann avatar Jan 12 '20 20:01 ThomasWaldmann

Nevertheless I would prefer this one, at least until we have something better. Have you looked at the solution of Feinstaubsensor? They use a server based auto update. I think one day we should use the same.

rexfue avatar Jan 12 '20 20:01 rexfue

New OTA possibility should be mentioned in Readme !

rexfue avatar Jan 12 '20 20:01 rexfue

Are you saying you prefer current master branch over something based on IOTWebConf? It looks pretty easy, so I might have that ready today (assuming the library code works).

ThomasWaldmann avatar Jan 12 '20 20:01 ThomasWaldmann

No, the other way round. I prefer IotWebConfig. Also because of #140.

rexfue avatar Jan 12 '20 20:01 rexfue

OK, IotWebConf based updater + docs merged into master now (I reverted my previous OTA code).

So starting from V1.12.0, we have OTA capability, yay! \o/

It's still a bit simple and insecure (only protection is the esp32 AP wifi password and there is no cryptographic signature on the binary) - but better than nothing.

ThomasWaldmann avatar Jan 12 '20 22:01 ThomasWaldmann

Super - thanks.

rexfue avatar Jan 12 '20 22:01 rexfue

Unassigning myself for now - maybe it is better to implement a good solution within IotWebConf or within Arduino framework rather than within our project. Let's see...

ThomasWaldmann avatar Jan 13 '20 22:01 ThomasWaldmann