-
Notifications
You must be signed in to change notification settings - Fork 13.3k
WIP: Add a SHA256Builder #3223
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
WIP: Add a SHA256Builder #3223
Conversation
This is a preperation for firmware file signature validation. In order to check, that a binary comes from a trusted source the signature needs to be validated. A secure hashing algorithm is a cruicial part of a secure signature. At the moment only MD5 is part of the core. I propose to add a SHA256Builder as a fundament for the firmware validation.
As discussed in #3105, i think the way forward is to add axTLS source as a submodule (or a subtree) to the Arduino core. This way we can use hashing, HMAC, x509 function without having to duplicate them. |
The other note about this: it seems to me that a lot of code in MD5Builder and SHA256Builder is very similar, with difference coming only in actual hashing function calls, hash context structures, and hash sizes. I do like the addition of SHA256Builder, but please consider folding implementation of these two hashes into one, both to reduce code size overhead (if both are used) and to reduce source code duplication. |
Thanks for that constructive feedback! To not introduce breaking changes I can do a "hashLib" baseclass and inherit it in MD5Builder and SHA256Builder? Or drop this and think of a serious axTLS submodule? |
I think if you make a base class for hash builders and temporary introduce (duplicate) SHA256 code this will be okay. Once someone figures out how to add axTLS as a submodule, this SHA256 code can be removed. |
…er, added seperate unit test for hashBuilder
Codecov Report
@@ Coverage Diff @@
## master #3223 +/- ##
==========================================
+ Coverage 27.6% 28.35% +0.74%
==========================================
Files 20 21 +1
Lines 3655 3707 +52
Branches 678 686 +8
==========================================
+ Hits 1009 1051 +42
- Misses 2468 2474 +6
- Partials 178 182 +4
Continue to review full report at Codecov.
|
The Crypto Submodule you mentioned - is there a concrete plan somewhere for this? /core The drawBack is, that the core will be filled with more classes. Alternatively, we might collect all functionalities (sha256, md5, rsa and aes) in a single class. The implementation I currently use in form of a library looks like this: String String sha256(const String &payload); String MD5(const String &payload); |
Does this include HMAC SHA256? |
Not yet, but I have a dirty implementation for signature checks with SHA256 if we could agree on a submodule structure. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good to me!
Suggest finalizing this and merging, then discussing RSA/AES as a separate step.
Another possible to-do thing (after this MR) is to update the Updater and all the dependent Updaters (HTTP, webserver, Arduino) to allow SHA256 to be used for hashes, with the goal of removing the use of MD5 after a while.
resString.reserve(res.size()*2); | ||
static constexpr char hex[] = "0123456789abcdef"; | ||
for (uint8_t & c : res){ | ||
resString += String(hex[c / 16]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I can't be upset with the indentation given that we don't have specific rules in this project (which is a shame)... but would be great if indentation was at least consistent at file scope.
void HashBuilder::getChars(char * output){ | ||
auto res = _result(); | ||
for(uint8_t i = 0; i < res.size(); i++){ | ||
sprintf(output + (i * 2), "%02x", res[i]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does nearly the same thing as _byteVecToString but uses sprintf instead of the hex
array. Would it make sense to use same method here?
|
||
// deprecated | ||
void getBytes(uint8_t * output ); | ||
void getChars(char * output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest expressing deprecation with __attribute__((deprecated))
Why are these deprecated, by the way?
|
||
protected: | ||
virtual void _init(void) = 0; | ||
virtual void _update(uint8_t * data, uint16_t len) = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is carried over from the original code, but since you are improving things, would you mind replacing this uint16_t with size_t? It doesn't serve any purpose and only adds extra extui
instructions to truncate 32-bit int to a 16-bit one.
|
||
// might be renamed to cryptoBuilder, cause same baseclass | ||
// might be reused in CrpytoSubmodule | ||
typedef HashBuilder CryptoBuilder; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that the current HashBuilder interface is a good fit for AES/RSA. There may be common operations such as conversions from/to byte/hex arrays, but this doesn't mean that these features should share a common interface, given how different the use cases are. If we happen to need the byte/hex transforms for crypto classes, my suggestion is to move these transforms into helper functions/classes shared between HashBuilder and the future crypto classes.
MD5Update(&_ctx, data, len); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for explicit return here
void MD5Builder::_init(void){ | ||
_resultVector = {}; | ||
MD5Init(&_ctx); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
likewise
void MD5Builder::_final(void){ | ||
_resultVector.resize(HEX_STR_LEN); | ||
MD5Final(_resultVector.data(), &_ctx); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
likewise
void SHA256Builder::_final(void){ | ||
_resultVector.resize(HEX_STR_LEN); | ||
SHA256_Final(_resultVector.data(), &_ctx); | ||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returns, indentation
@@ -0,0 +1,43 @@ | |||
/* | |||
MD5Builder.h - exposed md5 ROM functions for esp8266 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the ever present comment line :)
Regarding importing axTLS code — let me give it a try... |
Thanks a lot @igrr for taking the time for constructive feedback! EDIT: |
CC @earlephilhower |
Without a hardware module to accelerate things, either axtls or bearssl would be doable here. But so would any standard C/Arduino library, and it may end up importing less code than either one. There are hundreds of implementations out there, most optimized for 32 or 64 bit processors, so if this is really important I'd suggest looking there and not using either SSL lib as a base. The way BearSSL is implemented the hash functions are written as pseudo-C++ classes in straight C. It's got MD5, SHA 1, 224, 256, 384, and 512 implemented IIRC. It's not rocket science pulling them out and doing a wrapper, but I have not done any benchmarking to compare their performance. |
Given this is a WIP with 2 years w/o update, intended for use on signed updates (which are already in there using something similar but using BearSSL), I'm closing. If someone wants to do an abstract wrapper for hashes around the BSSL implementation (honestly, they're simple enough to use directly w/o a wrapper), a new PR would be the best way forward. |
A secure hashing algorithm is a crucial part of a secure signature.
At the moment only MD5 is part of the core, thus I propose to add the SHA256Builder.
Can then be implemented with: https://github.com/esp8266/Arduino/pull/3105/files
ToDo