diff options
author | Patrick Georgi <patrick@georgi-clan.de> | 2015-10-01 15:54:04 +0200 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-10-01 20:14:26 +0000 |
commit | 89f20340d5a4c14ab76d3612cd33fff8894602ec (patch) | |
tree | a44cf61e958eb121de01bd17bc1cb4691ad8d455 /util/cbfstool/cbfs_image.c | |
parent | 44853371f108b85a36775b72b894c93b24d7b7f7 (diff) |
cbfstool: Add support for hashes as file metadata
They allow optimizing a verification of a whole CBFS image by only
dealing with the headers (assuming you choose to trust the hash
algorithm(s)).
The format allows for multiple hashes for a single file, and cbfstool
can handle them, but right now it can't generate such headers.
Loosely based on Sol's work in http://review.coreboot.org/#/c/10147/,
but using the compatible file attribute format. vboot is now a hard
dependency of the build process, but we import it into the tree for
quite a while now.
Change-Id: I9f14f30537d676ce209ad612e7327c6f4810b313
Signed-off-by: Patrick Georgi <patrick@georgi-clan.de>
Reviewed-on: http://review.coreboot.org/11767
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'util/cbfstool/cbfs_image.c')
-rw-r--r-- | util/cbfstool/cbfs_image.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 24ab0c4977..895927dd50 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -85,6 +85,16 @@ int cbfs_parse_comp_algo(const char *name) return lookup_type_by_name(types_cbfs_compression, name); } +static const char *get_hash_attr_name(uint16_t hash_type) +{ + return lookup_name_by_type(types_cbfs_hash, hash_type, "(invalid)"); +} + +int cbfs_parse_hash_algo(const char *name) +{ + return lookup_type_by_name(types_cbfs_hash, name); +} + /* CBFS image */ size_t cbfs_calculate_file_header_size(const char *name) @@ -173,6 +183,24 @@ static int cbfs_file_get_compression_info(struct cbfs_file *entry, return compression; } +static struct cbfs_file_attr_hash *cbfs_file_get_next_hash( + struct cbfs_file *entry, struct cbfs_file_attr_hash *cur) +{ + struct cbfs_file_attribute *attr = (struct cbfs_file_attribute *)cur; + if (attr == NULL) { + attr = cbfs_file_first_attr(entry); + if (attr == NULL) + return NULL; + if (ntohl(attr->tag) == CBFS_FILE_ATTR_TAG_HASH) + return (struct cbfs_file_attr_hash *)attr; + } + while ((attr = cbfs_file_next_attr(entry, attr)) != NULL) { + if (ntohl(attr->tag) == CBFS_FILE_ATTR_TAG_HASH) + return (struct cbfs_file_attr_hash *)attr; + }; + return NULL; +} + void cbfs_get_header(struct cbfs_header *header, void *src) { struct buffer outheader; @@ -813,6 +841,31 @@ int cbfs_print_entry_info(struct cbfs_image *image, struct cbfs_file *entry, ); } + struct cbfs_file_attr_hash *hash = NULL; + while ((hash = cbfs_file_get_next_hash(entry, hash)) != NULL) { + unsigned int hash_type = ntohl(hash->hash_type); + if (hash_type > CBFS_NUM_SUPPORTED_HASHES) { + fprintf(fp, "invalid hash type %d\n", hash_type); + break; + } + size_t hash_len = widths_cbfs_hash[hash_type]; + char *hash_str = bintohex(hash->hash_data, hash_len); + uint8_t local_hash[hash_len]; + if (vb2_digest_buffer(CBFS_SUBHEADER(entry), + ntohl(entry->len), hash_type, local_hash, + hash_len) != VB2_SUCCESS) { + fprintf(fp, "failed to hash '%s'\n", name); + break; + } + int valid = memcmp(local_hash, hash->hash_data, hash_len) == 0; + const char *valid_str = valid ? "valid" : "invalid"; + + fprintf(fp, " hash %s:%s %s\n", + get_hash_attr_name(hash_type), + hash_str, valid_str); + free(hash_str); + } + if (!verbose) return 0; @@ -1129,6 +1182,32 @@ struct cbfs_file_attribute *cbfs_add_file_attr(struct cbfs_file *header, return attr; } +int cbfs_add_file_hash(struct cbfs_file *header, struct buffer *buffer, + enum vb2_hash_algorithm hash_type) +{ + if (hash_type >= CBFS_NUM_SUPPORTED_HASHES) + return -1; + + unsigned hash_size = widths_cbfs_hash[hash_type]; + if (hash_size == 0) + return -1; + + struct cbfs_file_attr_hash *attrs = + (struct cbfs_file_attr_hash *)cbfs_add_file_attr(header, + CBFS_FILE_ATTR_TAG_HASH, + sizeof(struct cbfs_file_attr_hash) + hash_size); + + if (attrs == NULL) + return -1; + + attrs->hash_type = htonl(hash_type); + if (vb2_digest_buffer(buffer_get(buffer), buffer_size(buffer), + hash_type, attrs->hash_data, hash_size) != VB2_SUCCESS) + return -1; + + return 0; +} + /* Finds a place to hold whole data in same memory page. */ static int is_in_same_page(uint32_t start, uint32_t size, uint32_t page) { |