@@ -847,6 +847,7 @@ int copyimage(void *out, struct img_type *img, writeimage callback)
.compressed = img->compressed,
.checksum = &img->checksum,
.hash = img->sha256,
+ .chunked_hashes = img->chunked_hashes,
.encrypted = img->is_encrypted,
.imgivt = img->ivt_ascii,
};
@@ -512,6 +512,7 @@ static void cleaup_img_entry(struct img_type *img)
void free_image(struct img_type *img) {
dict_drop_db(&img->properties);
+ free(img->chunked_hashes);
free(img);
}
@@ -210,6 +210,56 @@ void get_hash_value(parsertype p, void *elem, unsigned char *hash)
ascii_to_hash(hash, hash_ascii);
}
+#ifdef CONFIG_CHUNKED_HASH
+int get_chunked_hashes(parsertype p, void *elem, unsigned char **chunked_hashes)
+{
+ void *hashes_node = get_child(p, elem, "chunked_hashes");
+
+ /* does not have chunked hashes */
+ if (!hashes_node)
+ return 0;
+
+ int count = get_array_length(p, hashes_node);
+ if (!count) {
+ ERROR("chunked_hashes is not an array");
+ return -EINVAL;
+ }
+
+ unsigned char *hashes = malloc((count+1) * SHA256_HASH_LENGTH);
+ if (!hashes) {
+ ERROR("No memory: failed for %d bytes", (count+1) * SHA256_HASH_LENGTH);
+ return -ENOMEM;
+ }
+
+ int idx;
+ for (idx = 0; idx < count; idx++) {
+ void *hash_node = get_elem_from_idx(p, hashes_node, idx);
+ if (!hash_node) {
+ ERROR("Could not get %dth hash in %d long array?", idx, count);
+ free(hashes);
+ return -EINVAL;
+ }
+ const char *hash_str = get_field_string(p, hash_node, NULL);
+ if (!hash_str) {
+ ERROR("%dth hash in chunked hashes array was not a string?", idx);
+ free(hashes);
+ return -EINVAL;
+ }
+ if (ascii_to_hash(hashes + idx * SHA256_HASH_LENGTH, hash_str) < 0) {
+ ERROR("Invalid hash %s", hash_str);
+ free(hashes);
+ return -EINVAL;
+ }
+ }
+
+ /* zero final hash marking end of array */
+ memset(hashes + count * SHA256_HASH_LENGTH, 0, SHA256_HASH_LENGTH);
+
+ *chunked_hashes = hashes;
+ return 0;
+}
+#endif
+
bool set_find_path(const char **nodes, const char *newpath, char ***tmp)
{
char **paths;
@@ -61,6 +61,9 @@ void iterate_field(parsertype p, void *e, iterate_callback cb, void *data);
void get_field(parsertype p, void *e, const char *path, void *dest, field_type_t type);
int exist_field_string(parsertype p, void *e, const char *path);
void get_hash_value(parsertype p, void *elem, unsigned char *hash);
+#ifdef CONFIG_CHUNKED_HASH
+int get_chunked_hashes(parsertype p, void *elem, unsigned char **chunked_hashes);
+#endif
void check_field_string(const char *src, char *dst, const size_t max_len);
void *find_root(parsertype p, void *root, const char **nodes);
void *get_node(parsertype p, void *root, const char **nodes);
@@ -75,6 +75,7 @@ struct img_type {
long long size;
unsigned int checksum;
unsigned char sha256[SHA256_HASH_LENGTH]; /* SHA-256 is 32 byte */
+ unsigned char *chunked_hashes;
LIST_ENTRY(img_type) next;
};
@@ -421,6 +421,11 @@ static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
GET_FIELD_STRING(p, elem, "type", image->type);
GET_FIELD_STRING(p, elem, "data", image->type_data);
get_hash_value(p, elem, image->sha256);
+#ifdef CONFIG_CHUNKED_HASH
+ if (get_chunked_hashes(p, elem, &image->chunked_hashes)) {
+ return -1;
+ }
+#endif
/*
* offset can be set as number or string. As string,
This allows something like this to be fed to the new chunked_hashes code (libconfig syntax): ----- images: ( { filename = "somefile.tar.zst"; name = "version"; version = "1"; install-if-higher = true; compressed = "zstd"; encrypted = true; ivt = "3b627a40272e3ba253794680e6f870c9"; installed-directly = true; sha256 = "e437493d207e7dabfba69997072b938bcb93175eea09d4108b96825d1fc2b079"; chunked_hashes = ( "3028e787495f7a97bfb6c10110affed016d398374d8c2c02fd7d02bc84f75e68", "5280083a531be033af6bb31a579737fb296739c0d9fa100457ce328fdfad01d8", ); type = "archive"; path = "/tmp/swupdate"; properties: { create-destination = "true"; }; }, ); ----- Note the sha256 is ignored if chunked_hashes is found in copyfile(), but we've left it so this is installable by older versions of swupdate. Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com> --- core/cpio_utils.c | 1 + core/installer.c | 1 + core/parsing_library.c | 50 ++++++++++++++++++++++++++++++++++++++++ include/parselib.h | 3 +++ include/swupdate_image.h | 1 + parser/parser.c | 5 ++++ 6 files changed, 61 insertions(+)