-
Notifications
You must be signed in to change notification settings - Fork 13
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
port: add sha256 API #664
base: main
Are you sure you want to change the base?
port: add sha256 API #664
Conversation
fcdf4db
to
cae526c
Compare
Visit the preview URL for this PR (updated for commit 9c4dd63): https://golioth-firmware-sdk-doxygen-dev--pr664-szczys-sha256-z40limll.web.app (expires Fri, 22 Nov 2024 20:47:49 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: a9993e61697a3983f3479e468bcb0b616f9a0578 |
4a25ae3
to
5417aff
Compare
clang-format seems to want to indent everything after after |
@@ -121,6 +121,70 @@ void golioth_sys_thread_destroy(golioth_sys_thread_t thread); | |||
#define golioth_sys_rand() rand() | |||
#endif | |||
|
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.
When #666 merges I think we should guard the following function declarations so they are only available when CONFIG_GOLIOTH_OTA
is selected.
The same goes for the definitions in each platform file.
return 0; | ||
} | ||
|
||
size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) |
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.
It's really unfortunate that the manifest gives us a text string instead of a binary string for the SHA. In a manifest v2, I'd like to see this be binary, to reduce the payload size as well as the amount of computation that needs to be done on device.
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.
Thinking about this some more, I think it would make sense to convert the hash to binary as we download it, and store it as binary in the manifest struct. A user of the SDK would have no reason to expect a hash in ASCII format, it's just an artifact of the cloud API, and we shouldn't let that implementation detail dictate the Firmware API.
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.
Great idea, I've added a commit to store the hash as a binary array so it's ready for comparison.
port/utils/hex.h
Outdated
* | ||
* @return Zero on success or (negative) error code otherwise. | ||
*/ | ||
int char2hex(char c, uint8_t *x); |
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.
Do we actually need this function to be public?
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, this is an error. Thanks for catching.
port/utils/hex.c
Outdated
} | ||
else | ||
{ | ||
return GOLIOTH_ERR_INVALID_FORMAT; |
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 is a positive value, which will cause the check on lines 47, 59, and 65 to fail. We should just leave this as -EINVAL
, there's no reason to use golioth_status.h
here, errno.h
is part of the standard library and should be available on all platforms.
port/zephyr/golioth_sys_zephyr.c
Outdated
struct golioth_hash | ||
{ | ||
mbedtls_sha256_context sha256_ctx; | ||
}; |
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.
Why wrap this in another struct?
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.
Originally I thought I would need more than just the context and didn't update this when that wasn't the case. I've changed to directly assign the struct point to the golioth typedef.
include/golioth/golioth_sys.h
Outdated
/// Call on an existing context to begin generating a new sha256 hash. | ||
/// | ||
/// @param sha_ctx A sha256 context handle | ||
void golioth_sys_sha256_init(golioth_sys_sha256_t sha_ctx); |
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'm not sure we need both create()
and init()
. We don't need to provide a super-flexible, general API. We just need to provide hooks into the functionality that our SDK needs, ideally while minimizing the amount of work that a user of the SDK would need to do in order to port the SDK to another platform.
include/golioth/golioth_sys.h
Outdated
/// Frees memory allocated to a sha256 context. | ||
/// | ||
/// @param sha_ctx A sha256 context handle | ||
void golioth_sys_sha256_free(golioth_sys_sha256_t sha_ctx); |
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.
APIs should match semantically:
*_create()
should be paired with*_destroy()
*_alloc()
should be paired with*_free()
include/golioth/golioth_sys.h
Outdated
/// @return GOLIOTH_OK On success | ||
/// @return GOLIOTH_ERR_FAIL On failure | ||
enum golioth_status golioth_sys_sha256_update(golioth_sys_sha256_t sha_ctx, | ||
uint8_t *input, |
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.
We can make input const
.
mbedtls_sha256_context sha256_ctx; | ||
}; | ||
|
||
golioth_sys_sha256_t golioth_sys_sha256_create(void) |
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'm back and forth on whether to use a typedef here, a straight void *
, or a struct golioth_hash *
with the incomplete definition in the header and the concrete definition in the source file.
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 also went back and forth when considering your feedback. I decided to keep with the typedef. It uses the same memory as a void* but does a better job off indicating intent.
5417aff
to
270e269
Compare
Add an API to manage sha256. This hash calculation is needed to verify OTA component integrity based on the hash supplied by the server in the OTA manifest. Signed-off-by: Mike Szczys <[email protected]>
Add two functions of hex.c from the Zephyr tree for use in converting OTA hex string sha256 hash to a binary array. Expose the hex2bin() function needed to compare against locally-calculated sha256 of downloaded assets. Signed-off-by: Mike Szczys <[email protected]>
Signed-off-by: Mike Szczys <[email protected]>
Signed-off-by: Mike Szczys <[email protected]>
270e269
to
35364fa
Compare
Signed-off-by: Mike Szczys <[email protected]>
35364fa
to
7af79bb
Compare
2d14017
to
7b79cdf
Compare
Codecov ReportAttention: Patch coverage is
|
Component hash is received from the server as a hex string. Convert it to a binary array when decoding the manifest so that it's ready to compare to a locally generated hash. Signed-off-by: Mike Szczys <[email protected]>
7b79cdf
to
9c4dd63
Compare
Add an API for generating a sha256 hash that can be used to validate an OTA component.
Resolves https://github.com/golioth/firmware-issue-tracker/issues/717