blob: 91c24d0b5dfac04af31b5db66babcc41a4816408 [file] [log] [blame]
Bill Richardsoncf6e78d2014-08-27 15:50:25 -07001/*
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 Richardson3855e2e2015-02-05 10:44:54 -08006
7#define OPENSSL_NO_SHA
8#include <openssl/rsa.h>
9
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070010#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 Spangler98263a12016-06-02 16:05:49 -070023#include "2sysincludes.h"
24#include "2api.h"
25#include "2common.h"
26#include "2sha.h"
Bill Richardson25593382015-01-30 12:22:28 -080027#include "file_type.h"
Bill Richardson091c7b12015-03-26 16:58:49 -070028#include "file_type_bios.h"
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070029#include "fmap.h"
30#include "futility.h"
Bill Richardson1e35c3a2015-03-26 16:34:28 -070031#include "futility_options.h"
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070032#include "host_common.h"
Randall Spangler158b2962016-06-03 14:00:27 -070033#include "host_key2.h"
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070034#include "util_misc.h"
Bill Richardson5f2696d2014-09-23 22:03:56 -070035#include "vb1_helper.h"
Randall Spangler98263a12016-06-02 16:05:49 -070036#include "vb2_common.h"
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070037
Bill Richardson1e35c3a2015-03-26 16:34:28 -070038/* Options */
39struct show_option_s show_option = {
Bill Richardson5f2696d2014-09-23 22:03:56 -070040 .padding = 65536,
Bill Richardson453ecd12015-03-26 16:29:10 -070041 .type = FILE_TYPE_UNKNOWN,
Bill Richardson5f2696d2014-09-23 22:03:56 -070042};
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070043
Randall Spangler98263a12016-06-02 16:05:49 -070044/* Shared work buffer */
Randall Spangler158b2962016-06-03 14:00:27 -070045static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE];
Randall Spangler98263a12016-06-02 16:05:49 -070046static struct vb2_workbuf wb;
47
48void show_pubkey(const struct vb2_packed_key *pubkey, const char *sp)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070049{
Bill Richardsonadd997f2015-02-04 16:47:16 -080050 printf("%sVboot API: 1.0\n", sp);
Randall Spangler98263a12016-06-02 16:05:49 -070051 printf("%sAlgorithm: %d %s\n", sp, pubkey->algorithm,
Randall Spangler46a382d2016-10-18 12:00:07 -070052 vb2_get_crypto_algorithm_name(pubkey->algorithm));
Randall Spangler98263a12016-06-02 16:05:49 -070053 printf("%sKey Version: %d\n", sp, pubkey->key_version);
54 printf("%sKey sha1sum: %s\n",
55 sp, packed_key_sha1_string(pubkey));
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070056}
57
Randall Spangler98263a12016-06-02 16:05:49 -070058static void show_keyblock(struct vb2_keyblock *keyblock, const char *name,
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070059 int sign_key, int good_sig)
60{
Bill Richardson779796f2014-09-23 11:47:40 -070061 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 Spangler98263a12016-06-02 16:05:49 -070067 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 Richardsoncf6e78d2014-08-27 15:50:25 -070070 printf(" !DEV");
Randall Spangler98263a12016-06-02 16:05:49 -070071 if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_DEVELOPER_1)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070072 printf(" DEV");
Randall Spangler98263a12016-06-02 16:05:49 -070073 if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_RECOVERY_0)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070074 printf(" !REC");
Randall Spangler98263a12016-06-02 16:05:49 -070075 if (keyblock->keyblock_flags & VB2_KEY_BLOCK_FLAG_RECOVERY_1)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070076 printf(" REC");
77 printf("\n");
78
Randall Spangler98263a12016-06-02 16:05:49 -070079 struct vb2_packed_key *data_key = &keyblock->data_key;
80 printf(" Data key algorithm: %d %s\n", data_key->algorithm,
Randall Spangler46a382d2016-10-18 12:00:07 -070081 vb2_get_crypto_algorithm_name(data_key->algorithm));
Randall Spangler98263a12016-06-02 16:05:49 -070082 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 Richardsoncf6e78d2014-08-27 15:50:25 -070085}
86
Bill Richardson6ea2f722015-03-26 15:31:54 -070087int ft_show_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070088{
Randall Spangler98263a12016-06-02 16:05:49 -070089 struct vb2_packed_key *pubkey = (struct vb2_packed_key *)buf;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070090
Randall Spangler98263a12016-06-02 16:05:49 -070091 if (!packed_key_looks_ok(pubkey, len)) {
Bill Richardson6ea2f722015-03-26 15:31:54 -070092 printf("%s looks bogus\n", name);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070093 return 1;
94 }
95
Bill Richardson6ea2f722015-03-26 15:31:54 -070096 printf("Public Key file: %s\n", name);
Bill Richardson091c7b12015-03-26 16:58:49 -070097 show_pubkey(pubkey, " ");
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070098
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070099 return 0;
100}
101
Bill Richardson6ea2f722015-03-26 15:31:54 -0700102int ft_show_privkey(const char *name, uint8_t *buf, uint32_t len, void *data)
Bill Richardson4805f182015-01-30 22:21:10 -0800103{
Randall Spangler158b2962016-06-03 14:00:27 -0700104 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 Richardson4805f182015-01-30 22:21:10 -0800108
Randall Spangler158b2962016-06-03 14:00:27 -0700109 if (len <= sizeof(*pkey)) {
Bill Richardson6ea2f722015-03-26 15:31:54 -0700110 printf("%s looks bogus\n", name);
111 return 1;
112 }
Randall Spangler158b2962016-06-03 14:00:27 -0700113 len -= sizeof(*pkey);
Bill Richardson3855e2e2015-02-05 10:44:54 -0800114 key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, len);
Bill Richardson4805f182015-01-30 22:21:10 -0800115
Bill Richardson6ea2f722015-03-26 15:31:54 -0700116 printf("Private Key file: %s\n", name);
Bill Richardsonadd997f2015-02-04 16:47:16 -0800117 printf(" Vboot API: 1.0\n");
Randall Spangler158b2962016-06-03 14:00:27 -0700118 printf(" Algorithm: %u %s\n", pkey->algorithm,
Randall Spangler46a382d2016-10-18 12:00:07 -0700119 vb2_get_crypto_algorithm_name(pkey->algorithm));
Randall Spangler158b2962016-06-03 14:00:27 -0700120 printf(" Key sha1sum: %s\n",
121 private_key_sha1_string(&key));
Bill Richardson4805f182015-01-30 22:21:10 -0800122
Bill Richardson4805f182015-01-30 22:21:10 -0800123 return 0;
124}
125
Bill Richardson6ea2f722015-03-26 15:31:54 -0700126int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700127{
Randall Spangler98263a12016-06-02 16:05:49 -0700128 struct vb2_keyblock *block = (struct vb2_keyblock *)buf;
129 struct vb2_public_key *sign_key = show_option.k;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700130 int good_sig = 0;
Bill Richardson52a15f92014-09-23 22:31:08 -0700131 int retval = 0;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700132
133 /* Check the hash only first */
Randall Spangler98263a12016-06-02 16:05:49 -0700134 if (0 != vb2_verify_keyblock_hash(block, len, &wb)) {
Bill Richardson6ea2f722015-03-26 15:31:54 -0700135 printf("%s is invalid\n", name);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700136 return 1;
137 }
138
139 /* Check the signature if we have one */
Randall Spangler98263a12016-06-02 16:05:49 -0700140 if (sign_key &&
141 VB2_SUCCESS == vb2_verify_keyblock(block, len, sign_key, &wb))
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700142 good_sig = 1;
143
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700144 if (show_option.strict && (!sign_key || !good_sig))
Bill Richardson52a15f92014-09-23 22:31:08 -0700145 retval = 1;
146
Bill Richardson6ea2f722015-03-26 15:31:54 -0700147 show_keyblock(block, name, !!sign_key, good_sig);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700148
Bill Richardson52a15f92014-09-23 22:31:08 -0700149 return retval;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700150}
151
Bill Richardson6ea2f722015-03-26 15:31:54 -0700152int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
153 void *data)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700154{
Randall Spangler98263a12016-06-02 16:05:49 -0700155 struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
Bill Richardson091c7b12015-03-26 16:58:49 -0700156 struct bios_state_s *state = (struct bios_state_s *)data;
Randall Spangler98263a12016-06-02 16:05:49 -0700157 struct vb2_public_key *sign_key = show_option.k;
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700158 uint8_t *fv_data = show_option.fv;
159 uint64_t fv_size = show_option.fv_size;
Bill Richardson6ea2f722015-03-26 15:31:54 -0700160 struct bios_area_s *fw_body_area = 0;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700161 int good_sig = 0;
Bill Richardson52a15f92014-09-23 22:31:08 -0700162 int retval = 0;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700163
164 /* Check the hash... */
Randall Spangler98263a12016-06-02 16:05:49 -0700165 if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
Bill Richardson6ea2f722015-03-26 15:31:54 -0700166 printf("%s keyblock component is invalid\n", name);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700167 return 1;
168 }
169
Bill Richardson6ea2f722015-03-26 15:31:54 -0700170 /*
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 Spangler98263a12016-06-02 16:05:49 -0700176 struct vb2_public_key root_key;
Bill Richardson6ea2f722015-03-26 15:31:54 -0700177 if (state) {
Randall Spangler98263a12016-06-02 16:05:49 -0700178 if (!sign_key &&
179 state->rootkey.is_valid &&
180 VB2_SUCCESS == vb2_unpack_key(&root_key, state->rootkey.buf,
181 state->rootkey.len)) {
Bill Richardson5f2696d2014-09-23 22:03:56 -0700182 /* BIOS should have a rootkey in the GBB */
Randall Spangler98263a12016-06-02 16:05:49 -0700183 sign_key = &root_key;
184 }
185
Bill Richardson6ea2f722015-03-26 15:31:54 -0700186 /* 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 Richardsoncf6e78d2014-08-27 15:50:25 -0700191 }
192
193 /* If we have a key, check the signature too */
Randall Spangler98263a12016-06-02 16:05:49 -0700194 if (sign_key && VB2_SUCCESS ==
195 vb2_verify_keyblock(keyblock, len, sign_key, &wb))
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700196 good_sig = 1;
197
Randall Spangler98263a12016-06-02 16:05:49 -0700198 show_keyblock(keyblock, name, !!sign_key, good_sig);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700199
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700200 if (show_option.strict && (!sign_key || !good_sig))
Bill Richardson52a15f92014-09-23 22:31:08 -0700201 retval = 1;
202
Randall Spangler98263a12016-06-02 16:05:49 -0700203 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 Richardson6ea2f722015-03-26 15:31:54 -0700208 fprintf(stderr, "Error parsing data key in %s\n", name);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700209 return 1;
210 }
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700211
Randall Spangler98263a12016-06-02 16:05:49 -0700212 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 Richardson6ea2f722015-03-26 15:31:54 -0700216 printf("%s is invalid\n", name);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700217 return 1;
218 }
219
Randall Spangler98263a12016-06-02 16:05:49 -0700220 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 Richardson779796f2014-09-23 11:47:40 -0700224 printf("Firmware Preamble:\n");
Randall Spangler98263a12016-06-02 16:05:49 -0700225 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 Richardsoncf6e78d2014-08-27 15:50:25 -0700232 kernel_subkey->algorithm,
Randall Spangler46a382d2016-10-18 12:00:07 -0700233 vb2_get_crypto_algorithm_name(kernel_subkey->algorithm));
234 if (kernel_subkey->algorithm >= VB2_ALG_COUNT)
Bill Richardson52a15f92014-09-23 22:31:08 -0700235 retval = 1;
Randall Spangler98263a12016-06-02 16:05:49 -0700236 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 Richardsoncf6e78d2014-08-27 15:50:25 -0700241
Randall Spangler814aaf02016-06-17 10:48:16 -0700242 if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
Bill Richardson779796f2014-09-23 11:47:40 -0700243 printf("Preamble requests USE_RO_NORMAL;"
244 " skipping body verification.\n");
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700245 goto done;
246 }
247
248 /* We'll need to get the firmware body from somewhere... */
Bill Richardson6ea2f722015-03-26 15:31:54 -0700249 if (fw_body_area && fw_body_area->is_valid) {
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700250 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 Richardson1e35c3a2015-03-26 16:34:28 -0700256 if (show_option.strict)
Bill Richardson52a15f92014-09-23 22:31:08 -0700257 return 1;
Bill Richardson08efd1e2014-09-04 22:53:41 -0700258 return 0;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700259 }
260
Randall Spangler98263a12016-06-02 16:05:49 -0700261 if (VB2_SUCCESS !=
262 vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
263 &data_key, &wb)) {
Bill Richardson779796f2014-09-23 11:47:40 -0700264 fprintf(stderr, "Error verifying firmware body.\n");
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700265 return 1;
266 }
267
268done:
Bill Richardson6ea2f722015-03-26 15:31:54 -0700269 /* 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 Spangler814aaf02016-06-17 10:48:16 -0700272 if (!(flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL))
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700273 printf("Body verification succeeded.\n");
Bill Richardson6ea2f722015-03-26 15:31:54 -0700274 if (state)
275 state->area[state->c].is_valid = 1;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700276 } else {
Bill Richardson08efd1e2014-09-04 22:53:41 -0700277 printf("Seems legit, but the signature is unverified.\n");
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700278 if (show_option.strict)
Bill Richardson52a15f92014-09-23 22:31:08 -0700279 retval = 1;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700280 }
281
Bill Richardson52a15f92014-09-23 22:31:08 -0700282 return retval;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700283}
284
Bill Richardson6ea2f722015-03-26 15:31:54 -0700285int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len,
286 void *data)
287{
Randall Spangler98263a12016-06-02 16:05:49 -0700288 struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
289 struct vb2_public_key *sign_key = show_option.k;
Bill Richardson52a15f92014-09-23 22:31:08 -0700290 int retval = 0;
Bill Richardson5f2696d2014-09-23 22:03:56 -0700291
292 /* Check the hash... */
Randall Spangler98263a12016-06-02 16:05:49 -0700293 if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
Bill Richardson6ea2f722015-03-26 15:31:54 -0700294 printf("%s keyblock component is invalid\n", name);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700295 return 1;
296 }
297
298 /* If we have a key, check the signature too */
Randall Spangler158b2962016-06-03 14:00:27 -0700299 int good_sig = 0;
Randall Spangler98263a12016-06-02 16:05:49 -0700300 if (sign_key && VB2_SUCCESS ==
301 vb2_verify_keyblock(keyblock, len, sign_key, &wb))
Bill Richardson5f2696d2014-09-23 22:03:56 -0700302 good_sig = 1;
303
Bill Richardson6ea2f722015-03-26 15:31:54 -0700304 printf("Kernel partition: %s\n", name);
Randall Spangler98263a12016-06-02 16:05:49 -0700305 show_keyblock(keyblock, NULL, !!sign_key, good_sig);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700306
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700307 if (show_option.strict && (!sign_key || !good_sig))
Bill Richardson52a15f92014-09-23 22:31:08 -0700308 retval = 1;
309
Randall Spangler158b2962016-06-03 14:00:27 -0700310 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 Richardson6ea2f722015-03-26 15:31:54 -0700315 fprintf(stderr, "Error parsing data key in %s\n", name);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700316 return 1;
317 }
Bill Richardson5f2696d2014-09-23 22:03:56 -0700318
Randall Spangler158b2962016-06-03 14:00:27 -0700319 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 Richardson6ea2f722015-03-26 15:31:54 -0700325 printf("%s is invalid\n", name);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700326 return 1;
327 }
328
329 printf("Kernel Preamble:\n");
Randall Spangler158b2962016-06-03 14:00:27 -0700330 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 Richardson5f2696d2014-09-23 22:03:56 -0700335 printf(" Body load address: 0x%" PRIx64 "\n",
Randall Spangler158b2962016-06-03 14:00:27 -0700336 pre2->body_load_address);
337 printf(" Body size: 0x%x\n",
338 pre2->body_signature.data_size);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700339 printf(" Bootloader address: 0x%" PRIx64 "\n",
Randall Spangler158b2962016-06-03 14:00:27 -0700340 pre2->bootloader_address);
341 printf(" Bootloader size: 0x%x\n", pre2->bootloader_size);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700342
Randall Spangler158b2962016-06-03 14:00:27 -0700343 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 Chenf1f53b32015-01-08 09:13:44 -0800348 if (vmlinuz_header_size) {
349 printf(" Vmlinuz_header address: 0x%" PRIx64 "\n",
350 vmlinuz_header_address);
Randall Spangler158b2962016-06-03 14:00:27 -0700351 printf(" Vmlinuz header size: 0x%x\n",
Shelley Chenf1f53b32015-01-08 09:13:44 -0800352 vmlinuz_header_size);
353 }
Bill Richardson5f2696d2014-09-23 22:03:56 -0700354
Randall Spangler158b2962016-06-03 14:00:27 -0700355 printf(" Flags: 0x%x\n", vb2_kernel_get_flags(pre2));
Furquan Shaikh80e779d2015-02-03 15:34:29 -0800356
Bill Richardson5f2696d2014-09-23 22:03:56 -0700357 /* Verify kernel body */
Randall Spangler158b2962016-06-03 14:00:27 -0700358 uint8_t *kernel_blob = 0;
359 uint64_t kernel_size = 0;
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700360 if (show_option.fv) {
Bill Richardson5f2696d2014-09-23 22:03:56 -0700361 /* It's in a separate file, which we've already read in */
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700362 kernel_blob = show_option.fv;
363 kernel_size = show_option.fv_size;
364 } else if (len > show_option.padding) {
Bill Richardson5f2696d2014-09-23 22:03:56 -0700365 /* It should be at an offset within the input file. */
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700366 kernel_blob = buf + show_option.padding;
367 kernel_size = len - show_option.padding;
Bill Richardson5f2696d2014-09-23 22:03:56 -0700368 }
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 Spangler158b2962016-06-03 14:00:27 -0700376 if (VB2_SUCCESS !=
377 vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature,
378 &data_key, &wb)) {
Bill Richardson5f2696d2014-09-23 22:03:56 -0700379 fprintf(stderr, "Error verifying kernel body.\n");
380 return 1;
381 }
382
383 printf("Body verification succeeded.\n");
384
Randall Spangler158b2962016-06-03 14:00:27 -0700385 printf("Config:\n%s\n", kernel_blob + kernel_cmd_line_offset(pre2));
Bill Richardson5f2696d2014-09-23 22:03:56 -0700386
Bill Richardson52a15f92014-09-23 22:31:08 -0700387 return retval;
Bill Richardson5f2696d2014-09-23 22:03:56 -0700388}
389
Bill Richardson5f2696d2014-09-23 22:03:56 -0700390enum no_short_opts {
391 OPT_PADDING = 1000,
Bill Richardson453ecd12015-03-26 16:29:10 -0700392 OPT_TYPE,
Bill Richardson02ac2882015-10-15 00:23:18 -0700393 OPT_PUBKEY,
Bill Richardson01466d32015-03-11 11:21:47 -0700394 OPT_HELP,
Bill Richardson5f2696d2014-09-23 22:03:56 -0700395};
396
Bill Richardson779796f2014-09-23 11:47:40 -0700397static const char usage[] = "\n"
Bill Richardson25593382015-01-30 12:22:28 -0800398 "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n"
Bill Richardson779796f2014-09-23 11:47:40 -0700399 "\n"
Bill Richardsoneff31002015-04-06 13:02:40 -0700400 "Where FILE could be\n"
Bill Richardson779796f2014-09-23 11:47:40 -0700401 "\n"
Daisuke Nojiric3daa952016-09-22 09:48:20 -0700402 " a BDB\n"
Bill Richardsoneff31002015-04-06 13:02:40 -0700403 " 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 Richardson779796f2014-09-23 11:47:40 -0700409 "\n"
410 "Options:\n"
Bill Richardson25593382015-01-30 12:22:28 -0800411 " -t Just show the type of each file\n"
Bill Richardsoneff31002015-04-06 13:02:40 -0700412 " --type TYPE Override the detected file type\n"
413 " Use \"--type help\" for a list\n"
414 "Type-specific options:\n"
Bill Richardson02ac2882015-10-15 00:23:18 -0700415 " -k|--publickey FILE.vbpubk Public key in vb1 format\n"
416 " --pubkey FILE.vpubk2 Public key in vb2 format\n"
Bill Richardson5f2696d2014-09-23 22:03:56 -0700417 " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
418 " --pad NUM Kernel vblock padding size\n"
Bill Richardsoneff31002015-04-06 13:02:40 -0700419 " --strict "
420 "Fail unless all signatures are valid\n"
Bill Richardson779796f2014-09-23 11:47:40 -0700421 "\n";
422
Bill Richardson49a422f2015-03-05 13:49:36 -0800423static void print_help(int argc, char *argv[])
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700424{
Bill Richardsoneff31002015-04-06 13:02:40 -0700425 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 Richardsoncf6e78d2014-08-27 15:50:25 -0700432}
433
434static const struct option long_opts[] = {
435 /* name hasarg *flag val */
Bill Richardson5f2696d2014-09-23 22:03:56 -0700436 {"publickey", 1, 0, 'k'},
437 {"fv", 1, 0, 'f'},
438 {"pad", 1, NULL, OPT_PADDING},
Bill Richardson453ecd12015-03-26 16:29:10 -0700439 {"type", 1, NULL, OPT_TYPE},
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700440 {"strict", 0, &show_option.strict, 1},
Bill Richardson02ac2882015-10-15 00:23:18 -0700441 {"pubkey", 1, NULL, OPT_PUBKEY},
Bill Richardson01466d32015-03-11 11:21:47 -0700442 {"help", 0, NULL, OPT_HELP},
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700443 {NULL, 0, NULL, 0},
444};
Bill Richardson25593382015-01-30 12:22:28 -0800445static char *short_opts = ":f:k:t";
446
447
Bill Richardson453ecd12015-03-26 16:29:10 -0700448static int show_type(char *filename)
Bill Richardson25593382015-01-30 12:22:28 -0800449{
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 Richardson4dc15752015-03-09 19:39:19 -0700455 printf("%s:\t%s\n", filename, futil_file_type_name(type));
Bill Richardson453ecd12015-03-26 16:29:10 -0700456 /* Only our recognized types return success */
457 return 0;
Bill Richardson25593382015-01-30 12:22:28 -0800458 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 Richardson453ecd12015-03-26 16:29:10 -0700473 /* Everything else is an error */
474 return 1;
Bill Richardson25593382015-01-30 12:22:28 -0800475}
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700476
477static int do_show(int argc, char *argv[])
478{
Randall Spangler98263a12016-06-02 16:05:49 -0700479 uint8_t *pubkbuf = NULL;
480 struct vb2_public_key pubk2;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700481 char *infile = 0;
482 int ifd, i;
483 int errorcnt = 0;
Bill Richardsonb0f1cc52014-09-24 00:23:56 -0700484 uint8_t *buf;
Bill Richardson6ea2f722015-03-26 15:31:54 -0700485 uint32_t len;
Bill Richardson5f2696d2014-09-23 22:03:56 -0700486 char *e = 0;
Bill Richardson453ecd12015-03-26 16:29:10 -0700487 int type_override = 0;
488 enum futil_file_type type;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700489
Randall Spangler98263a12016-06-02 16:05:49 -0700490 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
491
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700492 opterr = 0; /* quiet, you */
493 while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
494 switch (i) {
495 case 'f':
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700496 show_option.fv = ReadFile(optarg,
497 &show_option.fv_size);
498 if (!show_option.fv) {
Bill Richardson5f2696d2014-09-23 22:03:56 -0700499 fprintf(stderr, "Error reading %s: %s\n",
500 optarg, strerror(errno));
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700501 errorcnt++;
502 }
503 break;
504 case 'k':
Randall Spangler98263a12016-06-02 16:05:49 -0700505 if (VB2_SUCCESS !=
506 vb2_read_file(optarg, &pubkbuf, &len)) {
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700507 fprintf(stderr, "Error reading %s\n", optarg);
508 errorcnt++;
Randall Spangler98263a12016-06-02 16:05:49 -0700509 break;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700510 }
Randall Spangler98263a12016-06-02 16:05:49 -0700511
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 Richardsoncf6e78d2014-08-27 15:50:25 -0700520 break;
Bill Richardson25593382015-01-30 12:22:28 -0800521 case 't':
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700522 show_option.t_flag = 1;
Bill Richardson25593382015-01-30 12:22:28 -0800523 break;
Bill Richardson5f2696d2014-09-23 22:03:56 -0700524 case OPT_PADDING:
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700525 show_option.padding = strtoul(optarg, &e, 0);
Bill Richardson5f2696d2014-09-23 22:03:56 -0700526 if (!*optarg || (e && *e)) {
527 fprintf(stderr,
528 "Invalid --padding \"%s\"\n", optarg);
529 errorcnt++;
530 }
531 break;
Bill Richardson453ecd12015-03-26 16:29:10 -0700532 case OPT_TYPE:
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700533 if (!futil_str_to_file_type(optarg,
534 &show_option.type)) {
Bill Richardson453ecd12015-03-26 16:29:10 -0700535 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 Richardson02ac2882015-10-15 00:23:18 -0700543 case OPT_PUBKEY:
Randall Spanglerca725122016-05-25 16:42:44 -0700544 if (vb21_packed_key_read(&show_option.pkey, optarg)) {
Bill Richardson02ac2882015-10-15 00:23:18 -0700545 fprintf(stderr, "Error reading %s\n", optarg);
546 errorcnt++;
547 }
548 break;
Bill Richardson01466d32015-03-11 11:21:47 -0700549 case OPT_HELP:
550 print_help(argc, argv);
551 return !!errorcnt;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700552
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 Richardson779796f2014-09-23 11:47:40 -0700565 case 0: /* handled option */
566 break;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700567 default:
568 DIE;
569 }
570 }
571
Bill Richardson779796f2014-09-23 11:47:40 -0700572 if (errorcnt) {
Bill Richardson49a422f2015-03-05 13:49:36 -0800573 print_help(argc, argv);
Bill Richardson779796f2014-09-23 11:47:40 -0700574 return 1;
575 }
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700576
577 if (argc - optind < 1) {
578 fprintf(stderr, "ERROR: missing input filename\n");
Bill Richardson49a422f2015-03-05 13:49:36 -0800579 print_help(argc, argv);
Bill Richardson779796f2014-09-23 11:47:40 -0700580 return 1;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700581 }
582
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700583 if (show_option.t_flag) {
Bill Richardson25593382015-01-30 12:22:28 -0800584 for (i = optind; i < argc; i++)
Bill Richardson453ecd12015-03-26 16:29:10 -0700585 errorcnt += show_type(argv[i]);
Bill Richardson25593382015-01-30 12:22:28 -0800586 goto done;
587 }
588
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700589 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 Richardsonb0f1cc52014-09-24 00:23:56 -0700596 continue;
597 }
598
Bill Richardson6ea2f722015-03-26 15:31:54 -0700599 if (0 != futil_map_file(ifd, MAP_RO, &buf, &len)) {
Bill Richardsonb0f1cc52014-09-24 00:23:56 -0700600 errorcnt++;
601 goto boo;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700602 }
603
Bill Richardson453ecd12015-03-26 16:29:10 -0700604 /* Allow the user to override the type */
605 if (type_override)
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700606 type = show_option.type;
Bill Richardson453ecd12015-03-26 16:29:10 -0700607 else
608 type = futil_file_type_buf(buf, len);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700609
Bill Richardson6ea2f722015-03-26 15:31:54 -0700610 errorcnt += futil_file_type_show(type, infile, buf, len);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700611
Bill Richardson6ea2f722015-03-26 15:31:54 -0700612 errorcnt += futil_unmap_file(ifd, MAP_RO, buf, len);
Bill Richardsonb0f1cc52014-09-24 00:23:56 -0700613boo:
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700614 if (close(ifd)) {
615 errorcnt++;
616 fprintf(stderr, "Error when closing %s: %s\n",
617 infile, strerror(errno));
618 }
619 }
620
Bill Richardson25593382015-01-30 12:22:28 -0800621done:
Randall Spangler98263a12016-06-02 16:05:49 -0700622 if (pubkbuf)
623 free(pubkbuf);
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700624 if (show_option.fv)
625 free(show_option.fv);
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700626
627 return !!errorcnt;
628}
629
Bill Richardson01466d32015-03-11 11:21:47 -0700630DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL,
631 "Display the content of various binary components");
Bill Richardson52a15f92014-09-23 22:31:08 -0700632
633static int do_verify(int argc, char *argv[])
634{
Bill Richardson1e35c3a2015-03-26 16:34:28 -0700635 show_option.strict = 1;
Bill Richardson52a15f92014-09-23 22:31:08 -0700636 return do_show(argc, argv);
637}
638
639DECLARE_FUTIL_COMMAND(verify, do_verify,
Bill Richardson1eae8732015-02-05 12:36:15 -0800640 VBOOT_VERSION_ALL,
Bill Richardson01466d32015-03-11 11:21:47 -0700641 "Verify the signatures of various binary components");