-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zlib compressed updates via flashz lib #100
Conversation
proof of concept - transparent decompression support for zlib compressed images sign+compression is not (yet) supported
hey @vortigont thanks for that POC, also perfect timing 👍 I've been experimenting with another decompression library (esp32-targz), and it's very comforting to see the similarities with your integration. I'm still evaluating the benefits of having the stream source overridable e.g. optionnally hook some open/read/error callbacks from the sketch and have the callbacks use HTTP (default), esp32-FlashZ, esp32-targz, fs::File, Serial or any other valid stream source during the update. So far the most complex scenario is with .tar.gz format, where a single decompression stream can handle separate contexts (spiffs and firmware) while the partitions order in the archive isn't controlled by esp32fota. Thanks to your POC I now have two decompression libraries to experiment with and much less choice paralysis for the implementation 🥳 |
Hi @tobozo you are welcome! |
esp32-targz needs some work before being usable with esp32fota as it bundles its own Update logic without using inheritance, so I'll leave this for later I haven't tested yet (still adjusting the CI workflow) but the optional use of esp32-flashz is possible, these are the macros I came up with to keep the impact on the code mininal: #if __has_include(<flashz.hpp>) || defined ESP32_FLASHZ_H
#include <flashz.hpp>
#define F_Update FlashZ::getInstance()
#define F_UseZlib (_stream->peek() == ZLIB_HEADER)
#define F_canBegin() mode_z ? F_Update.beginz(updateSize, partition) : F_Update.begin(updateSize, partition)
#define F_abort() if (mode_z) F_Update.abortz()
#define F_writeStream() mode_z ? F_Update.writezStream(*stream, contentLength) : F_Update.writeStream(*stream)
#else
#define F_Update Update
#define F_UseZlib false
#define F_canBegin() F_Update.begin( updateSize, partition )
#define F_abort() { }
#define F_writeStream() F_Update.writeStream( *_stream );
#endif |
Should be fine for testing I suppose. |
got some satisfying result after a few changes (published on 0.2.3 branch), and reduced the friction in the sketch to this: #include <flashz.hpp>
#include <esp32FOTA.hpp>
I'm not sure this choice is appropriate though, please advise if you think of a better extension/mimetype. apparently files created with gzip don't work with flashZ library, for some reason I thought zlib would handle gzipped content natively, is there a big difference between those formats? |
actually it should be just fine with default Need to think about signed updates though. I'm not that deep into this. As I can tell from the code a signature is in first 512 bytes of a |
thanks, your explanation makes sense I may have an idea for sig-checking archive: instead of being concatenated, the signature file is optionnally left in a separate file [edit] it was also suggested to provide the signature via a http header the signature logic happening after the partition is flashed still doesn't feel right though |
IMHO a detached signature sounds as the most flexible solution. It could be specified either as separate file in manifest or even in the manifest itself (much better approach than HTTP header as for me). And it could be on user's decision either to use it mandatory, or opportunistically. Any way it is good to have direct access to a plain firmware file, it could downloaded/flashed via serial, etc... without the need for specific update lib capable of signature verification. I was under impression that IDF has some embedded features to keys management, encrypting/verifying firmware but I've never researched this area much yet. It might worth investigating so not to reinvent the wheel :) |
I don't know esp-idf or even cryptographic practices well enough to tell but any change affecting a Using a http header to send the signature was suggested in the past though. Given all the suggested options I could find in the issue tracker, the signature can be:
// signature validation available methods
enum SigType_t
{
FOTA_SIG_PREPEND, // signature is contatenated with file (default)
FOTA_SIG_FILE, // signature is in a separate file
FOTA_SIG_JSON_PROPERTY, // signature is a JSON property
FOTA_SIG_HTTP_HEADER // signature is a HTTP header
};
struct FOTAConfig_t
{
const char* name { nullptr };
const char* manifest_url { nullptr };
SemverClass sem {0};
bool check_sig { false };
SigType_t type_sig {FOTA_SIG_PREPEND};
bool unsafe { false };
bool use_device_id { false };
CryptoAsset* root_ca { nullptr };
CryptoAsset* pub_key { nullptr };
FOTAConfig_t() = default;
};
The tradeoffs are suggesting that all or none of those situations should be implemented, maybe the signature check needs to be abstracted away from the main class ? Anyway I'm still busy researching how to add gz support so I probably won't be playing with signatures any time soon. |
IMO implementing all options is an overkill :) considering that ESP-IDF has native secure boot (maybe too complex but more feature reach). |
good point, I'm not sure if github supports polls but there's an upvote/downvote system with the discussions @chrisjoyce911 is it possible to enable the discussions tab on this repository? @vortigont I managed to get gz support to work by using a customized copy of the FlashZ class with some esp32-targz static methods 🥳 thanks for your inspiration! 🙇 |
Cool! Glad it was useful in adjacent areas :) |
closing this PR as esp32-flashz is now integrated |
This is proof-of-concept implementation of zlib-compressed images updating via esp32-flashz lib.
It allows transparent decompression and flashing with either compressed or uncompressed images.
A full featured implementation would require more work, especially with signed+compressed images.
Not sure if this idea is of any use for esp32FOTA project's roadmap. So any feedback is much appreciated.