cmd_show.c revision 5f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8
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" 265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson#include "vb1_helper.h" 27cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "vboot_common.h" 28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local values for cb_area_s._flags */ 30cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonenum callback_flags { 31cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson AREA_IS_VALID = 0x00000001, 32cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 33cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local structure for args, etc. */ 35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic struct local_data_s { 36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *k; 375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *fv; 385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t fv_size; 395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t padding; 405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int strict; 415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} option = { 425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson .padding = 65536, 435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}; 44cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 45cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_key(VbPublicKey *pubkey, const char *sp) 46cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 47779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("%sAlgorithm: %" PRIu64 " %s\n", sp, pubkey->algorithm, 48cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (pubkey->algorithm < kNumAlgorithms ? 49cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson algo_strings[pubkey->algorithm] : "(invalid)")); 50cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%sKey Version: %" PRIu64 "\n", sp, pubkey->key_version); 51cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%sKey sha1sum: ", sp); 52cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(pubkey); 53cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 54cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 55cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 56cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_keyblock(VbKeyBlockHeader *key_block, const char *name, 57cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int sign_key, int good_sig) 58cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 59779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (name) 60779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Key block: %s\n", name); 61779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson else 62779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Key block:\n"); 63779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(" Signature: %s\n", 64779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); 65779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(" Size: 0x%" PRIx64 "\n", 66cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson key_block->key_block_size); 67cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Flags: %" PRIu64 " ", 68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson key_block->key_block_flags); 69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) 70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" !DEV"); 71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) 72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" DEV"); 73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) 74cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" !REC"); 75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) 76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" REC"); 77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 78cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 79cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *data_key = &key_block->data_key; 80cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 81cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (data_key->algorithm < kNumAlgorithms 82cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ? algo_strings[data_key->algorithm] 83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson : "(invalid)")); 84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key sha1sum: "); 86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(data_key); 87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_key(struct futil_traverse_state_s *state) 91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 92cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf; 93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) { 95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s looks bogus\n", state->name); 96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Public Key file: %s\n", state->in_filename); 100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_gbb(struct futil_traverse_state_s *state) 107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 108cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint8_t *buf = state->my_area->buf; 109cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t len = state->my_area->len; 110cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf; 111cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *pubkey; 112cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson BmpBlockHeader *bmp; 113cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int retval = 0; 114cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t maxlen = 0; 115cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 116cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* It looks like a GBB or we wouldn't be called. */ 117cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!futil_valid_gbb_header(gbb, len, &maxlen)) 118cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 119cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 120cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB header: %s\n", 121cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->component == CB_GBB ? state->in_filename : state->name); 122cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Version: %d.%d\n", 123cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->major_version, gbb->minor_version); 124a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson printf(" Flags: 0x%08x\n", gbb->flags); 125cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Regions: offset size\n"); 126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" hwid 0x%08x 0x%08x\n", 127cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->hwid_offset, gbb->hwid_size); 128cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" bmpvf 0x%08x 0x%08x\n", 129cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->bmpfv_offset, gbb->bmpfv_size); 130cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" rootkey 0x%08x 0x%08x\n", 131cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->rootkey_offset, gbb->rootkey_size); 132cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" recovery_key 0x%08x 0x%08x\n", 133cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->recovery_key_offset, gbb->recovery_key_size); 134cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 135cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: 0x%08x / 0x%08x%s\n", 136cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson maxlen, len, maxlen > len ? " (not enough)" : ""); 137cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 138cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (retval) { 139cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB header is invalid, ignoring content\n"); 140cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 141cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 142cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 143cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB content:\n"); 144cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" HWID: %s\n", 145cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (const char *)(buf + gbb->hwid_offset)); 146cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 147cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset); 148cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) { 149cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.offset = state->my_area->offset + 150cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->rootkey_offset; 151cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.buf = buf + gbb->rootkey_offset; 152cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.len = gbb->rootkey_size; 153cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey._flags |= AREA_IS_VALID; 154cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Root Key:\n"); 155cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 156cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 157cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 158cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Root Key: <invalid>\n"); 159cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 160cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 161cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset); 162cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) { 163cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.offset = state->my_area->offset + 164cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->recovery_key_offset; 165cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.buf = buf + gbb->recovery_key_offset; 166cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.len = gbb->recovery_key_size; 167cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key._flags |= AREA_IS_VALID; 168cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Recovery Key:\n"); 169cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 170cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 171cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 172cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Recovery Key: <invalid>\n"); 173cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 174cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 175cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset); 176cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) { 177cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" BmpBlock: <invalid>\n"); 178cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 179cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" BmpBlock:\n"); 180cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Version: %d.%d\n", 181cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->major_version, bmp->minor_version); 182cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Localizations: %d\n", 183cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_localizations); 184cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Screen layouts: %d\n", 185cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_screenlayouts); 186cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Image infos: %d\n", 187cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_imageinfos); 188cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 189cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 190cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!retval) 191cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 192cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 193cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return retval; 194cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 195cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 196cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_keyblock(struct futil_traverse_state_s *state) 197cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 198cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf; 199cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *sign_key = option.k; 200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int good_sig = 0; 201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the hash only first */ 203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) { 204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s is invalid\n", state->name); 205cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 206cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 207cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 208cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the signature if we have one */ 209cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (sign_key && VBOOT_SUCCESS == 210cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson KeyBlockVerify(block, state->my_area->len, sign_key, 0)) 211cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson good_sig = 1; 212cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_keyblock(block, state->in_filename, !!sign_key, good_sig); 214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image. 222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * 223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing 224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter 225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * corresponding VBLOCK area, we'll have this to verify. 226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 227cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_main(struct futil_traverse_state_s *state) 228cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Firmware body: %s\n", state->name); 230cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Offset: 0x%08x\n", state->my_area->offset); 231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: 0x%08x\n", state->my_area->len); 232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_preamble(struct futil_traverse_state_s *state) 239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf; 241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t len = state->my_area->len; 2425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbPublicKey *sign_key = option.k; 2435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *fv_data = option.fv; 2445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t fv_size = option.fv_size; 245cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson struct cb_area_s *fw_body_area = 0; 246cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int good_sig = 0; 247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the hash... */ 249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { 250cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s keyblock component is invalid\n", state->name); 251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (state->component) { 255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FMAP_VBLOCK_A: 2565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!sign_key && (state->rootkey._flags & AREA_IS_VALID)) 2575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* BIOS should have a rootkey in the GBB */ 258cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = (VbPublicKey *)state->rootkey.buf; 259cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* And we should have already seen the firmware body */ 260cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A]; 261cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 262cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FMAP_VBLOCK_B: 2635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!sign_key && (state->rootkey._flags & AREA_IS_VALID)) 2645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* BIOS should have a rootkey in the GBB */ 265cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = (VbPublicKey *)state->rootkey.buf; 266cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* And we should have already seen the firmware body */ 267cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B]; 268cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 269cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FW_PREAMBLE: 2705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* We have to provide a signature and body in the options. */ 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 return 0; 339cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 340cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 341cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != 342cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) { 343779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson fprintf(stderr, "Error verifying firmware body.\n"); 344cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 345cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 346cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 347cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsondone: 348cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Can't trust the BIOS unless everything is signed, 349cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * but standalone files are okay. */ 350cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if ((state->component == CB_FW_PREAMBLE) || 351cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (sign_key && good_sig)) { 352cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL)) 353cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Body verification succeeded.\n"); 354cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 355cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 35608efd1ee358c546c968918a24b45219d7003cecaBill Richardson printf("Seems legit, but the signature is unverified.\n"); 357cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 358cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 359cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 360cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 361cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 3625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state) 3635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{ 3645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf; 3665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t len = state->my_area->len; 3675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbPublicKey *sign_key = option.k; 3685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *kernel_blob = 0; 3695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t kernel_size; 3705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int good_sig = 0; 3715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3725f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Check the hash... */ 3735f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { 3745f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("%s keyblock component is invalid\n", state->name); 3755f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 3765f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 3775f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* If we have a key, check the signature too */ 3795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (sign_key && VBOOT_SUCCESS == 3805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson KeyBlockVerify(key_block, len, sign_key, 0)) 3815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson good_sig = 1; 3825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Kernel partition: %s\n", state->in_filename); 3845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson show_keyblock(key_block, NULL, !!sign_key, good_sig); 3855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); 3875f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!rsa) { 3885f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error parsing data key in %s\n", state->name); 3895f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 3905f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 3915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t more = key_block->key_block_size; 3925f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbKernelPreambleHeader *preamble = 3935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson (VbKernelPreambleHeader *)(state->my_area->buf + more); 3945f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 3955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (VBOOT_SUCCESS != VerifyKernelPreamble(preamble, 3965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson len - more, rsa)) { 3975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("%s is invalid\n", state->name); 3985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 3995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Kernel Preamble:\n"); 4025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Size: 0x%" PRIx64 "\n", 4035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->preamble_size); 4045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Header version: %" PRIu32 ".%" PRIu32 "\n", 4055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->header_version_major, 4065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->header_version_minor); 4075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Kernel version: %" PRIu64 "\n", 4085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->kernel_version); 4095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Body load address: 0x%" PRIx64 "\n", 4105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->body_load_address); 4115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Body size: 0x%" PRIx64 "\n", 4125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->body_signature.data_size); 4135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Bootloader address: 0x%" PRIx64 "\n", 4145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->bootloader_address); 4155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Bootloader size: 0x%" PRIx64 "\n", 4165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->bootloader_size); 4175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Verify kernel body */ 4205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.fv) { 4215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* It's in a separate file, which we've already read in */ 4225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_blob = option.fv; 4235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_size = option.fv_size; 4245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } else { 4255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* It should be at an offset within the input file. */ 4265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_blob = state->my_area->buf + option.padding; 4275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_size = state->my_area->len - option.padding; 4285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!kernel_blob) { 4315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* TODO: Is this always a failure? The preamble is okay. */ 4325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "No kernel blob available to verify.\n"); 4335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 4345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (0 != VerifyData(kernel_blob, kernel_size, 4375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson &preamble->body_signature, rsa)) { 4385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error verifying kernel body.\n"); 4395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 4405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Body verification succeeded.\n"); 4435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble)); 4455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 0; 4475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} 4485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 449cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_begin(struct futil_traverse_state_s *state) 450cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 451cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (state->in_type) { 452cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_UNKNOWN: 453cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unable to determine type of %s\n", 454cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->in_filename); 455cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 456cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 457cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_BIOS_IMAGE: 458cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_OLD_BIOS_IMAGE: 459cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("BIOS: %s\n", state->in_filename); 460cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 461cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 462cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 463cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 464cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 465cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 466cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 467cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 4685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonenum no_short_opts { 4695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_PADDING = 1000, 4705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}; 4715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 472779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic const char usage[] = "\n" 473779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Usage: " MYNAME " %s [OPTIONS] FILE\n" 474779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 475779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Where FILE could be a\n" 476779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 477779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " keyblock (.keyblock)\n" 478779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " firmware preamble signature (VBLOCK_A/B)\n" 479779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " firmware image (bios.bin)\n" 480779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " kernel partition (/dev/sda2, /dev/mmcblk0p2)\n" 481779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 482779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Options:\n" 4835f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -k|--publickey FILE" 4845f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " Use this public key for validation\n" 4855f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n" 4865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --pad NUM Kernel vblock padding size\n" 487779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n"; 488779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson 489779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog) 490cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 491779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(usage, prog); 492cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 493cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 494cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct option long_opts[] = { 495cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* name hasarg *flag val */ 4965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"publickey", 1, 0, 'k'}, 4975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"fv", 1, 0, 'f'}, 4985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"pad", 1, NULL, OPT_PADDING}, 499e192e7f6cea5f2c4556b729bf57ef1f552e0242aBill Richardson {"debug", 0, &debugging_enabled, 1}, 500cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {NULL, 0, NULL, 0}, 501cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 502cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic char *short_opts = ":f:k:"; 503cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 504cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int do_show(int argc, char *argv[]) 505cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 506cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson char *infile = 0; 507cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int ifd, i; 508cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int errorcnt = 0; 509cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson struct futil_traverse_state_s state; 510b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson uint8_t *buf; 511b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson uint32_t buf_len; 5125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson char *e = 0; 513cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 514cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson opterr = 0; /* quiet, you */ 515cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { 516cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (i) { 517cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case 'f': 5185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.fv = ReadFile(optarg, &option.fv_size); 5195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.fv) { 5205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error reading %s: %s\n", 5215f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson optarg, strerror(errno)); 522cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 523cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 524cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 525cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case 'k': 526cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson option.k = PublicKeyRead(optarg); 527cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!option.k) { 528cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 529cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 530cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 531cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 5325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_PADDING: 5335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.padding = strtoul(optarg, &e, 0); 5345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!*optarg || (e && *e)) { 5355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 5365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Invalid --padding \"%s\"\n", optarg); 5375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 5385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 5395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 540cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 541cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case '?': 542cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (optopt) 543cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unrecognized option: -%c\n", 544cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson optopt); 545cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson else 546cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unrecognized option\n"); 547cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 548cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 549cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case ':': 550cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Missing argument to -%c\n", optopt); 551cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 552cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 553779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson case 0: /* handled option */ 554779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson break; 555cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 556cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson DIE; 557cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 558cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 559cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 560779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (errorcnt) { 561779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 562779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson return 1; 563779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson } 564cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 565cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (argc - optind < 1) { 566cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "ERROR: missing input filename\n"); 567779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 568779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson return 1; 569cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 570cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 571cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson for (i = optind; i < argc; i++) { 572cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile = argv[i]; 573cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ifd = open(infile, O_RDONLY); 574cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (ifd < 0) { 575cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 576cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Can't open %s: %s\n", 577cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile, strerror(errno)); 578b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson continue; 579b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson } 580b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 581b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) { 582b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt++; 583b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson goto boo; 584cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 585cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 586cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson memset(&state, 0, sizeof(state)); 587cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state.in_filename = infile ? infile : "<none>"; 588cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state.op = FUTIL_OP_SHOW; 589cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 590b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt += futil_traverse(buf, buf_len, &state, 591b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson FILE_TYPE_UNKNOWN); 592b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 5935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 594b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt += futil_unmap_file(ifd, MAP_RO, buf, buf_len); 595cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 596b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardsonboo: 597cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (close(ifd)) { 598cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 599cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error when closing %s: %s\n", 600cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile, strerror(errno)); 601cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 602cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 603cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 604cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (option.k) 605cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson free(option.k); 6065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.fv) 6075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson free(option.fv); 608cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 609cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return !!errorcnt; 610cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 611cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 612779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(show, do_show, 613779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Display the content of various binary components", 614779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help); 615