Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2014 The Chromium OS Authors. All rights reserved. |
| 3 | * Use of this source code is governed by a BSD-style license that can be |
| 4 | * found in the LICENSE file. |
| 5 | */ |
Bill Richardson | 3855e2e | 2015-02-05 10:44:54 -0800 | [diff] [blame] | 6 | |
| 7 | #define OPENSSL_NO_SHA |
| 8 | #include <openssl/rsa.h> |
| 9 | |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 10 | #include <errno.h> |
| 11 | #include <fcntl.h> |
| 12 | #include <getopt.h> |
| 13 | #include <inttypes.h> |
| 14 | #include <stddef.h> |
| 15 | #include <stdint.h> |
| 16 | #include <stdio.h> |
| 17 | #include <stdlib.h> |
| 18 | #include <string.h> |
| 19 | #include <sys/stat.h> |
| 20 | #include <sys/types.h> |
| 21 | #include <unistd.h> |
| 22 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 23 | #include "2sysincludes.h" |
| 24 | #include "2api.h" |
| 25 | #include "2common.h" |
| 26 | #include "2sha.h" |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 27 | #include "file_type.h" |
Bill Richardson | 091c7b1 | 2015-03-26 16:58:49 -0700 | [diff] [blame] | 28 | #include "file_type_bios.h" |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 29 | #include "fmap.h" |
| 30 | #include "futility.h" |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 31 | #include "futility_options.h" |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 32 | #include "host_common.h" |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 33 | #include "host_key2.h" |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 34 | #include "util_misc.h" |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 35 | #include "vb1_helper.h" |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 36 | #include "vb2_common.h" |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 37 | |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 38 | /* Options */ |
| 39 | struct show_option_s show_option = { |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 40 | .padding = 65536, |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 41 | .type = FILE_TYPE_UNKNOWN, |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 42 | }; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 43 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 44 | /* Shared work buffer */ |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 45 | static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]; |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 46 | static struct vb2_workbuf wb; |
| 47 | |
| 48 | void show_pubkey(const struct vb2_packed_key *pubkey, const char *sp) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 49 | { |
Bill Richardson | add997f | 2015-02-04 16:47:16 -0800 | [diff] [blame] | 50 | printf("%sVboot API: 1.0\n", sp); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 51 | printf("%sAlgorithm: %d %s\n", sp, pubkey->algorithm, |
Randall Spangler | 46a382d | 2016-10-18 12:00:07 -0700 | [diff] [blame] | 52 | vb2_get_crypto_algorithm_name(pubkey->algorithm)); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 53 | printf("%sKey Version: %d\n", sp, pubkey->key_version); |
| 54 | printf("%sKey sha1sum: %s\n", |
| 55 | sp, packed_key_sha1_string(pubkey)); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 56 | } |
| 57 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 58 | static void show_keyblock(struct vb2_keyblock *keyblock, const char *name, |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 59 | int sign_key, int good_sig) |
| 60 | { |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 61 | if (name) |
| 62 | printf("Key block: %s\n", name); |
| 63 | else |
| 64 | printf("Key block:\n"); |
| 65 | printf(" Signature: %s\n", |
| 66 | sign_key ? (good_sig ? "valid" : "invalid") : "ignored"); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 67 | printf(" Size: 0x%x\n", keyblock->keyblock_size); |
| 68 | printf(" Flags: %d ", keyblock->keyblock_flags); |
| 69 | if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_DEVELOPER_0) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 70 | printf(" !DEV"); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 71 | if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_DEVELOPER_1) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 72 | printf(" DEV"); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 73 | if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_RECOVERY_0) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 74 | printf(" !REC"); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 75 | if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_RECOVERY_1) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 76 | printf(" REC"); |
| 77 | printf("\n"); |
| 78 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 79 | struct vb2_packed_key *data_key = &keyblock->data_key; |
| 80 | printf(" Data key algorithm: %d %s\n", data_key->algorithm, |
Randall Spangler | 46a382d | 2016-10-18 12:00:07 -0700 | [diff] [blame] | 81 | vb2_get_crypto_algorithm_name(data_key->algorithm)); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 82 | printf(" Data key version: %d\n", data_key->key_version); |
| 83 | printf(" Data key sha1sum: %s\n", |
| 84 | packed_key_sha1_string(data_key)); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 85 | } |
| 86 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 87 | int ft_show_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 88 | { |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 89 | struct vb2_packed_key *pubkey = (struct vb2_packed_key *)buf; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 90 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 91 | if (!packed_key_looks_ok(pubkey, len)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 92 | printf("%s looks bogus\n", name); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 93 | return 1; |
| 94 | } |
| 95 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 96 | printf("Public Key file: %s\n", name); |
Bill Richardson | 091c7b1 | 2015-03-26 16:58:49 -0700 | [diff] [blame] | 97 | show_pubkey(pubkey, " "); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 98 | |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 99 | return 0; |
| 100 | } |
| 101 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 102 | int ft_show_privkey(const char *name, uint8_t *buf, uint32_t len, void *data) |
Bill Richardson | 4805f18 | 2015-01-30 22:21:10 -0800 | [diff] [blame] | 103 | { |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 104 | struct vb2_packed_private_key *pkey = |
| 105 | (struct vb2_packed_private_key *)buf; |
| 106 | struct vb2_private_key key; |
| 107 | const unsigned char *start = pkey->key_data; |
Bill Richardson | 4805f18 | 2015-01-30 22:21:10 -0800 | [diff] [blame] | 108 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 109 | if (len <= sizeof(*pkey)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 110 | printf("%s looks bogus\n", name); |
| 111 | return 1; |
| 112 | } |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 113 | len -= sizeof(*pkey); |
Bill Richardson | 3855e2e | 2015-02-05 10:44:54 -0800 | [diff] [blame] | 114 | key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, len); |
Bill Richardson | 4805f18 | 2015-01-30 22:21:10 -0800 | [diff] [blame] | 115 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 116 | printf("Private Key file: %s\n", name); |
Bill Richardson | add997f | 2015-02-04 16:47:16 -0800 | [diff] [blame] | 117 | printf(" Vboot API: 1.0\n"); |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 118 | printf(" Algorithm: %u %s\n", pkey->algorithm, |
Randall Spangler | 46a382d | 2016-10-18 12:00:07 -0700 | [diff] [blame] | 119 | vb2_get_crypto_algorithm_name(pkey->algorithm)); |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 120 | printf(" Key sha1sum: %s\n", |
| 121 | private_key_sha1_string(&key)); |
Bill Richardson | 4805f18 | 2015-01-30 22:21:10 -0800 | [diff] [blame] | 122 | |
Bill Richardson | 4805f18 | 2015-01-30 22:21:10 -0800 | [diff] [blame] | 123 | return 0; |
| 124 | } |
| 125 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 126 | int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 127 | { |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 128 | struct vb2_keyblock *block = (struct vb2_keyblock *)buf; |
| 129 | struct vb2_public_key *sign_key = show_option.k; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 130 | int good_sig = 0; |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 131 | int retval = 0; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 132 | |
| 133 | /* Check the hash only first */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 134 | if (0 != vb2_verify_keyblock_hash(block, len, &wb)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 135 | printf("%s is invalid\n", name); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 136 | return 1; |
| 137 | } |
| 138 | |
| 139 | /* Check the signature if we have one */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 140 | if (sign_key && |
| 141 | VB2_SUCCESS == vb2_verify_keyblock(block, len, sign_key, &wb)) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 142 | good_sig = 1; |
| 143 | |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 144 | if (show_option.strict && (!sign_key || !good_sig)) |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 145 | retval = 1; |
| 146 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 147 | show_keyblock(block, name, !!sign_key, good_sig); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 148 | |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 149 | return retval; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 150 | } |
| 151 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 152 | int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len, |
| 153 | void *data) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 154 | { |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 155 | struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf; |
Bill Richardson | 091c7b1 | 2015-03-26 16:58:49 -0700 | [diff] [blame] | 156 | struct bios_state_s *state = (struct bios_state_s *)data; |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 157 | struct vb2_public_key *sign_key = show_option.k; |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 158 | uint8_t *fv_data = show_option.fv; |
| 159 | uint64_t fv_size = show_option.fv_size; |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 160 | struct bios_area_s *fw_body_area = 0; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 161 | int good_sig = 0; |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 162 | int retval = 0; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 163 | |
| 164 | /* Check the hash... */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 165 | if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 166 | printf("%s keyblock component is invalid\n", name); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 167 | return 1; |
| 168 | } |
| 169 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 170 | /* |
| 171 | * If we're being invoked while poking through a BIOS, we should |
| 172 | * be given the keys and data to verify as part of the state. If we |
| 173 | * have no state, then we're just looking at a standalone fw_preamble, |
| 174 | * so we'll have to get any keys or data from options. |
| 175 | */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 176 | struct vb2_public_key root_key; |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 177 | if (state) { |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 178 | if (!sign_key && |
| 179 | state->rootkey.is_valid && |
| 180 | VB2_SUCCESS == vb2_unpack_key(&root_key, state->rootkey.buf, |
| 181 | state->rootkey.len)) { |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 182 | /* BIOS should have a rootkey in the GBB */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 183 | sign_key = &root_key; |
| 184 | } |
| 185 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 186 | /* Identify the firmware body for this VBLOCK */ |
| 187 | enum bios_component body_c = state->c == BIOS_FMAP_VBLOCK_A |
| 188 | ? BIOS_FMAP_FW_MAIN_A |
| 189 | : BIOS_FMAP_FW_MAIN_B; |
| 190 | fw_body_area = &state->area[body_c]; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 191 | } |
| 192 | |
| 193 | /* If we have a key, check the signature too */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 194 | if (sign_key && VB2_SUCCESS == |
| 195 | vb2_verify_keyblock(keyblock, len, sign_key, &wb)) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 196 | good_sig = 1; |
| 197 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 198 | show_keyblock(keyblock, name, !!sign_key, good_sig); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 199 | |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 200 | if (show_option.strict && (!sign_key || !good_sig)) |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 201 | retval = 1; |
| 202 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 203 | struct vb2_public_key data_key; |
| 204 | if (VB2_SUCCESS != |
| 205 | vb2_unpack_key(&data_key, (const uint8_t *)&keyblock->data_key, |
| 206 | keyblock->data_key.key_offset + |
| 207 | keyblock->data_key.key_size)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 208 | fprintf(stderr, "Error parsing data key in %s\n", name); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 209 | return 1; |
| 210 | } |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 211 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 212 | uint32_t more = keyblock->keyblock_size; |
| 213 | struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(buf + more); |
| 214 | if (VB2_SUCCESS != vb2_verify_fw_preamble(pre2, len - more, |
| 215 | &data_key, &wb)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 216 | printf("%s is invalid\n", name); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 217 | return 1; |
| 218 | } |
| 219 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 220 | uint32_t flags = pre2->flags; |
| 221 | if (pre2->header_version_minor < 1) |
| 222 | flags = 0; /* Old 2.0 structure didn't have flags */ |
| 223 | |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 224 | printf("Firmware Preamble:\n"); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 225 | printf(" Size: %d\n", pre2->preamble_size); |
| 226 | printf(" Header version: %d.%d\n", |
| 227 | pre2->header_version_major, pre2->header_version_minor); |
| 228 | printf(" Firmware version: %d\n", pre2->firmware_version); |
| 229 | |
| 230 | struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey; |
| 231 | printf(" Kernel key algorithm: %d %s\n", |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 232 | kernel_subkey->algorithm, |
Randall Spangler | 46a382d | 2016-10-18 12:00:07 -0700 | [diff] [blame] | 233 | vb2_get_crypto_algorithm_name(kernel_subkey->algorithm)); |
| 234 | if (kernel_subkey->algorithm >= VB2_ALG_COUNT) |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 235 | retval = 1; |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 236 | printf(" Kernel key version: %d\n", kernel_subkey->key_version); |
| 237 | printf(" Kernel key sha1sum: %s\n", |
| 238 | packed_key_sha1_string(kernel_subkey)); |
| 239 | printf(" Firmware body size: %d\n", pre2->body_signature.data_size); |
| 240 | printf(" Preamble flags: %d\n", flags); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 241 | |
Randall Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 242 | if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL) { |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 243 | printf("Preamble requests USE_RO_NORMAL;" |
| 244 | " skipping body verification.\n"); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 245 | goto done; |
| 246 | } |
| 247 | |
| 248 | /* We'll need to get the firmware body from somewhere... */ |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 249 | if (fw_body_area && fw_body_area->is_valid) { |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 250 | fv_data = fw_body_area->buf; |
| 251 | fv_size = fw_body_area->len; |
| 252 | } |
| 253 | |
| 254 | if (!fv_data) { |
| 255 | printf("No firmware body available to verify.\n"); |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 256 | if (show_option.strict) |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 257 | return 1; |
Bill Richardson | 08efd1e | 2014-09-04 22:53:41 -0700 | [diff] [blame] | 258 | return 0; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 259 | } |
| 260 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 261 | if (VB2_SUCCESS != |
| 262 | vb2_verify_data(fv_data, fv_size, &pre2->body_signature, |
| 263 | &data_key, &wb)) { |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 264 | fprintf(stderr, "Error verifying firmware body.\n"); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 265 | return 1; |
| 266 | } |
| 267 | |
| 268 | done: |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 269 | /* Can't trust the BIOS unless everything is signed (in which case |
| 270 | * we've already returned), but standalone files are okay. */ |
| 271 | if (state || (sign_key && good_sig)) { |
Randall Spangler | 814aaf0 | 2016-06-17 10:48:16 -0700 | [diff] [blame] | 272 | if (!(flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL)) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 273 | printf("Body verification succeeded.\n"); |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 274 | if (state) |
| 275 | state->area[state->c].is_valid = 1; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 276 | } else { |
Bill Richardson | 08efd1e | 2014-09-04 22:53:41 -0700 | [diff] [blame] | 277 | printf("Seems legit, but the signature is unverified.\n"); |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 278 | if (show_option.strict) |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 279 | retval = 1; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 280 | } |
| 281 | |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 282 | return retval; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 283 | } |
| 284 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 285 | int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len, |
| 286 | void *data) |
| 287 | { |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 288 | struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf; |
| 289 | struct vb2_public_key *sign_key = show_option.k; |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 290 | int retval = 0; |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 291 | |
| 292 | /* Check the hash... */ |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 293 | if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 294 | printf("%s keyblock component is invalid\n", name); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 295 | return 1; |
| 296 | } |
| 297 | |
| 298 | /* If we have a key, check the signature too */ |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 299 | int good_sig = 0; |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 300 | if (sign_key && VB2_SUCCESS == |
| 301 | vb2_verify_keyblock(keyblock, len, sign_key, &wb)) |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 302 | good_sig = 1; |
| 303 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 304 | printf("Kernel partition: %s\n", name); |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 305 | show_keyblock(keyblock, NULL, !!sign_key, good_sig); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 306 | |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 307 | if (show_option.strict && (!sign_key || !good_sig)) |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 308 | retval = 1; |
| 309 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 310 | struct vb2_public_key data_key; |
| 311 | if (VB2_SUCCESS != |
| 312 | vb2_unpack_key(&data_key, (const uint8_t *)&keyblock->data_key, |
| 313 | keyblock->data_key.key_offset + |
| 314 | keyblock->data_key.key_size)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 315 | fprintf(stderr, "Error parsing data key in %s\n", name); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 316 | return 1; |
| 317 | } |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 318 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 319 | uint32_t more = keyblock->keyblock_size; |
| 320 | struct vb2_kernel_preamble *pre2 = |
| 321 | (struct vb2_kernel_preamble *)(buf + more); |
| 322 | |
| 323 | if (VB2_SUCCESS != vb2_verify_kernel_preamble(pre2, len - more, |
| 324 | &data_key, &wb)) { |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 325 | printf("%s is invalid\n", name); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 326 | return 1; |
| 327 | } |
| 328 | |
| 329 | printf("Kernel Preamble:\n"); |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 330 | printf(" Size: 0x%x\n", pre2->preamble_size); |
| 331 | printf(" Header version: %u.%u\n", |
| 332 | pre2->header_version_major, |
| 333 | pre2->header_version_minor); |
| 334 | printf(" Kernel version: %u\n", pre2->kernel_version); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 335 | printf(" Body load address: 0x%" PRIx64 "\n", |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 336 | pre2->body_load_address); |
| 337 | printf(" Body size: 0x%x\n", |
| 338 | pre2->body_signature.data_size); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 339 | printf(" Bootloader address: 0x%" PRIx64 "\n", |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 340 | pre2->bootloader_address); |
| 341 | printf(" Bootloader size: 0x%x\n", pre2->bootloader_size); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 342 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 343 | uint64_t vmlinuz_header_address = 0; |
| 344 | uint32_t vmlinuz_header_size = 0; |
| 345 | vb2_kernel_get_vmlinuz_header(pre2, |
| 346 | &vmlinuz_header_address, |
| 347 | &vmlinuz_header_size); |
Shelley Chen | f1f53b3 | 2015-01-08 09:13:44 -0800 | [diff] [blame] | 348 | if (vmlinuz_header_size) { |
| 349 | printf(" Vmlinuz_header address: 0x%" PRIx64 "\n", |
| 350 | vmlinuz_header_address); |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 351 | printf(" Vmlinuz header size: 0x%x\n", |
Shelley Chen | f1f53b3 | 2015-01-08 09:13:44 -0800 | [diff] [blame] | 352 | vmlinuz_header_size); |
| 353 | } |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 354 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 355 | printf(" Flags: 0x%x\n", vb2_kernel_get_flags(pre2)); |
Furquan Shaikh | 80e779d | 2015-02-03 15:34:29 -0800 | [diff] [blame] | 356 | |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 357 | /* Verify kernel body */ |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 358 | uint8_t *kernel_blob = 0; |
| 359 | uint64_t kernel_size = 0; |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 360 | if (show_option.fv) { |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 361 | /* It's in a separate file, which we've already read in */ |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 362 | kernel_blob = show_option.fv; |
| 363 | kernel_size = show_option.fv_size; |
| 364 | } else if (len > show_option.padding) { |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 365 | /* It should be at an offset within the input file. */ |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 366 | kernel_blob = buf + show_option.padding; |
| 367 | kernel_size = len - show_option.padding; |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 368 | } |
| 369 | |
| 370 | if (!kernel_blob) { |
| 371 | /* TODO: Is this always a failure? The preamble is okay. */ |
| 372 | fprintf(stderr, "No kernel blob available to verify.\n"); |
| 373 | return 1; |
| 374 | } |
| 375 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 376 | if (VB2_SUCCESS != |
| 377 | vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature, |
| 378 | &data_key, &wb)) { |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 379 | fprintf(stderr, "Error verifying kernel body.\n"); |
| 380 | return 1; |
| 381 | } |
| 382 | |
| 383 | printf("Body verification succeeded.\n"); |
| 384 | |
Randall Spangler | 158b296 | 2016-06-03 14:00:27 -0700 | [diff] [blame] | 385 | printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(pre2)); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 386 | |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 387 | return retval; |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 388 | } |
| 389 | |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 390 | enum no_short_opts { |
| 391 | OPT_PADDING = 1000, |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 392 | OPT_TYPE, |
Bill Richardson | 02ac288 | 2015-10-15 00:23:18 -0700 | [diff] [blame] | 393 | OPT_PUBKEY, |
Bill Richardson | 01466d3 | 2015-03-11 11:21:47 -0700 | [diff] [blame] | 394 | OPT_HELP, |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 395 | }; |
| 396 | |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 397 | static const char usage[] = "\n" |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 398 | "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n" |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 399 | "\n" |
Bill Richardson | eff3100 | 2015-04-06 13:02:40 -0700 | [diff] [blame] | 400 | "Where FILE could be\n" |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 401 | "\n" |
Daisuke Nojiri | c3daa95 | 2016-09-22 09:48:20 -0700 | [diff] [blame] | 402 | " a BDB\n" |
Bill Richardson | eff3100 | 2015-04-06 13:02:40 -0700 | [diff] [blame] | 403 | " a keyblock (.keyblock)\n" |
| 404 | " a firmware preamble signature (VBLOCK_A/B)\n" |
| 405 | " a firmware image (bios.bin)\n" |
| 406 | " a kernel partition (/dev/sda2, /dev/mmcblk0p2)\n" |
| 407 | " keys in various formats (.vbpubk, .vbprivk, .pem)\n" |
| 408 | " several other file types related to verified boot\n" |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 409 | "\n" |
| 410 | "Options:\n" |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 411 | " -t Just show the type of each file\n" |
Bill Richardson | eff3100 | 2015-04-06 13:02:40 -0700 | [diff] [blame] | 412 | " --type TYPE Override the detected file type\n" |
| 413 | " Use \"--type help\" for a list\n" |
| 414 | "Type-specific options:\n" |
Bill Richardson | 02ac288 | 2015-10-15 00:23:18 -0700 | [diff] [blame] | 415 | " -k|--publickey FILE.vbpubk Public key in vb1 format\n" |
| 416 | " --pubkey FILE.vpubk2 Public key in vb2 format\n" |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 417 | " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n" |
| 418 | " --pad NUM Kernel vblock padding size\n" |
Bill Richardson | eff3100 | 2015-04-06 13:02:40 -0700 | [diff] [blame] | 419 | " --strict " |
| 420 | "Fail unless all signatures are valid\n" |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 421 | "\n"; |
| 422 | |
Bill Richardson | 49a422f | 2015-03-05 13:49:36 -0800 | [diff] [blame] | 423 | static void print_help(int argc, char *argv[]) |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 424 | { |
Bill Richardson | eff3100 | 2015-04-06 13:02:40 -0700 | [diff] [blame] | 425 | if (!strcmp(argv[0], "verify")) |
| 426 | printf("\nUsage: " MYNAME " %s [OPTIONS] FILE [...]\n\n" |
| 427 | "This is just an alias for\n\n" |
| 428 | " " MYNAME " show --strict\n\n", |
| 429 | argv[0]); |
| 430 | |
| 431 | printf(usage, "show"); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 432 | } |
| 433 | |
| 434 | static const struct option long_opts[] = { |
| 435 | /* name hasarg *flag val */ |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 436 | {"publickey", 1, 0, 'k'}, |
| 437 | {"fv", 1, 0, 'f'}, |
| 438 | {"pad", 1, NULL, OPT_PADDING}, |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 439 | {"type", 1, NULL, OPT_TYPE}, |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 440 | {"strict", 0, &show_option.strict, 1}, |
Bill Richardson | 02ac288 | 2015-10-15 00:23:18 -0700 | [diff] [blame] | 441 | {"pubkey", 1, NULL, OPT_PUBKEY}, |
Bill Richardson | 01466d3 | 2015-03-11 11:21:47 -0700 | [diff] [blame] | 442 | {"help", 0, NULL, OPT_HELP}, |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 443 | {NULL, 0, NULL, 0}, |
| 444 | }; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 445 | static char *short_opts = ":f:k:t"; |
| 446 | |
| 447 | |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 448 | static int show_type(char *filename) |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 449 | { |
| 450 | enum futil_file_err err; |
| 451 | enum futil_file_type type; |
| 452 | err = futil_file_type(filename, &type); |
| 453 | switch (err) { |
| 454 | case FILE_ERR_NONE: |
Bill Richardson | 4dc1575 | 2015-03-09 19:39:19 -0700 | [diff] [blame] | 455 | printf("%s:\t%s\n", filename, futil_file_type_name(type)); |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 456 | /* Only our recognized types return success */ |
| 457 | return 0; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 458 | case FILE_ERR_DIR: |
| 459 | printf("%s:\t%s\n", filename, "directory"); |
| 460 | break; |
| 461 | case FILE_ERR_CHR: |
| 462 | printf("%s:\t%s\n", filename, "character special"); |
| 463 | break; |
| 464 | case FILE_ERR_FIFO: |
| 465 | printf("%s:\t%s\n", filename, "FIFO"); |
| 466 | break; |
| 467 | case FILE_ERR_SOCK: |
| 468 | printf("%s:\t%s\n", filename, "socket"); |
| 469 | break; |
| 470 | default: |
| 471 | break; |
| 472 | } |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 473 | /* Everything else is an error */ |
| 474 | return 1; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 475 | } |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 476 | |
| 477 | static int do_show(int argc, char *argv[]) |
| 478 | { |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 479 | uint8_t *pubkbuf = NULL; |
| 480 | struct vb2_public_key pubk2; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 481 | char *infile = 0; |
| 482 | int ifd, i; |
| 483 | int errorcnt = 0; |
Bill Richardson | b0f1cc5 | 2014-09-24 00:23:56 -0700 | [diff] [blame] | 484 | uint8_t *buf; |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 485 | uint32_t len; |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 486 | char *e = 0; |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 487 | int type_override = 0; |
| 488 | enum futil_file_type type; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 489 | |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 490 | vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); |
| 491 | |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 492 | opterr = 0; /* quiet, you */ |
| 493 | while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { |
| 494 | switch (i) { |
| 495 | case 'f': |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 496 | show_option.fv = ReadFile(optarg, |
| 497 | &show_option.fv_size); |
| 498 | if (!show_option.fv) { |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 499 | fprintf(stderr, "Error reading %s: %s\n", |
| 500 | optarg, strerror(errno)); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 501 | errorcnt++; |
| 502 | } |
| 503 | break; |
| 504 | case 'k': |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 505 | if (VB2_SUCCESS != |
| 506 | vb2_read_file(optarg, &pubkbuf, &len)) { |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 507 | fprintf(stderr, "Error reading %s\n", optarg); |
| 508 | errorcnt++; |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 509 | break; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 510 | } |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 511 | |
| 512 | if (VB2_SUCCESS != |
| 513 | vb2_unpack_key(&pubk2, pubkbuf, len)) { |
| 514 | fprintf(stderr, "Error unpacking %s\n", optarg); |
| 515 | errorcnt++; |
| 516 | break; |
| 517 | } |
| 518 | |
| 519 | show_option.k = &pubk2; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 520 | break; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 521 | case 't': |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 522 | show_option.t_flag = 1; |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 523 | break; |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 524 | case OPT_PADDING: |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 525 | show_option.padding = strtoul(optarg, &e, 0); |
Bill Richardson | 5f2696d | 2014-09-23 22:03:56 -0700 | [diff] [blame] | 526 | if (!*optarg || (e && *e)) { |
| 527 | fprintf(stderr, |
| 528 | "Invalid --padding \"%s\"\n", optarg); |
| 529 | errorcnt++; |
| 530 | } |
| 531 | break; |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 532 | case OPT_TYPE: |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 533 | if (!futil_str_to_file_type(optarg, |
| 534 | &show_option.type)) { |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 535 | if (!strcasecmp("help", optarg)) |
| 536 | print_file_types_and_exit(errorcnt); |
| 537 | fprintf(stderr, |
| 538 | "Invalid --type \"%s\"\n", optarg); |
| 539 | errorcnt++; |
| 540 | } |
| 541 | type_override = 1; |
| 542 | break; |
Bill Richardson | 02ac288 | 2015-10-15 00:23:18 -0700 | [diff] [blame] | 543 | case OPT_PUBKEY: |
Randall Spangler | ca72512 | 2016-05-25 16:42:44 -0700 | [diff] [blame] | 544 | if (vb21_packed_key_read(&show_option.pkey, optarg)) { |
Bill Richardson | 02ac288 | 2015-10-15 00:23:18 -0700 | [diff] [blame] | 545 | fprintf(stderr, "Error reading %s\n", optarg); |
| 546 | errorcnt++; |
| 547 | } |
| 548 | break; |
Bill Richardson | 01466d3 | 2015-03-11 11:21:47 -0700 | [diff] [blame] | 549 | case OPT_HELP: |
| 550 | print_help(argc, argv); |
| 551 | return !!errorcnt; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 552 | |
| 553 | case '?': |
| 554 | if (optopt) |
| 555 | fprintf(stderr, "Unrecognized option: -%c\n", |
| 556 | optopt); |
| 557 | else |
| 558 | fprintf(stderr, "Unrecognized option\n"); |
| 559 | errorcnt++; |
| 560 | break; |
| 561 | case ':': |
| 562 | fprintf(stderr, "Missing argument to -%c\n", optopt); |
| 563 | errorcnt++; |
| 564 | break; |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 565 | case 0: /* handled option */ |
| 566 | break; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 567 | default: |
| 568 | DIE; |
| 569 | } |
| 570 | } |
| 571 | |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 572 | if (errorcnt) { |
Bill Richardson | 49a422f | 2015-03-05 13:49:36 -0800 | [diff] [blame] | 573 | print_help(argc, argv); |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 574 | return 1; |
| 575 | } |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 576 | |
| 577 | if (argc - optind < 1) { |
| 578 | fprintf(stderr, "ERROR: missing input filename\n"); |
Bill Richardson | 49a422f | 2015-03-05 13:49:36 -0800 | [diff] [blame] | 579 | print_help(argc, argv); |
Bill Richardson | 779796f | 2014-09-23 11:47:40 -0700 | [diff] [blame] | 580 | return 1; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 581 | } |
| 582 | |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 583 | if (show_option.t_flag) { |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 584 | for (i = optind; i < argc; i++) |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 585 | errorcnt += show_type(argv[i]); |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 586 | goto done; |
| 587 | } |
| 588 | |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 589 | for (i = optind; i < argc; i++) { |
| 590 | infile = argv[i]; |
| 591 | ifd = open(infile, O_RDONLY); |
| 592 | if (ifd < 0) { |
| 593 | errorcnt++; |
| 594 | fprintf(stderr, "Can't open %s: %s\n", |
| 595 | infile, strerror(errno)); |
Bill Richardson | b0f1cc5 | 2014-09-24 00:23:56 -0700 | [diff] [blame] | 596 | continue; |
| 597 | } |
| 598 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 599 | if (0 != futil_map_file(ifd, MAP_RO, &buf, &len)) { |
Bill Richardson | b0f1cc5 | 2014-09-24 00:23:56 -0700 | [diff] [blame] | 600 | errorcnt++; |
| 601 | goto boo; |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 602 | } |
| 603 | |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 604 | /* Allow the user to override the type */ |
| 605 | if (type_override) |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 606 | type = show_option.type; |
Bill Richardson | 453ecd1 | 2015-03-26 16:29:10 -0700 | [diff] [blame] | 607 | else |
| 608 | type = futil_file_type_buf(buf, len); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 609 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 610 | errorcnt += futil_file_type_show(type, infile, buf, len); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 611 | |
Bill Richardson | 6ea2f72 | 2015-03-26 15:31:54 -0700 | [diff] [blame] | 612 | errorcnt += futil_unmap_file(ifd, MAP_RO, buf, len); |
Bill Richardson | b0f1cc5 | 2014-09-24 00:23:56 -0700 | [diff] [blame] | 613 | boo: |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 614 | if (close(ifd)) { |
| 615 | errorcnt++; |
| 616 | fprintf(stderr, "Error when closing %s: %s\n", |
| 617 | infile, strerror(errno)); |
| 618 | } |
| 619 | } |
| 620 | |
Bill Richardson | 2559338 | 2015-01-30 12:22:28 -0800 | [diff] [blame] | 621 | done: |
Randall Spangler | 98263a1 | 2016-06-02 16:05:49 -0700 | [diff] [blame] | 622 | if (pubkbuf) |
| 623 | free(pubkbuf); |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 624 | if (show_option.fv) |
| 625 | free(show_option.fv); |
Bill Richardson | cf6e78d | 2014-08-27 15:50:25 -0700 | [diff] [blame] | 626 | |
| 627 | return !!errorcnt; |
| 628 | } |
| 629 | |
Bill Richardson | 01466d3 | 2015-03-11 11:21:47 -0700 | [diff] [blame] | 630 | DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL, |
| 631 | "Display the content of various binary components"); |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 632 | |
| 633 | static int do_verify(int argc, char *argv[]) |
| 634 | { |
Bill Richardson | 1e35c3a | 2015-03-26 16:34:28 -0700 | [diff] [blame] | 635 | show_option.strict = 1; |
Bill Richardson | 52a15f9 | 2014-09-23 22:31:08 -0700 | [diff] [blame] | 636 | return do_show(argc, argv); |
| 637 | } |
| 638 | |
| 639 | DECLARE_FUTIL_COMMAND(verify, do_verify, |
Bill Richardson | 1eae873 | 2015-02-05 12:36:15 -0800 | [diff] [blame] | 640 | VBOOT_VERSION_ALL, |
Bill Richardson | 01466d3 | 2015-03-11 11:21:47 -0700 | [diff] [blame] | 641 | "Verify the signatures of various binary components"); |