libuptiny is a library for (partial) verification of Uptane metadata on small devices with memory constraints and no POSIX OS.
Partial Uptane verification includes verification of director’s root and targets. How these metadata appears on the device is application-specific and is out of scope for this library.
Interfaces to verification functions for root and targets metadata are in root.h
and targets.h
respectively.
Interfaces to functions that user of the library should define are definced in common_data_api.h
, crypto_api.h
and state_api.h
.
This repository has been spun off Aktualizr, refer to its documentation for more details about HERE OTA Connect and Uptane.
The build system is CMake.
Right now, the library can either be built for the kea128 platform or natively for running tests.
The following instructions are intended to be run from an empty CMake build directory (mkdir build; cd build'
).
The test suite depends on Aktualizr, you will first need to run git submodule update --init --recursive
cmake ..
make build_uptiny_tests
ctest -L uptiny --output-on-failure
The interface to root metadata verifier is
bool uptane_parse_root(const char *metadata, size_t len, uptane_root_t *out_root);
metadata
should point to a buffer containing the whole root metadata with len
len being its length and the result written out_root
. Return value shows if the provided metadata was valid in terms of overall structure, old and new signatures and version. Expiration date is not yet checked, because time role for Uptane in HERE is still work in progress. The result in out_root
should only be trusted if the function returned true
.
Because the size of targets metadata can be indefinitely large depending of how many ECUs are managed by Uptane (one ECU adds app. 200-300 bytes to the metadata) it is critical to be able to parse it while having only part of it in the buffer. It also makes the interface somewhat complicated. Logically the caller and the parser/verifier are acting as coroutines where caller should change its behavior based on the output from the callee.
void uptane_parse_targets_init(void);
Should be called once before each targets metadata verification.
int uptane_parse_targets_feed(const char *message, size_t len, uptane_targets_t *out_targets, uint16_t *result);
Whenever the caller has a next chunk of targets metadata available, it calls uptane_parse_targets_feed
. The return value is either a number of characters the parser/verifier has consumed or a negative value on a critical error. If not the return value is non-negative, but is less that len
, that means that not the whole chunk could be processed on this iteration. In this case the rest of the chunk should be prepended to the next one at the next call to uptane_parse_targets_feed
. It is the responsibility of the caller to check the upper limit for the total size of targets metadata.
result
is a secondary output of the events that parser/verifier has detected. Error events are accompanied with return value of -1, which indicates that parsing should be aborted.
RESULT_END_FOUND
or RESULT_END_NOT_FOUND
indicate successfully processed targets metadata with the target for this particular ECU found or not found respectively. Only in the former case (i.e. RESULT_END_FOUND
) should the value in out_targets
be trusted.
-
Remote primary device requests current version manifest to check if there are updates for this ECU (manifest generation is not yet implemented).
-
Remote primary device requests the current root version from the ECU (out of scope of this library).
-
Starting with the first version after the present on the secondary ECU, the primary feeds respective root metadata (reception is also out of scop).
-
For each received metadata the secondary ECU verifies it as described above and on success stores it in the non-volatile state.
-
After root metadata is up-to-date, the targets metadata is fed sequentially and processed as described above. On success, and if the image in the ECU should be updated (
RESULT_END_FOUND
) it is stored in the non-volatile storage. -
The primary feeds the image and the secondary verifies its hashes according to what is in the stored targets metadata. On success it sets it as a new bootable image and saves the target name and version in the stored targets metadata as currently installed firmware name and version.
This code is maintained by the OTA team at HERE Technologies. If you have questions about the project, please reach us through Github issues for this repository or email us at otaconnect.support@here.com.
Complete contribution guidelines can be found in CONTRIBUTING.md.
This code is licensed under the Mozilla Public License 2.0, a copy of which can be found in this repository. All code is copyright HERE Europe B.V., 2016-2020.
We require that contributors accept the terms of Linux Foundation’s Developer Certificate of Origin. Specific instructions can be found in CONTRIBUTING.md.