cmd_show.c revision 779796f57e1e0236ea502248ede2cbea986fca21
1cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 2cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * Copyright 2014 The Chromium OS Authors. All rights reserved. 3cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * Use of this source code is governed by a BSD-style license that can be 4cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * found in the LICENSE file. 5cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 6cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <errno.h> 7cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <fcntl.h> 8cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <getopt.h> 9cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <inttypes.h> 10cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stddef.h> 11cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdint.h> 12cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdio.h> 13cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <stdlib.h> 14cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <string.h> 15cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <sys/stat.h> 16cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <sys/types.h> 17cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include <unistd.h> 18cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 19cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "bmpblk_header.h" 20cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "fmap.h" 21cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "futility.h" 22cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "gbb_header.h" 23cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "host_common.h" 24cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "traversal.h" 25cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "util_misc.h" 26cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "vboot_common.h" 27cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local values for cb_area_s._flags */ 29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonenum callback_flags { 30cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson AREA_IS_VALID = 0x00000001, 31cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 32cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 33cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local structure for args, etc. */ 34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic struct local_data_s { 35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *k; 36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint8_t *f; 37cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint64_t f_size; 38cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} option; 39cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 40cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_key(VbPublicKey *pubkey, const char *sp) 41cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 42779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("%sAlgorithm: %" PRIu64 " %s\n", sp, pubkey->algorithm, 43cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (pubkey->algorithm < kNumAlgorithms ? 44cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson algo_strings[pubkey->algorithm] : "(invalid)")); 45cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%sKey Version: %" PRIu64 "\n", sp, pubkey->key_version); 46cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%sKey sha1sum: ", sp); 47cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(pubkey); 48cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 49cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 50cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 51cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_keyblock(VbKeyBlockHeader *key_block, const char *name, 52cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int sign_key, int good_sig) 53cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 54779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (name) 55779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Key block: %s\n", name); 56779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson else 57779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Key block:\n"); 58779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(" Signature: %s\n", 59779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); 60779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(" Size: 0x%" PRIx64 "\n", 61cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson key_block->key_block_size); 62cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Flags: %" PRIu64 " ", 63cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson key_block->key_block_flags); 64cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) 65cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" !DEV"); 66cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) 67cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" DEV"); 68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) 69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" !REC"); 70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) 71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" REC"); 72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 74cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *data_key = &key_block->data_key; 75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (data_key->algorithm < kNumAlgorithms 77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ? algo_strings[data_key->algorithm] 78cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson : "(invalid)")); 79cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 80cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key sha1sum: "); 81cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(data_key); 82cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_key(struct futil_traverse_state_s *state) 86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf; 88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) { 90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s looks bogus\n", state->name); 91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 92cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Public Key file: %s\n", state->in_filename); 95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_gbb(struct futil_traverse_state_s *state) 102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint8_t *buf = state->my_area->buf; 104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t len = state->my_area->len; 105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf; 106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *pubkey; 107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson BmpBlockHeader *bmp; 108cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int retval = 0; 109cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t maxlen = 0; 110cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 111cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* It looks like a GBB or we wouldn't be called. */ 112cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!futil_valid_gbb_header(gbb, len, &maxlen)) 113cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 114cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 115cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB header: %s\n", 116cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->component == CB_GBB ? state->in_filename : state->name); 117cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Version: %d.%d\n", 118cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->major_version, gbb->minor_version); 119a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson printf(" Flags: 0x%08x\n", gbb->flags); 120cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Regions: offset size\n"); 121cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" hwid 0x%08x 0x%08x\n", 122cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->hwid_offset, gbb->hwid_size); 123cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" bmpvf 0x%08x 0x%08x\n", 124cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->bmpfv_offset, gbb->bmpfv_size); 125cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" rootkey 0x%08x 0x%08x\n", 126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->rootkey_offset, gbb->rootkey_size); 127cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" recovery_key 0x%08x 0x%08x\n", 128cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->recovery_key_offset, gbb->recovery_key_size); 129cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 130cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: 0x%08x / 0x%08x%s\n", 131cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson maxlen, len, maxlen > len ? " (not enough)" : ""); 132cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 133cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (retval) { 134cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB header is invalid, ignoring content\n"); 135cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 136cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 137cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 138cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB content:\n"); 139cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" HWID: %s\n", 140cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (const char *)(buf + gbb->hwid_offset)); 141cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 142cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset); 143cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) { 144cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.offset = state->my_area->offset + 145cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->rootkey_offset; 146cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.buf = buf + gbb->rootkey_offset; 147cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.len = gbb->rootkey_size; 148cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey._flags |= AREA_IS_VALID; 149cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Root Key:\n"); 150cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 151cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 152cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 153cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Root Key: <invalid>\n"); 154cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 155cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 156cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset); 157cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) { 158cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.offset = state->my_area->offset + 159cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->recovery_key_offset; 160cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.buf = buf + gbb->recovery_key_offset; 161cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.len = gbb->recovery_key_size; 162cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key._flags |= AREA_IS_VALID; 163cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Recovery Key:\n"); 164cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 165cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 166cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 167cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Recovery Key: <invalid>\n"); 168cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 169cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 170cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset); 171cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) { 172cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" BmpBlock: <invalid>\n"); 17308efd1ee358c546c968918a24b45219d7003cecaBill Richardson /* We don't support old formats, so it's not always an error */ 17408efd1ee358c546c968918a24b45219d7003cecaBill Richardson /* TODO: Add a --strict option to make this fatal? */ 175cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 176cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" BmpBlock:\n"); 177cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Version: %d.%d\n", 178cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->major_version, bmp->minor_version); 179cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Localizations: %d\n", 180cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_localizations); 181cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Screen layouts: %d\n", 182cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_screenlayouts); 183cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Image infos: %d\n", 184cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_imageinfos); 185cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 186cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 187cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!retval) 188cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 189cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 190cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return retval; 191cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 192cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 193cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_keyblock(struct futil_traverse_state_s *state) 194cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 195cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf; 196cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *sign_key = option.k; 197cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int good_sig = 0; 198cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 199cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the hash only first */ 200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) { 201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s is invalid\n", state->name); 202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 205cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the signature if we have one */ 206cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (sign_key && VBOOT_SUCCESS == 207cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson KeyBlockVerify(block, state->my_area->len, sign_key, 0)) 208cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson good_sig = 1; 209cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 210cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_keyblock(block, state->in_filename, !!sign_key, good_sig); 211cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 212cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image. 219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * 220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing 221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter 222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * corresponding VBLOCK area, we'll have this to verify. 223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_main(struct futil_traverse_state_s *state) 225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Firmware body: %s\n", state->name); 227cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Offset: 0x%08x\n", state->my_area->offset); 228cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: 0x%08x\n", state->my_area->len); 229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 230cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_preamble(struct futil_traverse_state_s *state) 236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf; 238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t len = state->my_area->len; 239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *sign_key = 0; 240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint8_t *fv_data = 0; 241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint64_t fv_size = 0; 242cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson struct cb_area_s *fw_body_area = 0; 243cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int good_sig = 0; 244cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 245cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the hash... */ 246cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { 247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s keyblock component is invalid\n", state->name); 248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 250cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (state->component) { 252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FMAP_VBLOCK_A: 253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* BIOS should have a rootkey in the GBB */ 254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (state->rootkey._flags & AREA_IS_VALID) 255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = (VbPublicKey *)state->rootkey.buf; 256cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* And we should have already seen the firmware body */ 257cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A]; 258cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 259cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FMAP_VBLOCK_B: 260cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* BIOS should have a rootkey in the GBB */ 261cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (state->rootkey._flags & AREA_IS_VALID) 262cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = (VbPublicKey *)state->rootkey.buf; 263cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* And we should have already seen the firmware body */ 264cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B]; 265cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 266cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FW_PREAMBLE: 267cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We'll have to get a signature and body from elsewhere */ 268cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = option.k; 269cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fv_data = option.f; 270cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fv_size = option.f_size; 271cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 272cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 273cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson DIE; 274cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 275cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 276cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* If we have a key, check the signature too */ 277cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (sign_key && VBOOT_SUCCESS == 278cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson KeyBlockVerify(key_block, len, sign_key, 0)) 279cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson good_sig = 1; 280cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 281cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_keyblock(key_block, 282cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->component == CB_FW_PREAMBLE 283cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ? state->in_filename : state->name, 284cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson !!sign_key, good_sig); 285cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 286cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); 287cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!rsa) { 288779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson fprintf(stderr, "Error parsing data key in %s\n", state->name); 289cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 290cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 291cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t more = key_block->key_block_size; 292cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbFirmwarePreambleHeader *preamble = 293cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (VbFirmwarePreambleHeader *)(state->my_area->buf + more); 294cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 295cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != VerifyFirmwarePreamble(preamble, 296cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson len - more, rsa)) { 297cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s is invalid\n", state->name); 298cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 299cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 300cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 301cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t flags = VbGetFirmwarePreambleFlags(preamble); 302779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Firmware Preamble:\n"); 303cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: %" PRIu64 "\n", 304cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->preamble_size); 305cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Header version: %" PRIu32 ".%" PRIu32 "\n", 306cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->header_version_major, preamble->header_version_minor); 307cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Firmware version: %" PRIu64 "\n", 308cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->firmware_version); 309cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *kernel_subkey = &preamble->kernel_subkey; 310cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Kernel key algorithm: %" PRIu64 " %s\n", 311cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson kernel_subkey->algorithm, 312cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (kernel_subkey->algorithm < kNumAlgorithms ? 313cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson algo_strings[kernel_subkey->algorithm] : "(invalid)")); 314cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Kernel key version: %" PRIu64 "\n", 315cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson kernel_subkey->key_version); 316cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Kernel key sha1sum: "); 317cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(kernel_subkey); 318cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 319cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Firmware body size: %" PRIu64 "\n", 320cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->body_signature.data_size); 321cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Preamble flags: %" PRIu32 "\n", flags); 322cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 323cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 324cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) { 325779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Preamble requests USE_RO_NORMAL;" 326779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " skipping body verification.\n"); 327cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson goto done; 328cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 329cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 330cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We'll need to get the firmware body from somewhere... */ 331779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (fw_body_area && (fw_body_area->_flags & AREA_IS_VALID)) { 332cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fv_data = fw_body_area->buf; 333cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fv_size = fw_body_area->len; 334cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 335cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 336cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!fv_data) { 337cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("No firmware body available to verify.\n"); 33808efd1ee358c546c968918a24b45219d7003cecaBill Richardson /* TODO: Add a --strict option to make this fatal? */ 33908efd1ee358c546c968918a24b45219d7003cecaBill Richardson return 0; 340cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 341cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 342cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != 343cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) { 344779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson fprintf(stderr, "Error verifying firmware body.\n"); 345cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 346cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 347cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 348cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsondone: 349cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Can't trust the BIOS unless everything is signed, 350cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * but standalone files are okay. */ 351cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if ((state->component == CB_FW_PREAMBLE) || 352cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (sign_key && good_sig)) { 353cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL)) 354cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Body verification succeeded.\n"); 355cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 356cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 35708efd1ee358c546c968918a24b45219d7003cecaBill Richardson printf("Seems legit, but the signature is unverified.\n"); 35808efd1ee358c546c968918a24b45219d7003cecaBill Richardson /* TODO: Add a --strict option to make this fatal? */ 359cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 360cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 361cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 362cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 363cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 364cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_begin(struct futil_traverse_state_s *state) 365cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 366cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (state->in_type) { 367cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_UNKNOWN: 368cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unable to determine type of %s\n", 369cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->in_filename); 370cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 371cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 372cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_BIOS_IMAGE: 373cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_OLD_BIOS_IMAGE: 374cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("BIOS: %s\n", state->in_filename); 375cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 376cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 377cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 378cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 379cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 380cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 381cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 382cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 383779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic const char usage[] = "\n" 384779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Usage: " MYNAME " %s [OPTIONS] FILE\n" 385779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 386779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Where FILE could be a\n" 387779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 388779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " public key (.vbpubk)\n" 389779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " keyblock (.keyblock)\n" 390779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " firmware preamble signature (VBLOCK_A/B)\n" 391779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " firmware image (bios.bin)\n" 392779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " kernel partition (/dev/sda2, /dev/mmcblk0p2)\n" 393779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 394779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Options:\n" 395779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " -k|--publickey FILE Use this public key for validation\n" 396779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " -f|--fv FILE|OFFSET Verify this payload (FW_MAIN_A/B, or\n" 397779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " kernel vblock padding size)\n" 398779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n"; 399779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson 400779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog) 401cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 402779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(usage, prog); 403cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 404cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 405cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct option long_opts[] = { 406cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* name hasarg *flag val */ 407cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"publickey", 1, 0, 'k'}, 408cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {"fv", 1, 0, 'f'}, 409cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {NULL, 0, NULL, 0}, 410cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 411cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic char *short_opts = ":f:k:"; 412cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 413cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int do_show(int argc, char *argv[]) 414cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 415cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson char *infile = 0; 416cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int ifd, i; 417cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int errorcnt = 0; 418cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson struct futil_traverse_state_s state; 419cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 420cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson opterr = 0; /* quiet, you */ 421cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { 422cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (i) { 423cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case 'f': 424cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson option.f = ReadFile(optarg, &option.f_size); 425cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!option.f) { 426cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 427cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 428cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 429cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 430cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case 'k': 431cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson option.k = PublicKeyRead(optarg); 432cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!option.k) { 433cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 434cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 435cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 436cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 437cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 438cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case '?': 439cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (optopt) 440cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unrecognized option: -%c\n", 441cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson optopt); 442cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson else 443cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unrecognized option\n"); 444cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 445cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 446cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case ':': 447cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Missing argument to -%c\n", optopt); 448cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 449cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 450779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson case 0: /* handled option */ 451779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson break; 452cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 453cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson DIE; 454cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 455cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 456cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 457779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (errorcnt) { 458779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 459779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson return 1; 460779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson } 461cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 462cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (argc - optind < 1) { 463cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "ERROR: missing input filename\n"); 464779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 465779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson return 1; 466cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 467cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 468cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson for (i = optind; i < argc; i++) { 469cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile = argv[i]; 470cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ifd = open(infile, O_RDONLY); 471cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (ifd < 0) { 472cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 473cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Can't open %s: %s\n", 474cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile, strerror(errno)); 475cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 476cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 477cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 478cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson memset(&state, 0, sizeof(state)); 479cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state.in_filename = infile ? infile : "<none>"; 480cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state.op = FUTIL_OP_SHOW; 481cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 48215dc6fc5eabc1b1756aca1dbed38cb9d26259bf2Bill Richardson errorcnt += futil_traverse(ifd, &state, 0); 483cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 484cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (close(ifd)) { 485cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 486cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error when closing %s: %s\n", 487cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile, strerror(errno)); 488cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 489cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 490cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 491cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (option.k) 492cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson free(option.k); 493cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (option.f) 494cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson free(option.f); 495cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 496cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return !!errorcnt; 497cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 498cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 499779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(show, do_show, 500779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Display the content of various binary components", 501779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help); 502