1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2014 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker */
5*8617a60dSAndroid Build Coastguard Worker
6*8617a60dSAndroid Build Coastguard Worker #include <openssl/rsa.h>
7*8617a60dSAndroid Build Coastguard Worker
8*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
9*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
10*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
11*8617a60dSAndroid Build Coastguard Worker #include <inttypes.h>
12*8617a60dSAndroid Build Coastguard Worker #include <stddef.h>
13*8617a60dSAndroid Build Coastguard Worker #include <stdint.h>
14*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
15*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
16*8617a60dSAndroid Build Coastguard Worker #include <string.h>
17*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
18*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
19*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
20*8617a60dSAndroid Build Coastguard Worker
21*8617a60dSAndroid Build Coastguard Worker #include "2api.h"
22*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
23*8617a60dSAndroid Build Coastguard Worker #include "2sha.h"
24*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
25*8617a60dSAndroid Build Coastguard Worker #include "cbfstool.h"
26*8617a60dSAndroid Build Coastguard Worker #include "file_type_bios.h"
27*8617a60dSAndroid Build Coastguard Worker #include "file_type.h"
28*8617a60dSAndroid Build Coastguard Worker #include "fmap.h"
29*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
30*8617a60dSAndroid Build Coastguard Worker #include "futility_options.h"
31*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
32*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
33*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
34*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
35*8617a60dSAndroid Build Coastguard Worker #include "vb1_helper.h"
36*8617a60dSAndroid Build Coastguard Worker
37*8617a60dSAndroid Build Coastguard Worker /* Options */
38*8617a60dSAndroid Build Coastguard Worker struct show_option_s show_option = {
39*8617a60dSAndroid Build Coastguard Worker .type = FILE_TYPE_UNKNOWN,
40*8617a60dSAndroid Build Coastguard Worker };
41*8617a60dSAndroid Build Coastguard Worker
42*8617a60dSAndroid Build Coastguard Worker /* Shared work buffer */
43*8617a60dSAndroid Build Coastguard Worker static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
44*8617a60dSAndroid Build Coastguard Worker __attribute__((aligned(VB2_WORKBUF_ALIGN)));
45*8617a60dSAndroid Build Coastguard Worker static struct vb2_workbuf wb;
46*8617a60dSAndroid Build Coastguard Worker
show_pubkey(const struct vb2_packed_key * pubkey,const char * sp)47*8617a60dSAndroid Build Coastguard Worker void show_pubkey(const struct vb2_packed_key *pubkey, const char *sp)
48*8617a60dSAndroid Build Coastguard Worker {
49*8617a60dSAndroid Build Coastguard Worker // Clear out formatting if we are in parseable mode.
50*8617a60dSAndroid Build Coastguard Worker if (show_option.parseable)
51*8617a60dSAndroid Build Coastguard Worker sp = "\0";
52*8617a60dSAndroid Build Coastguard Worker FT_PRINT("%sVboot API: 1.0\n", "%sapi::1.0\n", sp);
53*8617a60dSAndroid Build Coastguard Worker FT_PRINT("%sAlgorithm: %d %s\n",
54*8617a60dSAndroid Build Coastguard Worker "%salgorithm::%d::%s\n",
55*8617a60dSAndroid Build Coastguard Worker sp, pubkey->algorithm,
56*8617a60dSAndroid Build Coastguard Worker vb2_get_crypto_algorithm_name(pubkey->algorithm));
57*8617a60dSAndroid Build Coastguard Worker FT_PRINT("%sKey Version: %d\n", "%sversion::%d\n",
58*8617a60dSAndroid Build Coastguard Worker sp, pubkey->key_version);
59*8617a60dSAndroid Build Coastguard Worker FT_PRINT("%sKey sha1sum: %s\n", "%ssha1_sum::%s\n",
60*8617a60dSAndroid Build Coastguard Worker sp, packed_key_sha1_string(pubkey));
61*8617a60dSAndroid Build Coastguard Worker }
62*8617a60dSAndroid Build Coastguard Worker
show_keyblock(struct vb2_keyblock * keyblock,const char * print_name,int sign_key,int good_sig)63*8617a60dSAndroid Build Coastguard Worker static void show_keyblock(struct vb2_keyblock *keyblock, const char *print_name,
64*8617a60dSAndroid Build Coastguard Worker int sign_key, int good_sig)
65*8617a60dSAndroid Build Coastguard Worker {
66*8617a60dSAndroid Build Coastguard Worker const struct vb2_signature *sig = &keyblock->keyblock_signature;
67*8617a60dSAndroid Build Coastguard Worker
68*8617a60dSAndroid Build Coastguard Worker if (print_name)
69*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Keyblock: %s\n", print_name);
70*8617a60dSAndroid Build Coastguard Worker else
71*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Keyblock:\n");
72*8617a60dSAndroid Build Coastguard Worker
73*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Size: %#x\n",
74*8617a60dSAndroid Build Coastguard Worker "size::%d\n", keyblock->keyblock_size);
75*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Signature: %s\n", "signature::%s\n",
76*8617a60dSAndroid Build Coastguard Worker sign_key ? (good_sig ? "valid" : "invalid") : "ignored");
77*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Size: %#x\n", "signature::size::%u\n",
78*8617a60dSAndroid Build Coastguard Worker sig->sig_size);
79*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Data size: %#x\n", "signature::data_size::%u\n",
80*8617a60dSAndroid Build Coastguard Worker sig->data_size);
81*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Flags: %d ",
82*8617a60dSAndroid Build Coastguard Worker "flags::%d:", keyblock->keyblock_flags);
83*8617a60dSAndroid Build Coastguard Worker if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_0)
84*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW(" !DEV", ":!DEV");
85*8617a60dSAndroid Build Coastguard Worker if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_DEVELOPER_1)
86*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW(" DEV", ":DEV");
87*8617a60dSAndroid Build Coastguard Worker if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_0)
88*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW(" !REC", ":!REC");
89*8617a60dSAndroid Build Coastguard Worker if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1)
90*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW(" REC", ":REC");
91*8617a60dSAndroid Build Coastguard Worker if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0)
92*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW(" !MINIOS", ":!MINIOS");
93*8617a60dSAndroid Build Coastguard Worker if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1)
94*8617a60dSAndroid Build Coastguard Worker FT_PRINT_RAW(" MINIOS", ":MINIOS");
95*8617a60dSAndroid Build Coastguard Worker printf("\n");
96*8617a60dSAndroid Build Coastguard Worker
97*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *data_key = &keyblock->data_key;
98*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Data key algorithm: %d %s\n",
99*8617a60dSAndroid Build Coastguard Worker "data_key::algorithm::%d::%s\n", data_key->algorithm,
100*8617a60dSAndroid Build Coastguard Worker vb2_get_crypto_algorithm_name(data_key->algorithm));
101*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Data key version: %d\n", "data_key::version::%d\n",
102*8617a60dSAndroid Build Coastguard Worker data_key->key_version);
103*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Data key sha1sum: %s\n", "data_key::sha1_sum::%s\n",
104*8617a60dSAndroid Build Coastguard Worker packed_key_sha1_string(data_key));
105*8617a60dSAndroid Build Coastguard Worker }
106*8617a60dSAndroid Build Coastguard Worker
ft_show_pubkey(const char * fname)107*8617a60dSAndroid Build Coastguard Worker int ft_show_pubkey(const char *fname)
108*8617a60dSAndroid Build Coastguard Worker {
109*8617a60dSAndroid Build Coastguard Worker int fd = -1;
110*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *pubkey;
111*8617a60dSAndroid Build Coastguard Worker uint32_t len;
112*8617a60dSAndroid Build Coastguard Worker int rv = 0;
113*8617a60dSAndroid Build Coastguard Worker
114*8617a60dSAndroid Build Coastguard Worker if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&pubkey,
115*8617a60dSAndroid Build Coastguard Worker &len))
116*8617a60dSAndroid Build Coastguard Worker return 1;
117*8617a60dSAndroid Build Coastguard Worker
118*8617a60dSAndroid Build Coastguard Worker if (vb2_packed_key_looks_ok(pubkey, len)) {
119*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid public key: %s\n", fname);
120*8617a60dSAndroid Build Coastguard Worker rv = 1;
121*8617a60dSAndroid Build Coastguard Worker goto done;
122*8617a60dSAndroid Build Coastguard Worker }
123*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Public Key file: %s\n", fname);
124*8617a60dSAndroid Build Coastguard Worker
125*8617a60dSAndroid Build Coastguard Worker ft_print_header = "pubkey";
126*8617a60dSAndroid Build Coastguard Worker show_pubkey(pubkey, " ");
127*8617a60dSAndroid Build Coastguard Worker
128*8617a60dSAndroid Build Coastguard Worker done:
129*8617a60dSAndroid Build Coastguard Worker futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pubkey, len);
130*8617a60dSAndroid Build Coastguard Worker return rv;
131*8617a60dSAndroid Build Coastguard Worker }
132*8617a60dSAndroid Build Coastguard Worker
ft_show_privkey(const char * fname)133*8617a60dSAndroid Build Coastguard Worker int ft_show_privkey(const char *fname)
134*8617a60dSAndroid Build Coastguard Worker {
135*8617a60dSAndroid Build Coastguard Worker int fd = -1;
136*8617a60dSAndroid Build Coastguard Worker int rv = 0;
137*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_private_key *pkey = NULL;
138*8617a60dSAndroid Build Coastguard Worker uint32_t len;
139*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key key;
140*8617a60dSAndroid Build Coastguard Worker const unsigned char *start;
141*8617a60dSAndroid Build Coastguard Worker
142*8617a60dSAndroid Build Coastguard Worker if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&pkey,
143*8617a60dSAndroid Build Coastguard Worker &len))
144*8617a60dSAndroid Build Coastguard Worker return 1;
145*8617a60dSAndroid Build Coastguard Worker
146*8617a60dSAndroid Build Coastguard Worker start = pkey->key_data;
147*8617a60dSAndroid Build Coastguard Worker if (len <= sizeof(*pkey)) {
148*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid private key: %s\n", fname);
149*8617a60dSAndroid Build Coastguard Worker rv = 1;
150*8617a60dSAndroid Build Coastguard Worker goto done;
151*8617a60dSAndroid Build Coastguard Worker }
152*8617a60dSAndroid Build Coastguard Worker len -= sizeof(*pkey);
153*8617a60dSAndroid Build Coastguard Worker key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start, len);
154*8617a60dSAndroid Build Coastguard Worker
155*8617a60dSAndroid Build Coastguard Worker
156*8617a60dSAndroid Build Coastguard Worker ft_print_header = "prikey";
157*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Private Key file: %s\n", fname);
158*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Vboot API: 1.0\n", "api::1.0\n");
159*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Algorithm: %u %s\n",
160*8617a60dSAndroid Build Coastguard Worker "algorithm::%d::%s\n", pkey->algorithm,
161*8617a60dSAndroid Build Coastguard Worker vb2_get_crypto_algorithm_name(pkey->algorithm));
162*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Key sha1sum: %s\n", "sha1_sum::%s\n",
163*8617a60dSAndroid Build Coastguard Worker private_key_sha1_string(&key));
164*8617a60dSAndroid Build Coastguard Worker
165*8617a60dSAndroid Build Coastguard Worker done:
166*8617a60dSAndroid Build Coastguard Worker futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)pkey, len);
167*8617a60dSAndroid Build Coastguard Worker return rv;
168*8617a60dSAndroid Build Coastguard Worker }
169*8617a60dSAndroid Build Coastguard Worker
ft_show_keyblock(const char * fname)170*8617a60dSAndroid Build Coastguard Worker int ft_show_keyblock(const char *fname)
171*8617a60dSAndroid Build Coastguard Worker {
172*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *block;
173*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key *sign_key = show_option.k;
174*8617a60dSAndroid Build Coastguard Worker int good_sig = 0;
175*8617a60dSAndroid Build Coastguard Worker int retval = 0;
176*8617a60dSAndroid Build Coastguard Worker int fd = -1;
177*8617a60dSAndroid Build Coastguard Worker uint32_t len;
178*8617a60dSAndroid Build Coastguard Worker
179*8617a60dSAndroid Build Coastguard Worker if (futil_open_and_map_file(fname, &fd, FILE_RO, (uint8_t **)&block, &len))
180*8617a60dSAndroid Build Coastguard Worker return 1;
181*8617a60dSAndroid Build Coastguard Worker
182*8617a60dSAndroid Build Coastguard Worker ft_print_header = "keyblock";
183*8617a60dSAndroid Build Coastguard Worker
184*8617a60dSAndroid Build Coastguard Worker /* Check the hash only first */
185*8617a60dSAndroid Build Coastguard Worker if (vb2_verify_keyblock_hash(block, len, &wb)) {
186*8617a60dSAndroid Build Coastguard Worker ERROR("%s is invalid\n", fname);
187*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("invalid\n");
188*8617a60dSAndroid Build Coastguard Worker retval = 1;
189*8617a60dSAndroid Build Coastguard Worker goto done;
190*8617a60dSAndroid Build Coastguard Worker } else {
191*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("valid\n");
192*8617a60dSAndroid Build Coastguard Worker }
193*8617a60dSAndroid Build Coastguard Worker
194*8617a60dSAndroid Build Coastguard Worker /* Check the signature if we have one */
195*8617a60dSAndroid Build Coastguard Worker if (sign_key &&
196*8617a60dSAndroid Build Coastguard Worker VB2_SUCCESS == vb2_verify_keyblock(block, len, sign_key, &wb))
197*8617a60dSAndroid Build Coastguard Worker good_sig = 1;
198*8617a60dSAndroid Build Coastguard Worker else if (show_option.strict)
199*8617a60dSAndroid Build Coastguard Worker retval = 1;
200*8617a60dSAndroid Build Coastguard Worker
201*8617a60dSAndroid Build Coastguard Worker show_keyblock(block, fname, !!sign_key, good_sig);
202*8617a60dSAndroid Build Coastguard Worker
203*8617a60dSAndroid Build Coastguard Worker done:
204*8617a60dSAndroid Build Coastguard Worker futil_unmap_and_close_file(fd, FILE_RO, (uint8_t *)block, len);
205*8617a60dSAndroid Build Coastguard Worker return retval;
206*8617a60dSAndroid Build Coastguard Worker }
207*8617a60dSAndroid Build Coastguard Worker
fw_show_metadata_hash(const char * fname,enum bios_component body_c,struct vb2_fw_preamble * pre)208*8617a60dSAndroid Build Coastguard Worker static int fw_show_metadata_hash(const char *fname, enum bios_component body_c,
209*8617a60dSAndroid Build Coastguard Worker struct vb2_fw_preamble *pre)
210*8617a60dSAndroid Build Coastguard Worker {
211*8617a60dSAndroid Build Coastguard Worker struct vb2_hash real_hash;
212*8617a60dSAndroid Build Coastguard Worker struct vb2_hash *body_hash =
213*8617a60dSAndroid Build Coastguard Worker (struct vb2_hash *)vb2_signature_data(&pre->body_signature);
214*8617a60dSAndroid Build Coastguard Worker const uint32_t bhsize = vb2_digest_size(body_hash->algo);
215*8617a60dSAndroid Build Coastguard Worker
216*8617a60dSAndroid Build Coastguard Worker if (!bhsize || pre->body_signature.sig_size <
217*8617a60dSAndroid Build Coastguard Worker offsetof(struct vb2_hash, raw) + bhsize) {
218*8617a60dSAndroid Build Coastguard Worker ERROR("Body signature data is too small to fit metadata hash.\n");
219*8617a60dSAndroid Build Coastguard Worker return 1;
220*8617a60dSAndroid Build Coastguard Worker }
221*8617a60dSAndroid Build Coastguard Worker
222*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT(" Body metadata hash: %s ",
223*8617a60dSAndroid Build Coastguard Worker vb2_get_hash_algorithm_name(body_hash->algo));
224*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::metadata_hash::algorithm::%d::%s\n",
225*8617a60dSAndroid Build Coastguard Worker body_hash->algo,
226*8617a60dSAndroid Build Coastguard Worker vb2_get_hash_algorithm_name(body_hash->algo));
227*8617a60dSAndroid Build Coastguard Worker if (vb2_digest_size(body_hash->algo)) {
228*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::metadata_hash::hex::");
229*8617a60dSAndroid Build Coastguard Worker print_bytes((uint8_t *)body_hash->raw,
230*8617a60dSAndroid Build Coastguard Worker vb2_digest_size(body_hash->algo));
231*8617a60dSAndroid Build Coastguard Worker putchar('\n');
232*8617a60dSAndroid Build Coastguard Worker }
233*8617a60dSAndroid Build Coastguard Worker
234*8617a60dSAndroid Build Coastguard Worker if (cbfstool_get_metadata_hash(fname, fmap_name[body_c], &real_hash) !=
235*8617a60dSAndroid Build Coastguard Worker VB2_SUCCESS ||
236*8617a60dSAndroid Build Coastguard Worker real_hash.algo == VB2_HASH_INVALID) {
237*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to get metadata hash. Firmware body is"
238*8617a60dSAndroid Build Coastguard Worker " corrupted or is not a valid CBFS.\n");
239*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::metadata_hash::invalid\n");
240*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::signature::invalid\n");
241*8617a60dSAndroid Build Coastguard Worker return 1;
242*8617a60dSAndroid Build Coastguard Worker }
243*8617a60dSAndroid Build Coastguard Worker
244*8617a60dSAndroid Build Coastguard Worker if (body_hash->algo != real_hash.algo ||
245*8617a60dSAndroid Build Coastguard Worker !vb2_digest_size(body_hash->algo) ||
246*8617a60dSAndroid Build Coastguard Worker memcmp(body_hash->raw, real_hash.raw,
247*8617a60dSAndroid Build Coastguard Worker vb2_digest_size(body_hash->algo))) {
248*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT(" MISMATCH! Real hash: %s:",
249*8617a60dSAndroid Build Coastguard Worker vb2_get_hash_algorithm_name(real_hash.algo));
250*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::metadata_hash::invalid\n");
251*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT(
252*8617a60dSAndroid Build Coastguard Worker "body::metadata_hash::expected::algorithm::%d::%s\n",
253*8617a60dSAndroid Build Coastguard Worker real_hash.algo,
254*8617a60dSAndroid Build Coastguard Worker vb2_get_hash_algorithm_name(real_hash.algo));
255*8617a60dSAndroid Build Coastguard Worker
256*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::metadata_hash::expected::hex::");
257*8617a60dSAndroid Build Coastguard Worker
258*8617a60dSAndroid Build Coastguard Worker print_bytes(&real_hash.raw, vb2_digest_size(real_hash.algo));
259*8617a60dSAndroid Build Coastguard Worker putchar('\n');
260*8617a60dSAndroid Build Coastguard Worker ERROR("Signature hash does not match with"
261*8617a60dSAndroid Build Coastguard Worker " real metadata hash.\n");
262*8617a60dSAndroid Build Coastguard Worker
263*8617a60dSAndroid Build Coastguard Worker /* To balance out signature::valid otherwise printed by caller. */
264*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::signature::invalid\n");
265*8617a60dSAndroid Build Coastguard Worker return 1;
266*8617a60dSAndroid Build Coastguard Worker } else {
267*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Body metadata hash valid!\n",
268*8617a60dSAndroid Build Coastguard Worker "body::metadata_hash::valid\n");
269*8617a60dSAndroid Build Coastguard Worker }
270*8617a60dSAndroid Build Coastguard Worker return 0;
271*8617a60dSAndroid Build Coastguard Worker }
272*8617a60dSAndroid Build Coastguard Worker
show_fw_preamble_buf(const char * fname,uint8_t * buf,uint32_t len,struct bios_state_s * state)273*8617a60dSAndroid Build Coastguard Worker int show_fw_preamble_buf(const char *fname, uint8_t *buf, uint32_t len,
274*8617a60dSAndroid Build Coastguard Worker struct bios_state_s *state)
275*8617a60dSAndroid Build Coastguard Worker {
276*8617a60dSAndroid Build Coastguard Worker const char *print_name = state ? fmap_name[state->c] : fname;
277*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *keyblock = (struct vb2_keyblock *)buf;
278*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key *sign_key = show_option.k;
279*8617a60dSAndroid Build Coastguard Worker uint8_t *fv_data = show_option.fv;
280*8617a60dSAndroid Build Coastguard Worker uint64_t fv_size = show_option.fv_size;
281*8617a60dSAndroid Build Coastguard Worker struct bios_area_s *fw_body_area = 0;
282*8617a60dSAndroid Build Coastguard Worker enum bios_component body_c = BIOS_FMAP_FW_MAIN_A;
283*8617a60dSAndroid Build Coastguard Worker int good_sig = 0;
284*8617a60dSAndroid Build Coastguard Worker int retval = 0;
285*8617a60dSAndroid Build Coastguard Worker
286*8617a60dSAndroid Build Coastguard Worker ft_print_header2 = "keyblock";
287*8617a60dSAndroid Build Coastguard Worker /* Check the hash... */
288*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
289*8617a60dSAndroid Build Coastguard Worker ERROR("%s keyblock component is invalid\n", print_name);
290*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("invalid\n");
291*8617a60dSAndroid Build Coastguard Worker return 1;
292*8617a60dSAndroid Build Coastguard Worker } else {
293*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("valid\n");
294*8617a60dSAndroid Build Coastguard Worker }
295*8617a60dSAndroid Build Coastguard Worker
296*8617a60dSAndroid Build Coastguard Worker /*
297*8617a60dSAndroid Build Coastguard Worker * If we're being invoked while poking through a BIOS, we should
298*8617a60dSAndroid Build Coastguard Worker * be given the keys and data to verify as part of the state. If we
299*8617a60dSAndroid Build Coastguard Worker * have no state, then we're just looking at a standalone fw_preamble,
300*8617a60dSAndroid Build Coastguard Worker * so we'll have to get any keys or data from options.
301*8617a60dSAndroid Build Coastguard Worker */
302*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key root_key;
303*8617a60dSAndroid Build Coastguard Worker if (state) {
304*8617a60dSAndroid Build Coastguard Worker if (!sign_key &&
305*8617a60dSAndroid Build Coastguard Worker state->rootkey.is_valid &&
306*8617a60dSAndroid Build Coastguard Worker VB2_SUCCESS == vb2_unpack_key_buffer(&root_key,
307*8617a60dSAndroid Build Coastguard Worker state->rootkey.buf,
308*8617a60dSAndroid Build Coastguard Worker state->rootkey.len)) {
309*8617a60dSAndroid Build Coastguard Worker /* BIOS should have a rootkey in the GBB */
310*8617a60dSAndroid Build Coastguard Worker sign_key = &root_key;
311*8617a60dSAndroid Build Coastguard Worker }
312*8617a60dSAndroid Build Coastguard Worker
313*8617a60dSAndroid Build Coastguard Worker /* Identify the firmware body for this VBLOCK */
314*8617a60dSAndroid Build Coastguard Worker body_c = state->c == BIOS_FMAP_VBLOCK_A ? BIOS_FMAP_FW_MAIN_A
315*8617a60dSAndroid Build Coastguard Worker : BIOS_FMAP_FW_MAIN_B;
316*8617a60dSAndroid Build Coastguard Worker fw_body_area = &state->area[body_c];
317*8617a60dSAndroid Build Coastguard Worker }
318*8617a60dSAndroid Build Coastguard Worker
319*8617a60dSAndroid Build Coastguard Worker /* If we have a key, check the signature too */
320*8617a60dSAndroid Build Coastguard Worker if (sign_key && VB2_SUCCESS ==
321*8617a60dSAndroid Build Coastguard Worker vb2_verify_keyblock(keyblock, len, sign_key, &wb))
322*8617a60dSAndroid Build Coastguard Worker good_sig = 1;
323*8617a60dSAndroid Build Coastguard Worker else if (show_option.strict)
324*8617a60dSAndroid Build Coastguard Worker retval = 1;
325*8617a60dSAndroid Build Coastguard Worker
326*8617a60dSAndroid Build Coastguard Worker show_keyblock(keyblock, print_name, !!sign_key, good_sig);
327*8617a60dSAndroid Build Coastguard Worker
328*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key data_key;
329*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
330*8617a60dSAndroid Build Coastguard Worker ERROR("Parsing data key in %s\n", print_name);
331*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("data_key::invalid\n");
332*8617a60dSAndroid Build Coastguard Worker return 1;
333*8617a60dSAndroid Build Coastguard Worker }
334*8617a60dSAndroid Build Coastguard Worker
335*8617a60dSAndroid Build Coastguard Worker ft_print_header2 = "preamble";
336*8617a60dSAndroid Build Coastguard Worker uint32_t more = keyblock->keyblock_size;
337*8617a60dSAndroid Build Coastguard Worker struct vb2_fw_preamble *pre2 = (struct vb2_fw_preamble *)(buf + more);
338*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_verify_fw_preamble(pre2, len - more,
339*8617a60dSAndroid Build Coastguard Worker &data_key, &wb)) {
340*8617a60dSAndroid Build Coastguard Worker ERROR("%s is invalid\n", print_name);
341*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("invalid\n");
342*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("signature::invalid\n");
343*8617a60dSAndroid Build Coastguard Worker return 1;
344*8617a60dSAndroid Build Coastguard Worker } else {
345*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("valid\n");
346*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("signature::valid\n");
347*8617a60dSAndroid Build Coastguard Worker }
348*8617a60dSAndroid Build Coastguard Worker
349*8617a60dSAndroid Build Coastguard Worker uint32_t flags = pre2->flags;
350*8617a60dSAndroid Build Coastguard Worker if (pre2->header_version_minor < 1)
351*8617a60dSAndroid Build Coastguard Worker flags = 0; /* Old 2.0 structure didn't have flags */
352*8617a60dSAndroid Build Coastguard Worker
353*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Firmware Preamble:\n");
354*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Size: %d\n", "size::%d\n",
355*8617a60dSAndroid Build Coastguard Worker pre2->preamble_size);
356*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Header version: %d.%d\n",
357*8617a60dSAndroid Build Coastguard Worker "header_version::%d.%d\n",
358*8617a60dSAndroid Build Coastguard Worker pre2->header_version_major,
359*8617a60dSAndroid Build Coastguard Worker pre2->header_version_minor);
360*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Firmware version: %d\n", "firmware_version::%d\n",
361*8617a60dSAndroid Build Coastguard Worker pre2->firmware_version);
362*8617a60dSAndroid Build Coastguard Worker
363*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *kernel_subkey = &pre2->kernel_subkey;
364*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Kernel key algorithm: %d %s\n",
365*8617a60dSAndroid Build Coastguard Worker "kernel_subkey::algorithm::%d::%s\n",
366*8617a60dSAndroid Build Coastguard Worker kernel_subkey->algorithm,
367*8617a60dSAndroid Build Coastguard Worker vb2_get_crypto_algorithm_name(kernel_subkey->algorithm));
368*8617a60dSAndroid Build Coastguard Worker if (kernel_subkey->algorithm >= VB2_ALG_COUNT)
369*8617a60dSAndroid Build Coastguard Worker retval = 1;
370*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Kernel key version: %d\n",
371*8617a60dSAndroid Build Coastguard Worker "kernel_subkey::version::%d\n",
372*8617a60dSAndroid Build Coastguard Worker kernel_subkey->key_version);
373*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Kernel key sha1sum: %s\n",
374*8617a60dSAndroid Build Coastguard Worker "kernel_subkey::sha1_sum::%s\n",
375*8617a60dSAndroid Build Coastguard Worker packed_key_sha1_string(kernel_subkey));
376*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT(" Firmware body size: %d\n",
377*8617a60dSAndroid Build Coastguard Worker pre2->body_signature.data_size);
378*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Preamble flags: %d\n",
379*8617a60dSAndroid Build Coastguard Worker "flags::%d\n", flags);
380*8617a60dSAndroid Build Coastguard Worker ft_print_header2 = NULL;
381*8617a60dSAndroid Build Coastguard Worker
382*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::size::%d\n", pre2->body_signature.data_size);
383*8617a60dSAndroid Build Coastguard Worker
384*8617a60dSAndroid Build Coastguard Worker
385*8617a60dSAndroid Build Coastguard Worker if (flags & VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
386*8617a60dSAndroid Build Coastguard Worker FT_PRINT("Preamble requests USE_RO_NORMAL;"
387*8617a60dSAndroid Build Coastguard Worker " skipping body verification.\n",
388*8617a60dSAndroid Build Coastguard Worker "body::signature::ignored\n");
389*8617a60dSAndroid Build Coastguard Worker goto done;
390*8617a60dSAndroid Build Coastguard Worker }
391*8617a60dSAndroid Build Coastguard Worker
392*8617a60dSAndroid Build Coastguard Worker /* We'll need to get the firmware body from somewhere... */
393*8617a60dSAndroid Build Coastguard Worker if (fw_body_area && fw_body_area->is_valid) {
394*8617a60dSAndroid Build Coastguard Worker fv_data = fw_body_area->buf;
395*8617a60dSAndroid Build Coastguard Worker fv_size = fw_body_area->len;
396*8617a60dSAndroid Build Coastguard Worker }
397*8617a60dSAndroid Build Coastguard Worker
398*8617a60dSAndroid Build Coastguard Worker if (!fv_data) {
399*8617a60dSAndroid Build Coastguard Worker FT_PRINT("No firmware body available to verify.\n",
400*8617a60dSAndroid Build Coastguard Worker "body::signature::ignored\n");
401*8617a60dSAndroid Build Coastguard Worker if (show_option.strict)
402*8617a60dSAndroid Build Coastguard Worker return 1;
403*8617a60dSAndroid Build Coastguard Worker return 0;
404*8617a60dSAndroid Build Coastguard Worker }
405*8617a60dSAndroid Build Coastguard Worker
406*8617a60dSAndroid Build Coastguard Worker if (pre2->body_signature.data_size) {
407*8617a60dSAndroid Build Coastguard Worker if (vb2_verify_data(fv_data, fv_size, &pre2->body_signature,
408*8617a60dSAndroid Build Coastguard Worker &data_key, &wb) != VB2_SUCCESS) {
409*8617a60dSAndroid Build Coastguard Worker ERROR("Verifying firmware body.\n");
410*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::signature::invalid\n");
411*8617a60dSAndroid Build Coastguard Worker return show_option.strict ? 1 : 0;
412*8617a60dSAndroid Build Coastguard Worker }
413*8617a60dSAndroid Build Coastguard Worker } else if (state) { /* Only works if `fname` is a BIOS image */
414*8617a60dSAndroid Build Coastguard Worker if (fw_show_metadata_hash(fname, body_c, pre2))
415*8617a60dSAndroid Build Coastguard Worker return show_option.strict ? 1 : 0;
416*8617a60dSAndroid Build Coastguard Worker } else {
417*8617a60dSAndroid Build Coastguard Worker WARN("Metadata hash verification not supported.\n");
418*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::metadata_hash::ignored\n");
419*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::signature::ignored\n");
420*8617a60dSAndroid Build Coastguard Worker return show_option.strict ? 1 : 0;
421*8617a60dSAndroid Build Coastguard Worker }
422*8617a60dSAndroid Build Coastguard Worker
423*8617a60dSAndroid Build Coastguard Worker FT_PRINT("Body verification succeeded.\n",
424*8617a60dSAndroid Build Coastguard Worker "body::signature::valid\n");
425*8617a60dSAndroid Build Coastguard Worker
426*8617a60dSAndroid Build Coastguard Worker done:
427*8617a60dSAndroid Build Coastguard Worker /* Can't trust the BIOS unless everything is signed. */
428*8617a60dSAndroid Build Coastguard Worker if (good_sig) {
429*8617a60dSAndroid Build Coastguard Worker if (state)
430*8617a60dSAndroid Build Coastguard Worker state->area[state->c].is_valid = 1;
431*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("verified\n");
432*8617a60dSAndroid Build Coastguard Worker }
433*8617a60dSAndroid Build Coastguard Worker
434*8617a60dSAndroid Build Coastguard Worker return retval;
435*8617a60dSAndroid Build Coastguard Worker }
436*8617a60dSAndroid Build Coastguard Worker
ft_show_fw_preamble(const char * fname)437*8617a60dSAndroid Build Coastguard Worker int ft_show_fw_preamble(const char *fname)
438*8617a60dSAndroid Build Coastguard Worker {
439*8617a60dSAndroid Build Coastguard Worker int rv = 0;
440*8617a60dSAndroid Build Coastguard Worker int fd = -1;
441*8617a60dSAndroid Build Coastguard Worker uint8_t *buf;
442*8617a60dSAndroid Build Coastguard Worker uint32_t len;
443*8617a60dSAndroid Build Coastguard Worker
444*8617a60dSAndroid Build Coastguard Worker if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
445*8617a60dSAndroid Build Coastguard Worker return 1;
446*8617a60dSAndroid Build Coastguard Worker ft_print_header = "fw_pre";
447*8617a60dSAndroid Build Coastguard Worker rv = show_fw_preamble_buf(fname, buf, len, NULL);
448*8617a60dSAndroid Build Coastguard Worker
449*8617a60dSAndroid Build Coastguard Worker futil_unmap_and_close_file(fd, FILE_RO, buf, len);
450*8617a60dSAndroid Build Coastguard Worker return rv;
451*8617a60dSAndroid Build Coastguard Worker }
452*8617a60dSAndroid Build Coastguard Worker
ft_show_kernel_preamble(const char * fname)453*8617a60dSAndroid Build Coastguard Worker int ft_show_kernel_preamble(const char *fname)
454*8617a60dSAndroid Build Coastguard Worker {
455*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *keyblock;
456*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key *sign_key = show_option.k;
457*8617a60dSAndroid Build Coastguard Worker int retval = 0;
458*8617a60dSAndroid Build Coastguard Worker int fd = -1;
459*8617a60dSAndroid Build Coastguard Worker uint8_t *buf;
460*8617a60dSAndroid Build Coastguard Worker uint32_t len;
461*8617a60dSAndroid Build Coastguard Worker
462*8617a60dSAndroid Build Coastguard Worker if (futil_open_and_map_file(fname, &fd, FILE_RO, &buf, &len))
463*8617a60dSAndroid Build Coastguard Worker return 1;
464*8617a60dSAndroid Build Coastguard Worker
465*8617a60dSAndroid Build Coastguard Worker keyblock = (struct vb2_keyblock *)buf;
466*8617a60dSAndroid Build Coastguard Worker ft_print_header = "kernel";
467*8617a60dSAndroid Build Coastguard Worker ft_print_header2 = "keyblock";
468*8617a60dSAndroid Build Coastguard Worker /* Check the hash... */
469*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_verify_keyblock_hash(keyblock, len, &wb)) {
470*8617a60dSAndroid Build Coastguard Worker ERROR("%s keyblock component is invalid\n", fname);
471*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("invalid\n");
472*8617a60dSAndroid Build Coastguard Worker retval = 1;
473*8617a60dSAndroid Build Coastguard Worker goto done;
474*8617a60dSAndroid Build Coastguard Worker } else {
475*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("valid\n");
476*8617a60dSAndroid Build Coastguard Worker }
477*8617a60dSAndroid Build Coastguard Worker
478*8617a60dSAndroid Build Coastguard Worker /* If we have a key, check the signature too */
479*8617a60dSAndroid Build Coastguard Worker int good_sig = 0;
480*8617a60dSAndroid Build Coastguard Worker if (sign_key && VB2_SUCCESS ==
481*8617a60dSAndroid Build Coastguard Worker vb2_verify_keyblock(keyblock, len, sign_key, &wb))
482*8617a60dSAndroid Build Coastguard Worker good_sig = 1;
483*8617a60dSAndroid Build Coastguard Worker else if (show_option.strict)
484*8617a60dSAndroid Build Coastguard Worker retval = 1;
485*8617a60dSAndroid Build Coastguard Worker
486*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Kernel partition: %s\n", fname);
487*8617a60dSAndroid Build Coastguard Worker show_keyblock(keyblock, NULL, !!sign_key, good_sig);
488*8617a60dSAndroid Build Coastguard Worker
489*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key data_key;
490*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
491*8617a60dSAndroid Build Coastguard Worker ERROR("Parsing data key in %s\n", fname);
492*8617a60dSAndroid Build Coastguard Worker retval = 1;
493*8617a60dSAndroid Build Coastguard Worker goto done;
494*8617a60dSAndroid Build Coastguard Worker }
495*8617a60dSAndroid Build Coastguard Worker
496*8617a60dSAndroid Build Coastguard Worker ft_print_header2 = NULL;
497*8617a60dSAndroid Build Coastguard Worker uint32_t more = keyblock->keyblock_size;
498*8617a60dSAndroid Build Coastguard Worker struct vb2_kernel_preamble *pre2 =
499*8617a60dSAndroid Build Coastguard Worker (struct vb2_kernel_preamble *)(buf + more);
500*8617a60dSAndroid Build Coastguard Worker
501*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_verify_kernel_preamble(pre2, len - more,
502*8617a60dSAndroid Build Coastguard Worker &data_key, &wb)) {
503*8617a60dSAndroid Build Coastguard Worker ERROR("%s is invalid\n", fname);
504*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("preamble::invalid\n");
505*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("preamble::signature::invalid\n");
506*8617a60dSAndroid Build Coastguard Worker retval = 1;
507*8617a60dSAndroid Build Coastguard Worker goto done;
508*8617a60dSAndroid Build Coastguard Worker }
509*8617a60dSAndroid Build Coastguard Worker
510*8617a60dSAndroid Build Coastguard Worker more += pre2->preamble_size;
511*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("preamble::valid\n");
512*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("preamble::signature::valid\n");
513*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Kernel Preamble:\n");
514*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Size: %#x\n",
515*8617a60dSAndroid Build Coastguard Worker "preamble::size::%d\n", pre2->preamble_size);
516*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Header version: %d.%d\n",
517*8617a60dSAndroid Build Coastguard Worker "preamble::header_version::%d.%d\n",
518*8617a60dSAndroid Build Coastguard Worker pre2->header_version_major,
519*8617a60dSAndroid Build Coastguard Worker pre2->header_version_minor);
520*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Kernel version: %u\n",
521*8617a60dSAndroid Build Coastguard Worker "preamble::kernel_version::%u\n",
522*8617a60dSAndroid Build Coastguard Worker pre2->kernel_version);
523*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Flags: %#x\n",
524*8617a60dSAndroid Build Coastguard Worker "preamble::flags::%d\n", vb2_kernel_get_flags(pre2));
525*8617a60dSAndroid Build Coastguard Worker
526*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Body load address: 0x%" PRIx64 "\n",
527*8617a60dSAndroid Build Coastguard Worker "body::address::%" PRIu64 "\n",
528*8617a60dSAndroid Build Coastguard Worker pre2->body_load_address);
529*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Body size: %#x\n",
530*8617a60dSAndroid Build Coastguard Worker "body::size::%d\n",
531*8617a60dSAndroid Build Coastguard Worker pre2->body_signature.data_size);
532*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Bootloader address: 0x%" PRIx64 "\n",
533*8617a60dSAndroid Build Coastguard Worker "bootloader::address::%" PRIu64 "\n",
534*8617a60dSAndroid Build Coastguard Worker pre2->bootloader_address);
535*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Bootloader size: %#x\n",
536*8617a60dSAndroid Build Coastguard Worker "bootloader::size::%d\n",
537*8617a60dSAndroid Build Coastguard Worker pre2->bootloader_size);
538*8617a60dSAndroid Build Coastguard Worker
539*8617a60dSAndroid Build Coastguard Worker uint64_t vmlinuz_header_address = 0;
540*8617a60dSAndroid Build Coastguard Worker uint32_t vmlinuz_header_size = 0;
541*8617a60dSAndroid Build Coastguard Worker vb2_kernel_get_vmlinuz_header(pre2,
542*8617a60dSAndroid Build Coastguard Worker &vmlinuz_header_address,
543*8617a60dSAndroid Build Coastguard Worker &vmlinuz_header_size);
544*8617a60dSAndroid Build Coastguard Worker if (vmlinuz_header_size) {
545*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Vmlinuz_header address: 0x%" PRIx64 "\n",
546*8617a60dSAndroid Build Coastguard Worker "vmlinuz_header::address::%" PRIu64 "\n",
547*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_address);
548*8617a60dSAndroid Build Coastguard Worker FT_PRINT(" Vmlinuz header size: %#x\n",
549*8617a60dSAndroid Build Coastguard Worker "vmlinuz_header::size::%d\n",
550*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_size);
551*8617a60dSAndroid Build Coastguard Worker }
552*8617a60dSAndroid Build Coastguard Worker
553*8617a60dSAndroid Build Coastguard Worker /* Verify kernel body */
554*8617a60dSAndroid Build Coastguard Worker uint8_t *kernel_blob;
555*8617a60dSAndroid Build Coastguard Worker uint64_t kernel_size;
556*8617a60dSAndroid Build Coastguard Worker if (show_option.fv) {
557*8617a60dSAndroid Build Coastguard Worker /* It's in a separate file, which we've already read in */
558*8617a60dSAndroid Build Coastguard Worker kernel_blob = show_option.fv;
559*8617a60dSAndroid Build Coastguard Worker kernel_size = show_option.fv_size;
560*8617a60dSAndroid Build Coastguard Worker } else {
561*8617a60dSAndroid Build Coastguard Worker /* It should be at an offset within the input file. */
562*8617a60dSAndroid Build Coastguard Worker kernel_blob = buf + more;
563*8617a60dSAndroid Build Coastguard Worker kernel_size = len - more;
564*8617a60dSAndroid Build Coastguard Worker }
565*8617a60dSAndroid Build Coastguard Worker
566*8617a60dSAndroid Build Coastguard Worker if (!kernel_size) {
567*8617a60dSAndroid Build Coastguard Worker FT_PRINT("No kernel blob available to verify.\n",
568*8617a60dSAndroid Build Coastguard Worker "body::signature::ignored\n");
569*8617a60dSAndroid Build Coastguard Worker if (show_option.strict)
570*8617a60dSAndroid Build Coastguard Worker retval = 1;
571*8617a60dSAndroid Build Coastguard Worker goto done;
572*8617a60dSAndroid Build Coastguard Worker }
573*8617a60dSAndroid Build Coastguard Worker
574*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS !=
575*8617a60dSAndroid Build Coastguard Worker vb2_verify_data(kernel_blob, kernel_size, &pre2->body_signature,
576*8617a60dSAndroid Build Coastguard Worker &data_key, &wb)) {
577*8617a60dSAndroid Build Coastguard Worker ERROR("Verifying kernel body.\n");
578*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("body::signature::invalid\n");
579*8617a60dSAndroid Build Coastguard Worker if (show_option.strict)
580*8617a60dSAndroid Build Coastguard Worker retval = 1;
581*8617a60dSAndroid Build Coastguard Worker goto done;
582*8617a60dSAndroid Build Coastguard Worker }
583*8617a60dSAndroid Build Coastguard Worker
584*8617a60dSAndroid Build Coastguard Worker FT_PRINT("Body verification succeeded.\n",
585*8617a60dSAndroid Build Coastguard Worker "body::signature::valid\n");
586*8617a60dSAndroid Build Coastguard Worker if (good_sig)
587*8617a60dSAndroid Build Coastguard Worker FT_PARSEABLE_PRINT("verified\n");
588*8617a60dSAndroid Build Coastguard Worker
589*8617a60dSAndroid Build Coastguard Worker FT_READABLE_PRINT("Config:\n%s\n",
590*8617a60dSAndroid Build Coastguard Worker kernel_blob + kernel_cmd_line_offset(pre2));
591*8617a60dSAndroid Build Coastguard Worker
592*8617a60dSAndroid Build Coastguard Worker done:
593*8617a60dSAndroid Build Coastguard Worker futil_unmap_and_close_file(fd, FILE_RO, buf, len);
594*8617a60dSAndroid Build Coastguard Worker return retval;
595*8617a60dSAndroid Build Coastguard Worker }
596*8617a60dSAndroid Build Coastguard Worker
597*8617a60dSAndroid Build Coastguard Worker enum no_short_opts {
598*8617a60dSAndroid Build Coastguard Worker OPT_TYPE = 1000,
599*8617a60dSAndroid Build Coastguard Worker OPT_PUBKEY,
600*8617a60dSAndroid Build Coastguard Worker OPT_HELP,
601*8617a60dSAndroid Build Coastguard Worker };
602*8617a60dSAndroid Build Coastguard Worker
603*8617a60dSAndroid Build Coastguard Worker static const char usage[] = "\n"
604*8617a60dSAndroid Build Coastguard Worker "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n"
605*8617a60dSAndroid Build Coastguard Worker "\n"
606*8617a60dSAndroid Build Coastguard Worker "Where FILE could be\n"
607*8617a60dSAndroid Build Coastguard Worker "\n"
608*8617a60dSAndroid Build Coastguard Worker " a boot descriptor block (BDB)\n"
609*8617a60dSAndroid Build Coastguard Worker " a keyblock (.keyblock)\n"
610*8617a60dSAndroid Build Coastguard Worker " a firmware preamble signature (VBLOCK_A/B)\n"
611*8617a60dSAndroid Build Coastguard Worker " a firmware image (image.bin)\n"
612*8617a60dSAndroid Build Coastguard Worker " a kernel partition (/dev/sda2, /dev/mmcblk0p2)\n"
613*8617a60dSAndroid Build Coastguard Worker " keys in various formats (.vbpubk, .vbprivk, .pem)\n"
614*8617a60dSAndroid Build Coastguard Worker " several other file types related to verified boot\n"
615*8617a60dSAndroid Build Coastguard Worker "\n"
616*8617a60dSAndroid Build Coastguard Worker "Options:\n"
617*8617a60dSAndroid Build Coastguard Worker " -t Just show the type of each file\n"
618*8617a60dSAndroid Build Coastguard Worker " --type TYPE Override the detected file type\n"
619*8617a60dSAndroid Build Coastguard Worker " Use \"--type help\" for a list\n"
620*8617a60dSAndroid Build Coastguard Worker " -P|--parseable Machine friendly output format\n"
621*8617a60dSAndroid Build Coastguard Worker "Type-specific options:\n"
622*8617a60dSAndroid Build Coastguard Worker " -k|--publickey FILE.vbpubk Public key in vb1 format\n"
623*8617a60dSAndroid Build Coastguard Worker " --pubkey FILE.vpubk2 Public key in vb2 format\n"
624*8617a60dSAndroid Build Coastguard Worker " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
625*8617a60dSAndroid Build Coastguard Worker " --strict "
626*8617a60dSAndroid Build Coastguard Worker "Fail unless all signatures are valid\n"
627*8617a60dSAndroid Build Coastguard Worker "\n";
628*8617a60dSAndroid Build Coastguard Worker
print_help(int argc,char * argv[])629*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
630*8617a60dSAndroid Build Coastguard Worker {
631*8617a60dSAndroid Build Coastguard Worker if (!strcmp(argv[0], "verify"))
632*8617a60dSAndroid Build Coastguard Worker printf("\nUsage: " MYNAME " %s [OPTIONS] FILE [...]\n\n"
633*8617a60dSAndroid Build Coastguard Worker "This is just an alias for\n\n"
634*8617a60dSAndroid Build Coastguard Worker " " MYNAME " show --strict\n\n",
635*8617a60dSAndroid Build Coastguard Worker argv[0]);
636*8617a60dSAndroid Build Coastguard Worker
637*8617a60dSAndroid Build Coastguard Worker printf(usage, "show");
638*8617a60dSAndroid Build Coastguard Worker }
639*8617a60dSAndroid Build Coastguard Worker
640*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
641*8617a60dSAndroid Build Coastguard Worker /* name hasarg *flag val */
642*8617a60dSAndroid Build Coastguard Worker {"publickey", 1, 0, 'k'},
643*8617a60dSAndroid Build Coastguard Worker {"fv", 1, 0, 'f'},
644*8617a60dSAndroid Build Coastguard Worker {"type", 1, NULL, OPT_TYPE},
645*8617a60dSAndroid Build Coastguard Worker {"strict", 0, &show_option.strict, 1},
646*8617a60dSAndroid Build Coastguard Worker {"pubkey", 1, NULL, OPT_PUBKEY},
647*8617a60dSAndroid Build Coastguard Worker {"parseable", 0, NULL, 'P'},
648*8617a60dSAndroid Build Coastguard Worker {"help", 0, NULL, OPT_HELP},
649*8617a60dSAndroid Build Coastguard Worker {NULL, 0, NULL, 0},
650*8617a60dSAndroid Build Coastguard Worker };
651*8617a60dSAndroid Build Coastguard Worker static const char *short_opts = ":f:k:Pt";
652*8617a60dSAndroid Build Coastguard Worker
653*8617a60dSAndroid Build Coastguard Worker
show_type(char * filename)654*8617a60dSAndroid Build Coastguard Worker static int show_type(char *filename)
655*8617a60dSAndroid Build Coastguard Worker {
656*8617a60dSAndroid Build Coastguard Worker enum futil_file_err err;
657*8617a60dSAndroid Build Coastguard Worker enum futil_file_type type;
658*8617a60dSAndroid Build Coastguard Worker err = futil_file_type(filename, &type);
659*8617a60dSAndroid Build Coastguard Worker switch (err) {
660*8617a60dSAndroid Build Coastguard Worker case FILE_ERR_NONE:
661*8617a60dSAndroid Build Coastguard Worker printf("%s:\t%s\n", filename, futil_file_type_name(type));
662*8617a60dSAndroid Build Coastguard Worker /* Only our recognized types return success */
663*8617a60dSAndroid Build Coastguard Worker return 0;
664*8617a60dSAndroid Build Coastguard Worker case FILE_ERR_DIR:
665*8617a60dSAndroid Build Coastguard Worker printf("%s:\t%s\n", filename, "directory");
666*8617a60dSAndroid Build Coastguard Worker break;
667*8617a60dSAndroid Build Coastguard Worker case FILE_ERR_CHR:
668*8617a60dSAndroid Build Coastguard Worker printf("%s:\t%s\n", filename, "character special");
669*8617a60dSAndroid Build Coastguard Worker break;
670*8617a60dSAndroid Build Coastguard Worker case FILE_ERR_FIFO:
671*8617a60dSAndroid Build Coastguard Worker printf("%s:\t%s\n", filename, "FIFO");
672*8617a60dSAndroid Build Coastguard Worker break;
673*8617a60dSAndroid Build Coastguard Worker case FILE_ERR_SOCK:
674*8617a60dSAndroid Build Coastguard Worker printf("%s:\t%s\n", filename, "socket");
675*8617a60dSAndroid Build Coastguard Worker break;
676*8617a60dSAndroid Build Coastguard Worker default:
677*8617a60dSAndroid Build Coastguard Worker break;
678*8617a60dSAndroid Build Coastguard Worker }
679*8617a60dSAndroid Build Coastguard Worker /* Everything else is an error */
680*8617a60dSAndroid Build Coastguard Worker return 1;
681*8617a60dSAndroid Build Coastguard Worker }
682*8617a60dSAndroid Build Coastguard Worker
load_publickey(const char * fname,uint8_t ** buf_ptr,struct vb2_public_key * pubkey)683*8617a60dSAndroid Build Coastguard Worker static int load_publickey(const char *fname, uint8_t **buf_ptr,
684*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key *pubkey)
685*8617a60dSAndroid Build Coastguard Worker {
686*8617a60dSAndroid Build Coastguard Worker uint32_t len = 0;
687*8617a60dSAndroid Build Coastguard Worker if (vb2_read_file(fname, buf_ptr, &len) != VB2_SUCCESS) {
688*8617a60dSAndroid Build Coastguard Worker ERROR("Reading publickey %s\n", fname);
689*8617a60dSAndroid Build Coastguard Worker return 1;
690*8617a60dSAndroid Build Coastguard Worker }
691*8617a60dSAndroid Build Coastguard Worker
692*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *keyblock;
693*8617a60dSAndroid Build Coastguard Worker uint8_t *buf = *buf_ptr;
694*8617a60dSAndroid Build Coastguard Worker enum futil_file_type type = futil_file_type_buf(buf, len);
695*8617a60dSAndroid Build Coastguard Worker switch (type) {
696*8617a60dSAndroid Build Coastguard Worker case FILE_TYPE_FW_PREAMBLE:
697*8617a60dSAndroid Build Coastguard Worker keyblock = (struct vb2_keyblock *)buf;
698*8617a60dSAndroid Build Coastguard Worker if (vb2_check_keyblock(keyblock, len, &keyblock->keyblock_hash)
699*8617a60dSAndroid Build Coastguard Worker != VB2_SUCCESS) {
700*8617a60dSAndroid Build Coastguard Worker ERROR("Checking publickey keyblock\n");
701*8617a60dSAndroid Build Coastguard Worker return 1;
702*8617a60dSAndroid Build Coastguard Worker }
703*8617a60dSAndroid Build Coastguard Worker struct vb2_fw_preamble *pre =
704*8617a60dSAndroid Build Coastguard Worker (struct vb2_fw_preamble *)(buf + keyblock->keyblock_size);
705*8617a60dSAndroid Build Coastguard Worker if (vb2_unpack_key(pubkey, &pre->kernel_subkey) != VB2_SUCCESS) {
706*8617a60dSAndroid Build Coastguard Worker ERROR("Unpacking publickey from preamble %s\n", fname);
707*8617a60dSAndroid Build Coastguard Worker return 1;
708*8617a60dSAndroid Build Coastguard Worker }
709*8617a60dSAndroid Build Coastguard Worker break;
710*8617a60dSAndroid Build Coastguard Worker case FILE_TYPE_PUBKEY:
711*8617a60dSAndroid Build Coastguard Worker if (vb2_unpack_key_buffer(pubkey, buf, len) != VB2_SUCCESS) {
712*8617a60dSAndroid Build Coastguard Worker ERROR("Unpacking publickey %s\n", fname);
713*8617a60dSAndroid Build Coastguard Worker return 1;
714*8617a60dSAndroid Build Coastguard Worker }
715*8617a60dSAndroid Build Coastguard Worker break;
716*8617a60dSAndroid Build Coastguard Worker default:
717*8617a60dSAndroid Build Coastguard Worker ERROR("Unsupported file type '%s' for publickey %s\n",
718*8617a60dSAndroid Build Coastguard Worker futil_file_type_name(type), fname);
719*8617a60dSAndroid Build Coastguard Worker return 1;
720*8617a60dSAndroid Build Coastguard Worker }
721*8617a60dSAndroid Build Coastguard Worker
722*8617a60dSAndroid Build Coastguard Worker return 0;
723*8617a60dSAndroid Build Coastguard Worker }
724*8617a60dSAndroid Build Coastguard Worker
do_show(int argc,char * argv[])725*8617a60dSAndroid Build Coastguard Worker static int do_show(int argc, char *argv[])
726*8617a60dSAndroid Build Coastguard Worker {
727*8617a60dSAndroid Build Coastguard Worker uint8_t *pubkbuf = NULL;
728*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key pubk2;
729*8617a60dSAndroid Build Coastguard Worker char *infile = 0;
730*8617a60dSAndroid Build Coastguard Worker int i;
731*8617a60dSAndroid Build Coastguard Worker int errorcnt = 0;
732*8617a60dSAndroid Build Coastguard Worker int type_override = 0;
733*8617a60dSAndroid Build Coastguard Worker enum futil_file_type type;
734*8617a60dSAndroid Build Coastguard Worker
735*8617a60dSAndroid Build Coastguard Worker vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
736*8617a60dSAndroid Build Coastguard Worker
737*8617a60dSAndroid Build Coastguard Worker opterr = 0; /* quiet, you */
738*8617a60dSAndroid Build Coastguard Worker while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
739*8617a60dSAndroid Build Coastguard Worker switch (i) {
740*8617a60dSAndroid Build Coastguard Worker case 'f':
741*8617a60dSAndroid Build Coastguard Worker show_option.fv = ReadFile(optarg,
742*8617a60dSAndroid Build Coastguard Worker &show_option.fv_size);
743*8617a60dSAndroid Build Coastguard Worker if (!show_option.fv) {
744*8617a60dSAndroid Build Coastguard Worker ERROR("Reading %s: %s\n",
745*8617a60dSAndroid Build Coastguard Worker optarg, strerror(errno));
746*8617a60dSAndroid Build Coastguard Worker errorcnt++;
747*8617a60dSAndroid Build Coastguard Worker }
748*8617a60dSAndroid Build Coastguard Worker break;
749*8617a60dSAndroid Build Coastguard Worker case 'k':
750*8617a60dSAndroid Build Coastguard Worker if (load_publickey(optarg, &pubkbuf, &pubk2)) {
751*8617a60dSAndroid Build Coastguard Worker ERROR("Loading publickey %s\n", optarg);
752*8617a60dSAndroid Build Coastguard Worker errorcnt++;
753*8617a60dSAndroid Build Coastguard Worker break;
754*8617a60dSAndroid Build Coastguard Worker }
755*8617a60dSAndroid Build Coastguard Worker show_option.k = &pubk2;
756*8617a60dSAndroid Build Coastguard Worker break;
757*8617a60dSAndroid Build Coastguard Worker case 't':
758*8617a60dSAndroid Build Coastguard Worker show_option.t_flag = 1;
759*8617a60dSAndroid Build Coastguard Worker break;
760*8617a60dSAndroid Build Coastguard Worker case 'P':
761*8617a60dSAndroid Build Coastguard Worker show_option.parseable = true;
762*8617a60dSAndroid Build Coastguard Worker break;
763*8617a60dSAndroid Build Coastguard Worker case OPT_TYPE:
764*8617a60dSAndroid Build Coastguard Worker if (!futil_str_to_file_type(optarg,
765*8617a60dSAndroid Build Coastguard Worker &show_option.type)) {
766*8617a60dSAndroid Build Coastguard Worker if (!strcasecmp("help", optarg))
767*8617a60dSAndroid Build Coastguard Worker print_file_types_and_exit(errorcnt);
768*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid --type \"%s\"\n", optarg);
769*8617a60dSAndroid Build Coastguard Worker errorcnt++;
770*8617a60dSAndroid Build Coastguard Worker }
771*8617a60dSAndroid Build Coastguard Worker type_override = 1;
772*8617a60dSAndroid Build Coastguard Worker break;
773*8617a60dSAndroid Build Coastguard Worker case OPT_PUBKEY:
774*8617a60dSAndroid Build Coastguard Worker if (vb21_packed_key_read(&show_option.pkey, optarg)) {
775*8617a60dSAndroid Build Coastguard Worker ERROR("Reading %s\n", optarg);
776*8617a60dSAndroid Build Coastguard Worker errorcnt++;
777*8617a60dSAndroid Build Coastguard Worker }
778*8617a60dSAndroid Build Coastguard Worker break;
779*8617a60dSAndroid Build Coastguard Worker case OPT_HELP:
780*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
781*8617a60dSAndroid Build Coastguard Worker return !!errorcnt;
782*8617a60dSAndroid Build Coastguard Worker
783*8617a60dSAndroid Build Coastguard Worker case '?':
784*8617a60dSAndroid Build Coastguard Worker if (optopt)
785*8617a60dSAndroid Build Coastguard Worker ERROR("Unrecognized option: -%c\n",
786*8617a60dSAndroid Build Coastguard Worker optopt);
787*8617a60dSAndroid Build Coastguard Worker else
788*8617a60dSAndroid Build Coastguard Worker ERROR("Unrecognized option\n");
789*8617a60dSAndroid Build Coastguard Worker errorcnt++;
790*8617a60dSAndroid Build Coastguard Worker break;
791*8617a60dSAndroid Build Coastguard Worker case ':':
792*8617a60dSAndroid Build Coastguard Worker ERROR("Missing argument to -%c\n", optopt);
793*8617a60dSAndroid Build Coastguard Worker errorcnt++;
794*8617a60dSAndroid Build Coastguard Worker break;
795*8617a60dSAndroid Build Coastguard Worker case 0: /* handled option */
796*8617a60dSAndroid Build Coastguard Worker break;
797*8617a60dSAndroid Build Coastguard Worker default:
798*8617a60dSAndroid Build Coastguard Worker FATAL("Unrecognized getopt output: %d\n", i);
799*8617a60dSAndroid Build Coastguard Worker }
800*8617a60dSAndroid Build Coastguard Worker }
801*8617a60dSAndroid Build Coastguard Worker
802*8617a60dSAndroid Build Coastguard Worker if (errorcnt) {
803*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
804*8617a60dSAndroid Build Coastguard Worker return 1;
805*8617a60dSAndroid Build Coastguard Worker }
806*8617a60dSAndroid Build Coastguard Worker
807*8617a60dSAndroid Build Coastguard Worker if (argc - optind < 1) {
808*8617a60dSAndroid Build Coastguard Worker ERROR("Missing input filename\n");
809*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
810*8617a60dSAndroid Build Coastguard Worker return 1;
811*8617a60dSAndroid Build Coastguard Worker }
812*8617a60dSAndroid Build Coastguard Worker
813*8617a60dSAndroid Build Coastguard Worker if (show_option.t_flag) {
814*8617a60dSAndroid Build Coastguard Worker for (i = optind; i < argc; i++)
815*8617a60dSAndroid Build Coastguard Worker errorcnt += show_type(argv[i]);
816*8617a60dSAndroid Build Coastguard Worker goto done;
817*8617a60dSAndroid Build Coastguard Worker }
818*8617a60dSAndroid Build Coastguard Worker
819*8617a60dSAndroid Build Coastguard Worker for (i = optind; i < argc; i++) {
820*8617a60dSAndroid Build Coastguard Worker infile = argv[i];
821*8617a60dSAndroid Build Coastguard Worker
822*8617a60dSAndroid Build Coastguard Worker /* Allow the user to override the type */
823*8617a60dSAndroid Build Coastguard Worker if (type_override)
824*8617a60dSAndroid Build Coastguard Worker type = show_option.type;
825*8617a60dSAndroid Build Coastguard Worker else
826*8617a60dSAndroid Build Coastguard Worker futil_file_type(infile, &type);
827*8617a60dSAndroid Build Coastguard Worker
828*8617a60dSAndroid Build Coastguard Worker errorcnt += futil_file_type_show(type, infile);
829*8617a60dSAndroid Build Coastguard Worker }
830*8617a60dSAndroid Build Coastguard Worker
831*8617a60dSAndroid Build Coastguard Worker done:
832*8617a60dSAndroid Build Coastguard Worker if (pubkbuf)
833*8617a60dSAndroid Build Coastguard Worker free(pubkbuf);
834*8617a60dSAndroid Build Coastguard Worker if (show_option.fv)
835*8617a60dSAndroid Build Coastguard Worker free(show_option.fv);
836*8617a60dSAndroid Build Coastguard Worker
837*8617a60dSAndroid Build Coastguard Worker return !!errorcnt;
838*8617a60dSAndroid Build Coastguard Worker }
839*8617a60dSAndroid Build Coastguard Worker
840*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL,
841*8617a60dSAndroid Build Coastguard Worker "Display the content of various binary components");
842*8617a60dSAndroid Build Coastguard Worker
do_verify(int argc,char * argv[])843*8617a60dSAndroid Build Coastguard Worker static int do_verify(int argc, char *argv[])
844*8617a60dSAndroid Build Coastguard Worker {
845*8617a60dSAndroid Build Coastguard Worker show_option.strict = 1;
846*8617a60dSAndroid Build Coastguard Worker return do_show(argc, argv);
847*8617a60dSAndroid Build Coastguard Worker }
848*8617a60dSAndroid Build Coastguard Worker
849*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(verify, do_verify,
850*8617a60dSAndroid Build Coastguard Worker VBOOT_VERSION_ALL,
851*8617a60dSAndroid Build Coastguard Worker "Verify the signatures of various binary components. "
852*8617a60dSAndroid Build Coastguard Worker "This does not verify GSCVD contents.");
853