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" 202559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson#include "file_type.h" 21cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "fmap.h" 22cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "futility.h" 23cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "gbb_header.h" 24cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "host_common.h" 25cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "traversal.h" 26cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "util_misc.h" 275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson#include "vb1_helper.h" 28cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson#include "vboot_common.h" 29cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 30cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local values for cb_area_s._flags */ 31cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonenum callback_flags { 32cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson AREA_IS_VALID = 0x00000001, 33cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 34cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 35cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* Local structure for args, etc. */ 36cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic struct local_data_s { 37cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *k; 385f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *fv; 395f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t fv_size; 405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t padding; 415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int strict; 422559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson int t_flag; 435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} option = { 445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson .padding = 65536, 455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}; 46cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 47cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_key(VbPublicKey *pubkey, const char *sp) 48cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 49779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("%sAlgorithm: %" PRIu64 " %s\n", sp, pubkey->algorithm, 50cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (pubkey->algorithm < kNumAlgorithms ? 51cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson algo_strings[pubkey->algorithm] : "(invalid)")); 52cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%sKey Version: %" PRIu64 "\n", sp, pubkey->key_version); 53cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%sKey sha1sum: ", sp); 54cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(pubkey); 55cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 56cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 57cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 58cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic void show_keyblock(VbKeyBlockHeader *key_block, const char *name, 59cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int sign_key, int good_sig) 60cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 61779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (name) 62779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Key block: %s\n", name); 63779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson else 64779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Key block:\n"); 65779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(" Signature: %s\n", 66779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); 67779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf(" Size: 0x%" PRIx64 "\n", 68cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson key_block->key_block_size); 69cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Flags: %" PRIu64 " ", 70cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson key_block->key_block_flags); 71cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) 72cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" !DEV"); 73cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) 74cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" DEV"); 75cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) 76cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" !REC"); 77cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) 78cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" REC"); 79cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 80cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 81cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *data_key = &key_block->data_key; 82cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, 83cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (data_key->algorithm < kNumAlgorithms 84cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ? algo_strings[data_key->algorithm] 85cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson : "(invalid)")); 86cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key version: %" PRIu64 "\n", data_key->key_version); 87cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Data key sha1sum: "); 88cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(data_key); 89cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 90cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 91cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 924805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardsonint futil_cb_show_pubkey(struct futil_traverse_state_s *state) 93cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 94cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf; 95cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 96cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!PublicKeyLooksOkay(pubkey, state->my_area->len)) { 97cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s looks bogus\n", state->name); 98cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 99cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 100cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 101cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Public Key file: %s\n", state->in_filename); 102cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 103cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 104cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 105cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 106cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 107cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 1084805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardsonint futil_cb_show_privkey(struct futil_traverse_state_s *state) 1094805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson{ 1104805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson VbPrivateKey key; 1114805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson int alg_okay; 1124805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson 1134805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson key.algorithm = *(typeof(key.algorithm) *)state->my_area->buf; 1144805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson 1154805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson printf("Private Key file: %s\n", state->in_filename); 1164805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson alg_okay = key.algorithm < kNumAlgorithms; 1174805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson printf(" Algorithm: %" PRIu64 " %s\n", key.algorithm, 1184805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson alg_okay ? algo_strings[key.algorithm] : "(unknown)"); 1194805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson 1204805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson if (alg_okay) 1214805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 1224805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson 1234805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson return 0; 1244805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson} 1254805f1841de9d670aaed9bdaea21147ee1d59242Bill Richardson 126cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_gbb(struct futil_traverse_state_s *state) 127cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 128cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint8_t *buf = state->my_area->buf; 129cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t len = state->my_area->len; 130cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf; 131cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *pubkey; 132cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson BmpBlockHeader *bmp; 133cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int retval = 0; 134cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t maxlen = 0; 135cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 1367ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson if (!len) { 1377ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson printf("GBB header: %s <invalid>\n", 1387ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson state->component == CB_GBB ? 1397ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson state->in_filename : state->name); 1407ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson return 1; 1417ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson } 1427ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson 143cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* It looks like a GBB or we wouldn't be called. */ 144cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!futil_valid_gbb_header(gbb, len, &maxlen)) 145cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 146cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 147cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB header: %s\n", 148cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->component == CB_GBB ? state->in_filename : state->name); 149cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Version: %d.%d\n", 150cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->major_version, gbb->minor_version); 151a19b00dfd0c17681b71bd61994854dff3f3576a3Bill Richardson printf(" Flags: 0x%08x\n", gbb->flags); 152cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Regions: offset size\n"); 153cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" hwid 0x%08x 0x%08x\n", 154cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->hwid_offset, gbb->hwid_size); 155cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" bmpvf 0x%08x 0x%08x\n", 156cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->bmpfv_offset, gbb->bmpfv_size); 157cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" rootkey 0x%08x 0x%08x\n", 158cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->rootkey_offset, gbb->rootkey_size); 159cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" recovery_key 0x%08x 0x%08x\n", 160cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->recovery_key_offset, gbb->recovery_key_size); 161cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 162cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: 0x%08x / 0x%08x%s\n", 163cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson maxlen, len, maxlen > len ? " (not enough)" : ""); 164cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 165cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (retval) { 166cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB header is invalid, ignoring content\n"); 167cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 168cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 169cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 170cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("GBB content:\n"); 1716df3e33912baf2633ed27fce6fe166d87e2f04a8Bill Richardson printf(" HWID: %s\n", buf + gbb->hwid_offset); 1726df3e33912baf2633ed27fce6fe166d87e2f04a8Bill Richardson print_hwid_digest(gbb, " digest: ", "\n"); 173cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 174cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson pubkey = (VbPublicKey *)(buf + gbb->rootkey_offset); 175cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (PublicKeyLooksOkay(pubkey, gbb->rootkey_size)) { 176cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.offset = state->my_area->offset + 177cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->rootkey_offset; 178cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.buf = buf + gbb->rootkey_offset; 179cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey.len = gbb->rootkey_size; 180cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->rootkey._flags |= AREA_IS_VALID; 181cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Root Key:\n"); 182cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 183cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 184cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 185cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Root Key: <invalid>\n"); 186cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 187cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 188cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson pubkey = (VbPublicKey *)(buf + gbb->recovery_key_offset); 189cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (PublicKeyLooksOkay(pubkey, gbb->recovery_key_size)) { 190cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.offset = state->my_area->offset + 191cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson gbb->recovery_key_offset; 192cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.buf = buf + gbb->recovery_key_offset; 193cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key.len = gbb->recovery_key_size; 194cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->recovery_key._flags |= AREA_IS_VALID; 195cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Recovery Key:\n"); 196cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_key(pubkey, " "); 197cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 198cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson retval = 1; 199cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Recovery Key: <invalid>\n"); 200cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 201cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 202cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset); 203cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) { 204cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" BmpBlock: <invalid>\n"); 20552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson /* We don't support older BmpBlock formats, so we can't 20652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson * be strict about this. */ 207cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 208cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" BmpBlock:\n"); 209cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Version: %d.%d\n", 210cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->major_version, bmp->minor_version); 211cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Localizations: %d\n", 212cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_localizations); 213cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Screen layouts: %d\n", 214cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_screenlayouts); 215cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Image infos: %d\n", 216cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson bmp->number_of_imageinfos); 217cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 218cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 219cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!retval) 220cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 221cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 222cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return retval; 223cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 224cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 225cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_keyblock(struct futil_traverse_state_s *state) 226cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 227cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf; 228cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *sign_key = option.k; 229cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int good_sig = 0; 23052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson int retval = 0; 231cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 232cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the hash only first */ 233cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) { 234cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s is invalid\n", state->name); 235cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 236cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 237cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 238cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the signature if we have one */ 239cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (sign_key && VBOOT_SUCCESS == 240cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson KeyBlockVerify(block, state->my_area->len, sign_key, 0)) 241cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson good_sig = 1; 242cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 24352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (option.strict && (!sign_key || !good_sig)) 24452a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson retval = 1; 24552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson 246cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_keyblock(block, state->in_filename, !!sign_key, good_sig); 247cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 248cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 249cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 25052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson return retval; 251cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 252cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 253cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson/* 254cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * This handles FW_MAIN_A and FW_MAIN_B while processing a BIOS image. 255cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * 256cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * The data in state->my_area is just the RW firmware blob, so there's nothing 257cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * useful to show about it. We'll just mark it as present so when we encounter 258cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * corresponding VBLOCK area, we'll have this to verify. 259cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson */ 260cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_main(struct futil_traverse_state_s *state) 261cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 2627ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson if (!state->my_area->len) { 2637ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson printf("Firmware body: %s <invalid>\n", state->name); 2647ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson return 1; 2657ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson } 2667ccd9ce48e761b7614d29ff95ef97d0a7dc1d599Bill Richardson 267cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Firmware body: %s\n", state->name); 268cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Offset: 0x%08x\n", state->my_area->offset); 269cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: 0x%08x\n", state->my_area->len); 270cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 271cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 272cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 273cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 274cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 275cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 276cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_fw_preamble(struct futil_traverse_state_s *state) 277cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 278cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf; 279cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t len = state->my_area->len; 2805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbPublicKey *sign_key = option.k; 2815f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *fv_data = option.fv; 2825f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint64_t fv_size = option.fv_size; 283cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson struct cb_area_s *fw_body_area = 0; 284cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int good_sig = 0; 28552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson int retval = 0; 286cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 287cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Check the hash... */ 288cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { 289cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s keyblock component is invalid\n", state->name); 290cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 291cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 292cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 293cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (state->component) { 294cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FMAP_VBLOCK_A: 2955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!sign_key && (state->rootkey._flags & AREA_IS_VALID)) 2965f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* BIOS should have a rootkey in the GBB */ 297cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = (VbPublicKey *)state->rootkey.buf; 298cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* And we should have already seen the firmware body */ 299cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_A]; 300cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 301cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FMAP_VBLOCK_B: 3025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!sign_key && (state->rootkey._flags & AREA_IS_VALID)) 3035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* BIOS should have a rootkey in the GBB */ 304cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson sign_key = (VbPublicKey *)state->rootkey.buf; 305cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* And we should have already seen the firmware body */ 306cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fw_body_area = &state->cb_area[CB_FMAP_FW_MAIN_B]; 307cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 308cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case CB_FW_PREAMBLE: 3095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* We have to provide a signature and body in the options. */ 310cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 311cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 312cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson DIE; 313cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 314cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 315cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* If we have a key, check the signature too */ 316cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (sign_key && VBOOT_SUCCESS == 317cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson KeyBlockVerify(key_block, len, sign_key, 0)) 318cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson good_sig = 1; 319cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 320cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson show_keyblock(key_block, 321cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->component == CB_FW_PREAMBLE 322cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ? state->in_filename : state->name, 323cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson !!sign_key, good_sig); 324cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 32552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (option.strict && (!sign_key || !good_sig)) 32652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson retval = 1; 32752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson 328cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); 329cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!rsa) { 330779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson fprintf(stderr, "Error parsing data key in %s\n", state->name); 331cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 332cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 333cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t more = key_block->key_block_size; 334cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbFirmwarePreambleHeader *preamble = 335cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (VbFirmwarePreambleHeader *)(state->my_area->buf + more); 336cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 337cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != VerifyFirmwarePreamble(preamble, 338cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson len - more, rsa)) { 339cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("%s is invalid\n", state->name); 340cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 341cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 342cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 343cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson uint32_t flags = VbGetFirmwarePreambleFlags(preamble); 344779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Firmware Preamble:\n"); 345cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Size: %" PRIu64 "\n", 346cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->preamble_size); 347cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Header version: %" PRIu32 ".%" PRIu32 "\n", 348cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->header_version_major, preamble->header_version_minor); 349cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Firmware version: %" PRIu64 "\n", 350cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->firmware_version); 351cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VbPublicKey *kernel_subkey = &preamble->kernel_subkey; 352cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Kernel key algorithm: %" PRIu64 " %s\n", 353cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson kernel_subkey->algorithm, 354cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (kernel_subkey->algorithm < kNumAlgorithms ? 355cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson algo_strings[kernel_subkey->algorithm] : "(invalid)")); 35652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (kernel_subkey->algorithm >= kNumAlgorithms) 35752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson retval = 1; 358cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Kernel key version: %" PRIu64 "\n", 359cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson kernel_subkey->key_version); 360cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Kernel key sha1sum: "); 361cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson PrintPubKeySha1Sum(kernel_subkey); 362cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("\n"); 363cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Firmware body size: %" PRIu64 "\n", 364cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson preamble->body_signature.data_size); 365cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf(" Preamble flags: %" PRIu32 "\n", flags); 366cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 367cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 368cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) { 369779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson printf("Preamble requests USE_RO_NORMAL;" 370779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " skipping body verification.\n"); 371cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson goto done; 372cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 373cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 374cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* We'll need to get the firmware body from somewhere... */ 375779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (fw_body_area && (fw_body_area->_flags & AREA_IS_VALID)) { 376cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fv_data = fw_body_area->buf; 377cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fv_size = fw_body_area->len; 378cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 379cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 380cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!fv_data) { 381cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("No firmware body available to verify.\n"); 38252a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (option.strict) 38352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson return 1; 38408efd1ee358c546c968918a24b45219d7003cecaBill Richardson return 0; 385cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 386cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 387cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (VBOOT_SUCCESS != 388cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) { 389779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson fprintf(stderr, "Error verifying firmware body.\n"); 390cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 391cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 392cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 393cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsondone: 394cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* Can't trust the BIOS unless everything is signed, 395cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson * but standalone files are okay. */ 396cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if ((state->component == CB_FW_PREAMBLE) || 397cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson (sign_key && good_sig)) { 398cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!(flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL)) 399cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("Body verification succeeded.\n"); 400cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->my_area->_flags |= AREA_IS_VALID; 401cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } else { 40208efd1ee358c546c968918a24b45219d7003cecaBill Richardson printf("Seems legit, but the signature is unverified.\n"); 40352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (option.strict) 40452a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson retval = 1; 405cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 406cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 40752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson return retval; 408cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 409cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 4105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonint futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state) 4115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson{ 4125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf; 4145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t len = state->my_area->len; 4155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbPublicKey *sign_key = option.k; 4165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint8_t *kernel_blob = 0; 417bd2eb59ded600c7a62b396f41dcf6937d567dca2Bill Richardson uint64_t kernel_size = 0; 4185f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson int good_sig = 0; 41952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson int retval = 0; 420f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen uint64_t vmlinuz_header_size = 0; 421f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen uint64_t vmlinuz_header_address = 0; 42280e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh uint32_t flags = 0; 4235f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4245f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Check the hash... */ 4255f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) { 4265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("%s keyblock component is invalid\n", state->name); 4275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 4285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* If we have a key, check the signature too */ 4315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (sign_key && VBOOT_SUCCESS == 4325f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson KeyBlockVerify(key_block, len, sign_key, 0)) 4335f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson good_sig = 1; 4345f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4355f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Kernel partition: %s\n", state->in_filename); 4365f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson show_keyblock(key_block, NULL, !!sign_key, good_sig); 4375f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 43852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (option.strict && (!sign_key || !good_sig)) 43952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson retval = 1; 44052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson 4415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); 4425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!rsa) { 4435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error parsing data key in %s\n", state->name); 4445f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 4455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson uint32_t more = key_block->key_block_size; 4475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson VbKernelPreambleHeader *preamble = 4485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson (VbKernelPreambleHeader *)(state->my_area->buf + more); 4495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (VBOOT_SUCCESS != VerifyKernelPreamble(preamble, 4515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson len - more, rsa)) { 4525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("%s is invalid\n", state->name); 4535f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 4545f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 4555f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 4565f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Kernel Preamble:\n"); 4575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Size: 0x%" PRIx64 "\n", 4585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->preamble_size); 4595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Header version: %" PRIu32 ".%" PRIu32 "\n", 4605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->header_version_major, 4615f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->header_version_minor); 4625f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Kernel version: %" PRIu64 "\n", 4635f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->kernel_version); 4645f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Body load address: 0x%" PRIx64 "\n", 4655f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->body_load_address); 4665f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Body size: 0x%" PRIx64 "\n", 4675f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->body_signature.data_size); 4685f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Bootloader address: 0x%" PRIx64 "\n", 4695f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->bootloader_address); 4705f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf(" Bootloader size: 0x%" PRIx64 "\n", 4715f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson preamble->bootloader_size); 4725f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 473f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen if (VbGetKernelVmlinuzHeader(preamble, 474f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen &vmlinuz_header_address, 475f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen &vmlinuz_header_size) 476f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen != VBOOT_SUCCESS) { 477f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen fprintf(stderr, "Unable to retrieve Vmlinuz Header!"); 478f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen return 1; 479f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen } 480f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen if (vmlinuz_header_size) { 481f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen printf(" Vmlinuz_header address: 0x%" PRIx64 "\n", 482f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen vmlinuz_header_address); 483f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen printf(" Vmlinuz header size: 0x%" PRIx64 "\n", 484f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen vmlinuz_header_size); 485f1f53b3732f235da15a50080db6e7bbd4666e390Shelley Chen } 4865f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 48780e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) 48880e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh flags = preamble->flags; 48980e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh printf(" Flags: 0x%" PRIx32 "\n", flags); 49080e779d50b52cd97c9d5896a3b75fa8118ee488fFurquan Shaikh 4915f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* Verify kernel body */ 4925f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.fv) { 4935f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* It's in a separate file, which we've already read in */ 4945f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_blob = option.fv; 4955f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_size = option.fv_size; 496bd2eb59ded600c7a62b396f41dcf6937d567dca2Bill Richardson } else if (state->my_area->len > option.padding) { 4975f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* It should be at an offset within the input file. */ 4985f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_blob = state->my_area->buf + option.padding; 4995f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson kernel_size = state->my_area->len - option.padding; 5005f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 5015f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5025f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!kernel_blob) { 5035f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson /* TODO: Is this always a failure? The preamble is okay. */ 5045f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "No kernel blob available to verify.\n"); 5055f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 5065f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 5075f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5085f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (0 != VerifyData(kernel_blob, kernel_size, 5095f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson &preamble->body_signature, rsa)) { 5105f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error verifying kernel body.\n"); 5115f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson return 1; 5125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 5135f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5145f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Body verification succeeded.\n"); 5155f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 5165f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble)); 5175f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 51852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson return retval; 5195f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson} 5205f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 521cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonint futil_cb_show_begin(struct futil_traverse_state_s *state) 522cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 523cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (state->in_type) { 524cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_UNKNOWN: 525cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unable to determine type of %s\n", 526cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state->in_filename); 527cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 1; 528cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 529cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_BIOS_IMAGE: 530cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case FILE_TYPE_OLD_BIOS_IMAGE: 531cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson printf("BIOS: %s\n", state->in_filename); 532cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 533cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 534cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 535cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 536cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 537cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return 0; 538cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 539cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 5405f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardsonenum no_short_opts { 5415f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson OPT_PADDING = 1000, 5425f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson}; 5435f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 544779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic const char usage[] = "\n" 5452559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n" 546779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 547779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Where FILE could be a\n" 548779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 54952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson "%s" 550779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " keyblock (.keyblock)\n" 551779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " firmware preamble signature (VBLOCK_A/B)\n" 552779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " firmware image (bios.bin)\n" 553779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson " kernel partition (/dev/sda2, /dev/mmcblk0p2)\n" 554779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n" 555779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Options:\n" 5562559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson " -t Just show the type of each file\n" 5575f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -k|--publickey FILE" 5585f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " Use this public key for validation\n" 5595f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n" 5605f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson " --pad NUM Kernel vblock padding size\n" 56152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson "%s" 562779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "\n"; 563779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson 564779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *prog) 565cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 56652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson if (strcmp(prog, "verify")) 56752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson printf(usage, prog, 56852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson " public key (.vbpubk)\n", 56952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson " --strict " 57052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson "Fail unless all signatures are valid\n"); 57152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson else 57252a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson printf(usage, prog, "", 57352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson "\nIt will fail unless all signatures are valid\n"); 574cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 575cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 576cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic const struct option long_opts[] = { 577cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson /* name hasarg *flag val */ 5785f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"publickey", 1, 0, 'k'}, 5795f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"fv", 1, 0, 'f'}, 5805f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson {"pad", 1, NULL, OPT_PADDING}, 58152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson {"verify", 0, &option.strict, 1}, 582e192e7f6cea5f2c4556b729bf57ef1f552e0242aBill Richardson {"debug", 0, &debugging_enabled, 1}, 583cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson {NULL, 0, NULL, 0}, 584cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson}; 5852559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonstatic char *short_opts = ":f:k:t"; 5862559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson 5872559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson 5882559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsonstatic void show_type(char *filename) 5892559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson{ 5902559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson enum futil_file_err err; 5912559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson enum futil_file_type type; 5922559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson err = futil_file_type(filename, &type); 5932559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson switch (err) { 5942559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case FILE_ERR_NONE: 5952559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson printf("%s:\t%s\n", filename, futil_file_type_str(type)); 5962559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 5972559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case FILE_ERR_DIR: 5982559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson printf("%s:\t%s\n", filename, "directory"); 5992559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 6002559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case FILE_ERR_CHR: 6012559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson printf("%s:\t%s\n", filename, "character special"); 6022559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 6032559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case FILE_ERR_FIFO: 6042559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson printf("%s:\t%s\n", filename, "FIFO"); 6052559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 6062559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case FILE_ERR_SOCK: 6072559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson printf("%s:\t%s\n", filename, "socket"); 6082559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 6092559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson default: 6102559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 6112559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson } 6122559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson} 613cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 614cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardsonstatic int do_show(int argc, char *argv[]) 615cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson{ 616cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson char *infile = 0; 617cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int ifd, i; 618cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson int errorcnt = 0; 619cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson struct futil_traverse_state_s state; 620b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson uint8_t *buf; 621b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson uint32_t buf_len; 6225f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson char *e = 0; 623cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 624cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson opterr = 0; /* quiet, you */ 625cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { 626cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson switch (i) { 627cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case 'f': 6285f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.fv = ReadFile(optarg, &option.fv_size); 6295f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!option.fv) { 6305f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, "Error reading %s: %s\n", 6315f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson optarg, strerror(errno)); 632cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 633cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 634cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 635cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case 'k': 636cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson option.k = PublicKeyRead(optarg); 637cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (!option.k) { 638cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error reading %s\n", optarg); 639cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 640cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 641cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 6422559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson case 't': 6432559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson option.t_flag = 1; 6442559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson break; 6455f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson case OPT_PADDING: 6465f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson option.padding = strtoul(optarg, &e, 0); 6475f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (!*optarg || (e && *e)) { 6485f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson fprintf(stderr, 6495f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson "Invalid --padding \"%s\"\n", optarg); 6505f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson errorcnt++; 6515f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson } 6525f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson break; 653cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 654cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case '?': 655cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (optopt) 656cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unrecognized option: -%c\n", 657cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson optopt); 658cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson else 659cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Unrecognized option\n"); 660cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 661cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 662cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson case ':': 663cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Missing argument to -%c\n", optopt); 664cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 665cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson break; 666779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson case 0: /* handled option */ 667779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson break; 668cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson default: 669cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson DIE; 670cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 671cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 672cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 673779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson if (errorcnt) { 674779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 675779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson return 1; 676779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson } 677cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 678cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (argc - optind < 1) { 679cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "ERROR: missing input filename\n"); 680779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 681779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson return 1; 682cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 683cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 6842559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson if (option.t_flag) { 6852559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson for (i = optind; i < argc; i++) 6862559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson show_type(argv[i]); 6872559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson goto done; 6882559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson } 6892559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardson 690cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson for (i = optind; i < argc; i++) { 691cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile = argv[i]; 692cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson ifd = open(infile, O_RDONLY); 693cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (ifd < 0) { 694cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 695cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Can't open %s: %s\n", 696cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile, strerror(errno)); 697b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson continue; 698b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson } 699b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 700b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) { 701b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt++; 702b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson goto boo; 703cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 704cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 705cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson memset(&state, 0, sizeof(state)); 706cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state.in_filename = infile ? infile : "<none>"; 707cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson state.op = FUTIL_OP_SHOW; 708cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 709b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt += futil_traverse(buf, buf_len, &state, 710b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson FILE_TYPE_UNKNOWN); 711b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson 7125f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson 713b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardson errorcnt += futil_unmap_file(ifd, MAP_RO, buf, buf_len); 714cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 715b0f1cc5e22e87a3ef1655643116991673dd1b531Bill Richardsonboo: 716cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (close(ifd)) { 717cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson errorcnt++; 718cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson fprintf(stderr, "Error when closing %s: %s\n", 719cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson infile, strerror(errno)); 720cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 721cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson } 722cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 7232559338dbdacbcbd3ae426337403196135bbc7e8Bill Richardsondone: 724cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson if (option.k) 725cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson free(option.k); 7265f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson if (option.fv) 7275f2696d2ff09d7c9c5c6125e9f0a62e56e54e0b8Bill Richardson free(option.fv); 728cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 729cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson return !!errorcnt; 730cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson} 731cf6e78dbd54684ebba0c3bfc2524426f61193416Bill Richardson 732779796f57e1e0236ea502248ede2cbea986fca21Bill RichardsonDECLARE_FUTIL_COMMAND(show, do_show, 7331eae873b6194db25781233d7a4aaee6a34160eecBill Richardson VBOOT_VERSION_ALL, 734779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson "Display the content of various binary components", 735779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help); 73652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson 73752a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardsonstatic int do_verify(int argc, char *argv[]) 73852a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson{ 73952a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson option.strict = 1; 74052a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson return do_show(argc, argv); 74152a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson} 74252a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson 74352a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill RichardsonDECLARE_FUTIL_COMMAND(verify, do_verify, 7441eae873b6194db25781233d7a4aaee6a34160eecBill Richardson VBOOT_VERSION_ALL, 74552a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson "Verify the signatures of various binary components", 74652a15f96ac009222ebf7d1299c7d17825e5a4ab5Bill Richardson print_help); 747