diff options
Diffstat (limited to 'futility/cmd_show.c')
-rw-r--r-- | futility/cmd_show.c | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/futility/cmd_show.c b/futility/cmd_show.c index 6ed15435..4b11b50f 100644 --- a/futility/cmd_show.c +++ b/futility/cmd_show.c @@ -22,6 +22,7 @@ #include "2common.h" #include "2sha.h" #include "2sysincludes.h" +#include "cbfstool.h" #include "file_type_bios.h" #include "file_type.h" #include "fmap.h" @@ -181,6 +182,53 @@ done: return retval; } +static int fw_show_metadata_hash(const char *name, enum bios_component body_c, + struct vb2_fw_preamble *pre) +{ + struct vb2_hash real_hash; + struct vb2_hash *body_hash = + (struct vb2_hash *)vb2_signature_data(&pre->body_signature); + const uint32_t bhsize = vb2_digest_size(body_hash->algo); + + if (!bhsize || pre->body_signature.sig_size < + offsetof(struct vb2_hash, raw) + bhsize) { + fprintf(stderr, "Body signature data is too small to " + "fit metadata hash.\n"); + return 1; + } + + printf(" Body metadata hash: %s", + vb2_get_hash_algorithm_name(body_hash->algo)); + if (vb2_digest_size(body_hash->algo)) { + putchar(':'); + print_bytes((uint8_t *)body_hash->raw, + vb2_digest_size(body_hash->algo)); + } + putchar('\n'); + + if (cbfstool_get_metadata_hash(name, fmap_name[body_c], &real_hash) != + VB2_SUCCESS || + real_hash.algo == VB2_HASH_INVALID) { + fprintf(stderr, "Failed to get metadata hash. Firmware body is" + " corrupted or is not a valid CBFS.\n"); + return 1; + } + + if (body_hash->algo != real_hash.algo || + !vb2_digest_size(body_hash->algo) || + memcmp(body_hash->raw, real_hash.raw, + vb2_digest_size(body_hash->algo))) { + printf(" MISMATCH! Real hash: %s:", + vb2_get_hash_algorithm_name(real_hash.algo)); + print_bytes(&real_hash.raw, vb2_digest_size(real_hash.algo)); + putchar('\n'); + fprintf(stderr, "Signature hash does not match with" + " real metadata hash.\n"); + return 1; + } + return 0; +} + int show_fw_preamble_buf(const char *name, uint8_t *buf, uint32_t len, void *data) { @@ -190,6 +238,7 @@ int show_fw_preamble_buf(const char *name, uint8_t *buf, uint32_t len, uint8_t *fv_data = show_option.fv; uint64_t fv_size = show_option.fv_size; struct bios_area_s *fw_body_area = 0; + enum bios_component body_c; int good_sig = 0; int retval = 0; @@ -217,9 +266,8 @@ int show_fw_preamble_buf(const char *name, uint8_t *buf, uint32_t len, } /* Identify the firmware body for this VBLOCK */ - enum bios_component body_c = state->c == BIOS_FMAP_VBLOCK_A - ? BIOS_FMAP_FW_MAIN_A - : BIOS_FMAP_FW_MAIN_B; + body_c = state->c == BIOS_FMAP_VBLOCK_A ? BIOS_FMAP_FW_MAIN_A + : BIOS_FMAP_FW_MAIN_B; fw_body_area = &state->area[body_c]; } @@ -288,11 +336,15 @@ int show_fw_preamble_buf(const char *name, uint8_t *buf, uint32_t len, return 0; } - if (VB2_SUCCESS != - vb2_verify_data(fv_data, fv_size, &pre2->body_signature, - &data_key, &wb)) { - fprintf(stderr, "Error verifying firmware body.\n"); - return 1; + if (pre2->body_signature.data_size) { + if (vb2_verify_data(fv_data, fv_size, &pre2->body_signature, + &data_key, &wb) != VB2_SUCCESS) { + fprintf(stderr, "Error verifying firmware body.\n"); + return 1; + } + } else if (state) { /* Only works for images with at least FW_MAIN_A */ + if (fw_show_metadata_hash(name, body_c, pre2)) + return 1; } done: |