xref: /aosp_15_r20/external/vboot_reference/futility/cmd_gscvd.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2021 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 <errno.h>
7*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
8*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
9*8617a60dSAndroid Build Coastguard Worker #include <openssl/bn.h>
10*8617a60dSAndroid Build Coastguard Worker #include <openssl/pem.h>
11*8617a60dSAndroid Build Coastguard Worker #include <stdbool.h>
12*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
13*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
14*8617a60dSAndroid Build Coastguard Worker 
15*8617a60dSAndroid Build Coastguard Worker #include "fmap.h"
16*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
17*8617a60dSAndroid Build Coastguard Worker #include "gsc_ro.h"
18*8617a60dSAndroid Build Coastguard Worker #include "host_key21.h"
19*8617a60dSAndroid Build Coastguard Worker #include "host_keyblock.h"
20*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
21*8617a60dSAndroid Build Coastguard Worker #include "host_signature.h"
22*8617a60dSAndroid Build Coastguard Worker #include "host_p11.h"
23*8617a60dSAndroid Build Coastguard Worker 
24*8617a60dSAndroid Build Coastguard Worker /*
25*8617a60dSAndroid Build Coastguard Worker  * for testing purposes let's use
26*8617a60dSAndroid Build Coastguard Worker  * - tests/devkeys/arv_root.vbprivk as the root private key
27*8617a60dSAndroid Build Coastguard Worker  * - tests/devkeys/arv_root.vbpubk as the root public key
28*8617a60dSAndroid Build Coastguard Worker  *   used for signing of the platform public key
29*8617a60dSAndroid Build Coastguard Worker  * - tests/devkeys/arv_platform.vbprivk signing platform key
30*8617a60dSAndroid Build Coastguard Worker  * - tests/devkeys/arv_platform.vbpubk - public key used for signature
31*8617a60dSAndroid Build Coastguard Worker  *       verification
32*8617a60dSAndroid Build Coastguard Worker  *------------
33*8617a60dSAndroid Build Coastguard Worker  * Command to create the signed public key block in ~/tmp/packed:
34*8617a60dSAndroid Build Coastguard Worker  *
35*8617a60dSAndroid Build Coastguard Worker   ./build/futility/futility vbutil_keyblock --pack ~/tmp/packed \
36*8617a60dSAndroid Build Coastguard Worker       --datapubkey  tests/devkeys/arv_platform.vbpubk \
37*8617a60dSAndroid Build Coastguard Worker       --signprivate tests/devkeys/arv_root.vbprivk
38*8617a60dSAndroid Build Coastguard Worker  *------------
39*8617a60dSAndroid Build Coastguard Worker  * Command to fill RO_GSCVD FMAP area in an AP firmware file. The input AP
40*8617a60dSAndroid Build Coastguard Worker  *   firmware file is ~/tmp/image-guybrush.serial.bin, the output signed
41*8617a60dSAndroid Build Coastguard Worker  *   AP firmware file is ~/tmp/guybrush-signed:
42*8617a60dSAndroid Build Coastguard Worker  *
43*8617a60dSAndroid Build Coastguard Worker   ./build/futility/futility gscvd --outfile ~/tmp/guybrush-signed \
44*8617a60dSAndroid Build Coastguard Worker     -R 818100:10000,f00000:100,f80000:2000,f8c000:1000,0x00804000:0x00000800 \
45*8617a60dSAndroid Build Coastguard Worker     -k ~/tmp/packed -p tests/devkeys/arv_platform.vbprivk -b 5a5a4352  \
46*8617a60dSAndroid Build Coastguard Worker     -r tests/devkeys/arv_root.vbpubk ~/tmp/image-guybrush.serial.bin
47*8617a60dSAndroid Build Coastguard Worker  *------------
48*8617a60dSAndroid Build Coastguard Worker  * Command to validate a previously signed AP firmware file. The hash is the
49*8617a60dSAndroid Build Coastguard Worker  *  sha256sum of tests/devkeys/kernel_subkey.vbpubk:
50*8617a60dSAndroid Build Coastguard Worker  *
51*8617a60dSAndroid Build Coastguard Worker   build/futility/futility gscvd ~/tmp/guybrush-signed \
52*8617a60dSAndroid Build Coastguard Worker    3d74429f35be8d34bcb425d4397e2218e6961afed456a78ce30047f5b54ed158
53*8617a60dSAndroid Build Coastguard Worker  */
54*8617a60dSAndroid Build Coastguard Worker 
55*8617a60dSAndroid Build Coastguard Worker /* Command line options processing support. */
56*8617a60dSAndroid Build Coastguard Worker enum no_short_opts {
57*8617a60dSAndroid Build Coastguard Worker 	OPT_OUTFILE = 1000,
58*8617a60dSAndroid Build Coastguard Worker 	OPT_RO_GSCVD_FILE = 1001,
59*8617a60dSAndroid Build Coastguard Worker };
60*8617a60dSAndroid Build Coastguard Worker 
61*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
62*8617a60dSAndroid Build Coastguard Worker 	/* name       hasarg *flag  val */
63*8617a60dSAndroid Build Coastguard Worker 	{"add_gbb",       0, NULL, 'G'},
64*8617a60dSAndroid Build Coastguard Worker 	{"board_id",      1, NULL, 'b'},
65*8617a60dSAndroid Build Coastguard Worker 	{"help",          0, NULL, 'h'},
66*8617a60dSAndroid Build Coastguard Worker 	{"keyblock",      1, NULL, 'k'},
67*8617a60dSAndroid Build Coastguard Worker 	{"outfile",       1, NULL, OPT_OUTFILE},
68*8617a60dSAndroid Build Coastguard Worker 	{"platform_priv", 1, NULL, 'p'},
69*8617a60dSAndroid Build Coastguard Worker 	{"ranges",        1, NULL, 'R'},
70*8617a60dSAndroid Build Coastguard Worker 	{"gscvd_out",     1, NULL, OPT_RO_GSCVD_FILE},
71*8617a60dSAndroid Build Coastguard Worker 	{"root_pub_key",  1, NULL, 'r'},
72*8617a60dSAndroid Build Coastguard Worker 	{}
73*8617a60dSAndroid Build Coastguard Worker };
74*8617a60dSAndroid Build Coastguard Worker 
75*8617a60dSAndroid Build Coastguard Worker static const char *short_opts = "R:Gb:hk:p:r:";
76*8617a60dSAndroid Build Coastguard Worker 
77*8617a60dSAndroid Build Coastguard Worker static const char usage[] =
78*8617a60dSAndroid Build Coastguard Worker 	"\n"
79*8617a60dSAndroid Build Coastguard Worker 	"This utility creates an RO verification space in the Chrome OS AP\n"
80*8617a60dSAndroid Build Coastguard Worker 	"firmware image, allows to validate a previously prepared image\n"
81*8617a60dSAndroid Build Coastguard Worker 	"containing the RO verification space, and prints out the hash of the\n"
82*8617a60dSAndroid Build Coastguard Worker 	"payload of the root public key.\n\n"
83*8617a60dSAndroid Build Coastguard Worker 	"Create a new GSCVD from scratch:\n"
84*8617a60dSAndroid Build Coastguard Worker 	"  "MYNAME" gscvd -R <ranges> PARAMS <firmware image>\n\n"
85*8617a60dSAndroid Build Coastguard Worker 	"Re-sign an existing GSCVD with new keys, preserving ranges:\n"
86*8617a60dSAndroid Build Coastguard Worker 	"  "MYNAME" gscvd PARAMS <firmware image>\n\n"
87*8617a60dSAndroid Build Coastguard Worker 	"Validate an existing GSCVD with given root key hash:\n"
88*8617a60dSAndroid Build Coastguard Worker 	"  "MYNAME" gscvd <firmware image> [<root key hash in hex>]\n\n"
89*8617a60dSAndroid Build Coastguard Worker 	"Print the hash of a public root key:\n"
90*8617a60dSAndroid Build Coastguard Worker 	"  "MYNAME" gscvd -r <root key .vpubk file>\n\n"
91*8617a60dSAndroid Build Coastguard Worker 	"Required PARAMS:\n"
92*8617a60dSAndroid Build Coastguard Worker 	"  -b|--board_id  <string|hex>      The Board ID of the board for\n"
93*8617a60dSAndroid Build Coastguard Worker 	"                                     which the image is signed.\n"
94*8617a60dSAndroid Build Coastguard Worker 	"                                     Can be passed as a 4-letter\n"
95*8617a60dSAndroid Build Coastguard Worker 	"                                     string or a hexadecimal number.\n"
96*8617a60dSAndroid Build Coastguard Worker 	"  -r|--root_pub_key  <file>        The main public key, in .vbpubk\n"
97*8617a60dSAndroid Build Coastguard Worker 	"                                     format, used to verify platform\n"
98*8617a60dSAndroid Build Coastguard Worker 	"                                     key\n"
99*8617a60dSAndroid Build Coastguard Worker 	"  -k|--keyblock      <file>        Signed platform public key in\n"
100*8617a60dSAndroid Build Coastguard Worker 	"                                     .keyblock format, used for run\n"
101*8617a60dSAndroid Build Coastguard Worker 	"                                     time RO verifcation\n"
102*8617a60dSAndroid Build Coastguard Worker 	"  -p|--platform_priv <file>        Private platform key in .vbprivk\n"
103*8617a60dSAndroid Build Coastguard Worker 	"                                     format, used for signing RO\n"
104*8617a60dSAndroid Build Coastguard Worker 	"                                     verification data\n"
105*8617a60dSAndroid Build Coastguard Worker 	"Optional PARAMS:\n"
106*8617a60dSAndroid Build Coastguard Worker 	"  -G|--add_gbb                     Add the `GBB` FMAP section to the\n"
107*8617a60dSAndroid Build Coastguard Worker 	"                                     ranges covered by the signature.\n"
108*8617a60dSAndroid Build Coastguard Worker 	"                                     This option takes special care\n"
109*8617a60dSAndroid Build Coastguard Worker 	"                                     to exclude the HWID (and its\n"
110*8617a60dSAndroid Build Coastguard Worker 	"                                     digest) from this range.\n"
111*8617a60dSAndroid Build Coastguard Worker 	"  -R|--ranges        STRING        Comma separated colon delimited\n"
112*8617a60dSAndroid Build Coastguard Worker 	"                                     hex tuples <offset>:<size>, the\n"
113*8617a60dSAndroid Build Coastguard Worker 	"                                     areas of the RO covered by the\n"
114*8617a60dSAndroid Build Coastguard Worker 	"                                     signature, if omitted the\n"
115*8617a60dSAndroid Build Coastguard Worker 	"                                     ranges are expected to be\n"
116*8617a60dSAndroid Build Coastguard Worker 	"                                     present in the GSCVD section\n"
117*8617a60dSAndroid Build Coastguard Worker 	"                                     of the input file\n"
118*8617a60dSAndroid Build Coastguard Worker 	"  [--outfile]        OUTFILE       Output firmware image containing\n"
119*8617a60dSAndroid Build Coastguard Worker 	"                                     RO verification information\n"
120*8617a60dSAndroid Build Coastguard Worker 	"  [--gscvd_out]      GSCVD_FILE    A binary blob containing just the\n"
121*8617a60dSAndroid Build Coastguard Worker 	"                                     unpadded RO_GSCVD section\n"
122*8617a60dSAndroid Build Coastguard Worker 	"  -h|--help                        Print this message\n\n";
123*8617a60dSAndroid Build Coastguard Worker 
124*8617a60dSAndroid Build Coastguard Worker /* Structure helping to keep track of the file mapped into memory. */
125*8617a60dSAndroid Build Coastguard Worker struct file_buf {
126*8617a60dSAndroid Build Coastguard Worker 	uint32_t len;
127*8617a60dSAndroid Build Coastguard Worker 	uint8_t *data;
128*8617a60dSAndroid Build Coastguard Worker 	int fd;
129*8617a60dSAndroid Build Coastguard Worker 	FmapAreaHeader *ro_gscvd;
130*8617a60dSAndroid Build Coastguard Worker 	/* Cached GBB information. */
131*8617a60dSAndroid Build Coastguard Worker 	const FmapAreaHeader *gbb_area;
132*8617a60dSAndroid Build Coastguard Worker 	uint32_t gbb_maxlen;
133*8617a60dSAndroid Build Coastguard Worker };
134*8617a60dSAndroid Build Coastguard Worker 
135*8617a60dSAndroid Build Coastguard Worker /*
136*8617a60dSAndroid Build Coastguard Worker  * Max number of RO ranges to cover. 32 is more than enough, this must be kept
137*8617a60dSAndroid Build Coastguard Worker  * in sync with
138*8617a60dSAndroid Build Coastguard Worker  * - AP_RO_MAX_NUM_RANGES in cr50/common/ap_ro_integrity_check.c
139*8617a60dSAndroid Build Coastguard Worker  * - MAX_RO_RANGES in ti50/common/capsules/src/ap_ro_verification/gscvd.rs
140*8617a60dSAndroid Build Coastguard Worker  */
141*8617a60dSAndroid Build Coastguard Worker #define MAX_RANGES 32
142*8617a60dSAndroid Build Coastguard Worker 
143*8617a60dSAndroid Build Coastguard Worker /*
144*8617a60dSAndroid Build Coastguard Worker  * Container keeping track of the set of ranges to include in hash
145*8617a60dSAndroid Build Coastguard Worker  * calculation.
146*8617a60dSAndroid Build Coastguard Worker  */
147*8617a60dSAndroid Build Coastguard Worker struct gscvd_ro_ranges {
148*8617a60dSAndroid Build Coastguard Worker 	size_t range_count;
149*8617a60dSAndroid Build Coastguard Worker 	struct gscvd_ro_range ranges[MAX_RANGES];
150*8617a60dSAndroid Build Coastguard Worker };
151*8617a60dSAndroid Build Coastguard Worker 
152*8617a60dSAndroid Build Coastguard Worker /**
153*8617a60dSAndroid Build Coastguard Worker  * Load the AP firmware file into memory.
154*8617a60dSAndroid Build Coastguard Worker  *
155*8617a60dSAndroid Build Coastguard Worker  * Map the requested file into memory, find RO_GSCVD area in the file, and
156*8617a60dSAndroid Build Coastguard Worker  * cache the information in the passed in file_buf structure.
157*8617a60dSAndroid Build Coastguard Worker  *
158*8617a60dSAndroid Build Coastguard Worker  * @param file_name  name of the AP firmware file
159*8617a60dSAndroid Build Coastguard Worker  * @param file_buf   pointer to the helper structure keeping information about
160*8617a60dSAndroid Build Coastguard Worker  *                   the file
161*8617a60dSAndroid Build Coastguard Worker  *
162*8617a60dSAndroid Build Coastguard Worker  * @return 0 on success 1 on failure.
163*8617a60dSAndroid Build Coastguard Worker  */
load_ap_firmware(const char * file_name,struct file_buf * file,int mode)164*8617a60dSAndroid Build Coastguard Worker static int load_ap_firmware(const char *file_name, struct file_buf *file,
165*8617a60dSAndroid Build Coastguard Worker 			int mode)
166*8617a60dSAndroid Build Coastguard Worker {
167*8617a60dSAndroid Build Coastguard Worker 	memset(file, 0, sizeof(*file));
168*8617a60dSAndroid Build Coastguard Worker 
169*8617a60dSAndroid Build Coastguard Worker 	if (futil_open_and_map_file(file_name, &file->fd, mode, &file->data,
170*8617a60dSAndroid Build Coastguard Worker 				    &file->len))
171*8617a60dSAndroid Build Coastguard Worker 		return 1;
172*8617a60dSAndroid Build Coastguard Worker 
173*8617a60dSAndroid Build Coastguard Worker 	if (!fmap_find_by_name(file->data, file->len, NULL, "RO_GSCVD",
174*8617a60dSAndroid Build Coastguard Worker 			       &file->ro_gscvd)) {
175*8617a60dSAndroid Build Coastguard Worker 		ERROR("Could not find RO_GSCVD in the FMAP\n");
176*8617a60dSAndroid Build Coastguard Worker 		futil_unmap_and_close_file(file->fd, mode, file->data,
177*8617a60dSAndroid Build Coastguard Worker 					   file->len);
178*8617a60dSAndroid Build Coastguard Worker 		file->fd = -1;
179*8617a60dSAndroid Build Coastguard Worker 		file->data = NULL;
180*8617a60dSAndroid Build Coastguard Worker 		file->len = 0;
181*8617a60dSAndroid Build Coastguard Worker 		return 1;
182*8617a60dSAndroid Build Coastguard Worker 	}
183*8617a60dSAndroid Build Coastguard Worker 
184*8617a60dSAndroid Build Coastguard Worker 	/*
185*8617a60dSAndroid Build Coastguard Worker 	 * Try finding FMAP gbb area and validating the GBB. It's not a
186*8617a60dSAndroid Build Coastguard Worker 	 * failure if GBB is not found, it might not be required after all.
187*8617a60dSAndroid Build Coastguard Worker 	 */
188*8617a60dSAndroid Build Coastguard Worker 	FmapAreaHeader *area;
189*8617a60dSAndroid Build Coastguard Worker 	while (fmap_find_by_name(file->data, file->len, NULL, "GBB", &area)) {
190*8617a60dSAndroid Build Coastguard Worker 		struct vb2_gbb_header *gbb;
191*8617a60dSAndroid Build Coastguard Worker 		uint32_t maxlen;
192*8617a60dSAndroid Build Coastguard Worker 
193*8617a60dSAndroid Build Coastguard Worker 		gbb = (void *)(file->data + area->area_offset);
194*8617a60dSAndroid Build Coastguard Worker 
195*8617a60dSAndroid Build Coastguard Worker 		if (!futil_valid_gbb_header(gbb, area->area_size, &maxlen)) {
196*8617a60dSAndroid Build Coastguard Worker 			ERROR("GBB is invalid.\n");
197*8617a60dSAndroid Build Coastguard Worker 			break;
198*8617a60dSAndroid Build Coastguard Worker 		}
199*8617a60dSAndroid Build Coastguard Worker 
200*8617a60dSAndroid Build Coastguard Worker 		/*
201*8617a60dSAndroid Build Coastguard Worker 		 * This implementation relies on the fact that no meaningful
202*8617a60dSAndroid Build Coastguard Worker 		 * fields come after the `hwid_digest` field in the header. If
203*8617a60dSAndroid Build Coastguard Worker 		 * we ever make new GBB versions that add more fields, the
204*8617a60dSAndroid Build Coastguard Worker 		 * code below and in add_gbb() needs to be adapted. Older
205*8617a60dSAndroid Build Coastguard Worker 		 * versions than 1.2 or GBBs with a bmpblk are not expected
206*8617a60dSAndroid Build Coastguard Worker 		 * with GSCVD images.
207*8617a60dSAndroid Build Coastguard Worker 		 */
208*8617a60dSAndroid Build Coastguard Worker 		if (gbb->major_version != 1 || gbb->minor_version != 2 ||
209*8617a60dSAndroid Build Coastguard Worker 		    gbb->bmpfv_size != 0) {
210*8617a60dSAndroid Build Coastguard Worker 			ERROR("Unsupported GBB version.\n");
211*8617a60dSAndroid Build Coastguard Worker 			break;
212*8617a60dSAndroid Build Coastguard Worker 		}
213*8617a60dSAndroid Build Coastguard Worker 
214*8617a60dSAndroid Build Coastguard Worker 
215*8617a60dSAndroid Build Coastguard Worker 		file->gbb_area = area;
216*8617a60dSAndroid Build Coastguard Worker 		file->gbb_maxlen = maxlen;
217*8617a60dSAndroid Build Coastguard Worker 
218*8617a60dSAndroid Build Coastguard Worker 		break;
219*8617a60dSAndroid Build Coastguard Worker 	}
220*8617a60dSAndroid Build Coastguard Worker 
221*8617a60dSAndroid Build Coastguard Worker 	return 0;
222*8617a60dSAndroid Build Coastguard Worker }
223*8617a60dSAndroid Build Coastguard Worker 
224*8617a60dSAndroid Build Coastguard Worker /**
225*8617a60dSAndroid Build Coastguard Worker  * Check if the passed in offset falls into the passed in FMAP area.
226*8617a60dSAndroid Build Coastguard Worker  */
in_range(uint32_t offset,const FmapAreaHeader * ah)227*8617a60dSAndroid Build Coastguard Worker static bool in_range(uint32_t offset, const FmapAreaHeader *ah)
228*8617a60dSAndroid Build Coastguard Worker {
229*8617a60dSAndroid Build Coastguard Worker 	return (offset >= ah->area_offset) &&
230*8617a60dSAndroid Build Coastguard Worker 	       (offset <= (ah->area_offset + ah->area_size));
231*8617a60dSAndroid Build Coastguard Worker }
232*8617a60dSAndroid Build Coastguard Worker 
233*8617a60dSAndroid Build Coastguard Worker /**
234*8617a60dSAndroid Build Coastguard Worker  * Check if the passed in range fits into the passed in FMAP area.
235*8617a60dSAndroid Build Coastguard Worker  */
range_fits(const struct gscvd_ro_range * range,const FmapAreaHeader * ah)236*8617a60dSAndroid Build Coastguard Worker static bool range_fits(const struct gscvd_ro_range *range,
237*8617a60dSAndroid Build Coastguard Worker 		       const FmapAreaHeader *ah)
238*8617a60dSAndroid Build Coastguard Worker {
239*8617a60dSAndroid Build Coastguard Worker 	if (in_range(range->offset, ah) &&
240*8617a60dSAndroid Build Coastguard Worker 	    in_range(range->offset + range->size, ah))
241*8617a60dSAndroid Build Coastguard Worker 		return true;
242*8617a60dSAndroid Build Coastguard Worker 
243*8617a60dSAndroid Build Coastguard Worker 	return false;
244*8617a60dSAndroid Build Coastguard Worker }
245*8617a60dSAndroid Build Coastguard Worker 
246*8617a60dSAndroid Build Coastguard Worker /**
247*8617a60dSAndroid Build Coastguard Worker  * Check if the passed in range overlaps with the area.
248*8617a60dSAndroid Build Coastguard Worker  *
249*8617a60dSAndroid Build Coastguard Worker  * @param range  pointer to the range to check
250*8617a60dSAndroid Build Coastguard Worker  * @param offset  offset of the area to check against
251*8617a60dSAndroid Build Coastguard Worker  * @param size  size of the area to check against
252*8617a60dSAndroid Build Coastguard Worker  *
253*8617a60dSAndroid Build Coastguard Worker  * @return true if range overlaps with the area, false otherwise.
254*8617a60dSAndroid Build Coastguard Worker  */
range_overlaps(const struct gscvd_ro_range * range,uint32_t offset,size_t size)255*8617a60dSAndroid Build Coastguard Worker static bool range_overlaps(const struct gscvd_ro_range *range, uint32_t offset,
256*8617a60dSAndroid Build Coastguard Worker 			   size_t size)
257*8617a60dSAndroid Build Coastguard Worker {
258*8617a60dSAndroid Build Coastguard Worker 	if (((range->offset + range->size) <= offset) ||
259*8617a60dSAndroid Build Coastguard Worker 	    (offset + size) <= range->offset)
260*8617a60dSAndroid Build Coastguard Worker 		return false;
261*8617a60dSAndroid Build Coastguard Worker 
262*8617a60dSAndroid Build Coastguard Worker 	ERROR("Range %x..+%x overlaps with %x..+%zx\n", range->offset,
263*8617a60dSAndroid Build Coastguard Worker 	      range->size, offset, size);
264*8617a60dSAndroid Build Coastguard Worker 
265*8617a60dSAndroid Build Coastguard Worker 	return true;
266*8617a60dSAndroid Build Coastguard Worker }
267*8617a60dSAndroid Build Coastguard Worker 
268*8617a60dSAndroid Build Coastguard Worker /*
269*8617a60dSAndroid Build Coastguard Worker  * Check validity of the passed in ranges.
270*8617a60dSAndroid Build Coastguard Worker  *
271*8617a60dSAndroid Build Coastguard Worker  * All ranges must
272*8617a60dSAndroid Build Coastguard Worker  * - fit into the WP_RO FMAP area
273*8617a60dSAndroid Build Coastguard Worker  * - not overlap with the RO_GSCVD FMAP area
274*8617a60dSAndroid Build Coastguard Worker  * - not overlap with each other
275*8617a60dSAndroid Build Coastguard Worker  *
276*8617a60dSAndroid Build Coastguard Worker  * @param ranges - pointer to the container of ranges to check
277*8617a60dSAndroid Build Coastguard Worker  * @param file - pointer to the file layout descriptor
278*8617a60dSAndroid Build Coastguard Worker  *
279*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, -1 on failures
280*8617a60dSAndroid Build Coastguard Worker  */
verify_ranges(const struct gscvd_ro_ranges * ranges,const struct file_buf * file)281*8617a60dSAndroid Build Coastguard Worker static int verify_ranges(const struct gscvd_ro_ranges *ranges,
282*8617a60dSAndroid Build Coastguard Worker 			 const struct file_buf *file)
283*8617a60dSAndroid Build Coastguard Worker {
284*8617a60dSAndroid Build Coastguard Worker 	size_t i;
285*8617a60dSAndroid Build Coastguard Worker 	FmapAreaHeader *wp_ro;
286*8617a60dSAndroid Build Coastguard Worker 	FmapAreaHeader *si_all;
287*8617a60dSAndroid Build Coastguard Worker 	int errorcount;
288*8617a60dSAndroid Build Coastguard Worker 
289*8617a60dSAndroid Build Coastguard Worker 	if (!fmap_find_by_name(file->data, file->len, NULL, "WP_RO", &wp_ro)) {
290*8617a60dSAndroid Build Coastguard Worker 		ERROR("Could not find WP_RO in the FMAP\n");
291*8617a60dSAndroid Build Coastguard Worker 		return 1;
292*8617a60dSAndroid Build Coastguard Worker 	}
293*8617a60dSAndroid Build Coastguard Worker 
294*8617a60dSAndroid Build Coastguard Worker 	/* Intel boards can have an SI_ALL region that's not in WP_RO but is
295*8617a60dSAndroid Build Coastguard Worker 	   protected by platform-specific mechanisms, and may still contain
296*8617a60dSAndroid Build Coastguard Worker 	   components that we want to protect from physical attack. */
297*8617a60dSAndroid Build Coastguard Worker 	if (!fmap_find_by_name(file->data, file->len, NULL, "SI_ALL", &si_all))
298*8617a60dSAndroid Build Coastguard Worker 		si_all = NULL;
299*8617a60dSAndroid Build Coastguard Worker 
300*8617a60dSAndroid Build Coastguard Worker 	errorcount = 0;
301*8617a60dSAndroid Build Coastguard Worker 	for (i = 0; i < ranges->range_count; i++) {
302*8617a60dSAndroid Build Coastguard Worker 		size_t j;
303*8617a60dSAndroid Build Coastguard Worker 
304*8617a60dSAndroid Build Coastguard Worker 		/* Must fit into WP_RO or SI_ALL. */
305*8617a60dSAndroid Build Coastguard Worker 		if (!range_fits(ranges->ranges + i, wp_ro) &&
306*8617a60dSAndroid Build Coastguard Worker 		    (!si_all || !range_fits(ranges->ranges + i, si_all))) {
307*8617a60dSAndroid Build Coastguard Worker 			ERROR("Range %#x..+%#x does not fit in WP_RO/SI_ALL\n",
308*8617a60dSAndroid Build Coastguard Worker 				ranges->ranges[i].offset,
309*8617a60dSAndroid Build Coastguard Worker 				ranges->ranges[i].size);
310*8617a60dSAndroid Build Coastguard Worker 			errorcount++;
311*8617a60dSAndroid Build Coastguard Worker 		}
312*8617a60dSAndroid Build Coastguard Worker 
313*8617a60dSAndroid Build Coastguard Worker 		/* Must not overlap with RO_GSCVD. */
314*8617a60dSAndroid Build Coastguard Worker 		if (range_overlaps(ranges->ranges + i,
315*8617a60dSAndroid Build Coastguard Worker 				   file->ro_gscvd->area_offset,
316*8617a60dSAndroid Build Coastguard Worker 				   file->ro_gscvd->area_size))
317*8617a60dSAndroid Build Coastguard Worker 			errorcount++;
318*8617a60dSAndroid Build Coastguard Worker 
319*8617a60dSAndroid Build Coastguard Worker 		/* The last range is nothing to compare against. */
320*8617a60dSAndroid Build Coastguard Worker 		if (i == ranges->range_count - 1)
321*8617a60dSAndroid Build Coastguard Worker 			break;
322*8617a60dSAndroid Build Coastguard Worker 
323*8617a60dSAndroid Build Coastguard Worker 		/* Must not overlap with all following ranges. */
324*8617a60dSAndroid Build Coastguard Worker 		for (j = i + 1; j < ranges->range_count; j++)
325*8617a60dSAndroid Build Coastguard Worker 			if (range_overlaps(ranges->ranges + i,
326*8617a60dSAndroid Build Coastguard Worker 					   ranges->ranges[j].offset,
327*8617a60dSAndroid Build Coastguard Worker 					   ranges->ranges[j].size))
328*8617a60dSAndroid Build Coastguard Worker 				errorcount++;
329*8617a60dSAndroid Build Coastguard Worker 	}
330*8617a60dSAndroid Build Coastguard Worker 
331*8617a60dSAndroid Build Coastguard Worker 	return errorcount ? -1 : 0;
332*8617a60dSAndroid Build Coastguard Worker }
333*8617a60dSAndroid Build Coastguard Worker 
334*8617a60dSAndroid Build Coastguard Worker /**
335*8617a60dSAndroid Build Coastguard Worker  * Parse range specification supplied by the user.
336*8617a60dSAndroid Build Coastguard Worker  *
337*8617a60dSAndroid Build Coastguard Worker  * The input is a string of the following format:
338*8617a60dSAndroid Build Coastguard Worker  * <hex base>:<hex size>[,<hex base>:<hex size>[,...]]
339*8617a60dSAndroid Build Coastguard Worker  *
340*8617a60dSAndroid Build Coastguard Worker  * @param input  user input, part of the command line
341*8617a60dSAndroid Build Coastguard Worker  * @param output  pointer to the ranges container
342*8617a60dSAndroid Build Coastguard Worker  *
343*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, -1 on failure
344*8617a60dSAndroid Build Coastguard Worker  */
parse_ranges(const char * input,struct gscvd_ro_ranges * output)345*8617a60dSAndroid Build Coastguard Worker static int parse_ranges(const char *input, struct gscvd_ro_ranges *output)
346*8617a60dSAndroid Build Coastguard Worker {
347*8617a60dSAndroid Build Coastguard Worker 	char *cursor;
348*8617a60dSAndroid Build Coastguard Worker 	char *delim;
349*8617a60dSAndroid Build Coastguard Worker 	char *str = strdup(input);
350*8617a60dSAndroid Build Coastguard Worker 	int rv = 0;
351*8617a60dSAndroid Build Coastguard Worker 
352*8617a60dSAndroid Build Coastguard Worker 	if (!str) {
353*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to allocate memory for ranges string copy!\n");
354*8617a60dSAndroid Build Coastguard Worker 		return -1;
355*8617a60dSAndroid Build Coastguard Worker 	}
356*8617a60dSAndroid Build Coastguard Worker 
357*8617a60dSAndroid Build Coastguard Worker 	cursor = str;
358*8617a60dSAndroid Build Coastguard Worker 	do {
359*8617a60dSAndroid Build Coastguard Worker 		char *colon;
360*8617a60dSAndroid Build Coastguard Worker 		char *e;
361*8617a60dSAndroid Build Coastguard Worker 
362*8617a60dSAndroid Build Coastguard Worker 		if (output->range_count >= ARRAY_SIZE(output->ranges)) {
363*8617a60dSAndroid Build Coastguard Worker 			ERROR("Too many ranges!\n");
364*8617a60dSAndroid Build Coastguard Worker 			rv = -1;
365*8617a60dSAndroid Build Coastguard Worker 			break;
366*8617a60dSAndroid Build Coastguard Worker 		}
367*8617a60dSAndroid Build Coastguard Worker 
368*8617a60dSAndroid Build Coastguard Worker 		delim = strchr(cursor, ',');
369*8617a60dSAndroid Build Coastguard Worker 		if (delim)
370*8617a60dSAndroid Build Coastguard Worker 			*delim = '\0';
371*8617a60dSAndroid Build Coastguard Worker 		colon = strchr(cursor, ':');
372*8617a60dSAndroid Build Coastguard Worker 		if (!colon) {
373*8617a60dSAndroid Build Coastguard Worker 			rv = -1;
374*8617a60dSAndroid Build Coastguard Worker 			break;
375*8617a60dSAndroid Build Coastguard Worker 		}
376*8617a60dSAndroid Build Coastguard Worker 		*colon = '\0';
377*8617a60dSAndroid Build Coastguard Worker 
378*8617a60dSAndroid Build Coastguard Worker 		errno = 0;
379*8617a60dSAndroid Build Coastguard Worker 		output->ranges[output->range_count].offset =
380*8617a60dSAndroid Build Coastguard Worker 			strtol(cursor, &e, 16);
381*8617a60dSAndroid Build Coastguard Worker 		if (errno || *e) {
382*8617a60dSAndroid Build Coastguard Worker 			rv = -1;
383*8617a60dSAndroid Build Coastguard Worker 			break;
384*8617a60dSAndroid Build Coastguard Worker 		}
385*8617a60dSAndroid Build Coastguard Worker 
386*8617a60dSAndroid Build Coastguard Worker 		output->ranges[output->range_count].size =
387*8617a60dSAndroid Build Coastguard Worker 			strtol(colon + 1, &e, 16);
388*8617a60dSAndroid Build Coastguard Worker 		if (errno || *e) {
389*8617a60dSAndroid Build Coastguard Worker 			rv = -1;
390*8617a60dSAndroid Build Coastguard Worker 			break;
391*8617a60dSAndroid Build Coastguard Worker 		}
392*8617a60dSAndroid Build Coastguard Worker 
393*8617a60dSAndroid Build Coastguard Worker 		output->range_count++;
394*8617a60dSAndroid Build Coastguard Worker 		cursor = delim + 1;
395*8617a60dSAndroid Build Coastguard Worker 		/* Iterate until there is no more commas. */
396*8617a60dSAndroid Build Coastguard Worker 	} while (delim);
397*8617a60dSAndroid Build Coastguard Worker 
398*8617a60dSAndroid Build Coastguard Worker 	free(str);
399*8617a60dSAndroid Build Coastguard Worker 	if (rv)
400*8617a60dSAndroid Build Coastguard Worker 		ERROR("Misformatted ranges string\n");
401*8617a60dSAndroid Build Coastguard Worker 
402*8617a60dSAndroid Build Coastguard Worker 	return rv;
403*8617a60dSAndroid Build Coastguard Worker }
404*8617a60dSAndroid Build Coastguard Worker 
405*8617a60dSAndroid Build Coastguard Worker /**
406*8617a60dSAndroid Build Coastguard Worker  * Add GBB to ranges.
407*8617a60dSAndroid Build Coastguard Worker  *
408*8617a60dSAndroid Build Coastguard Worker  * Splits the `GBB` FMAP section into separate ranges to exclude the HWID string
409*8617a60dSAndroid Build Coastguard Worker  * and the `hwid_digest` field in the header. Will also exclude the empty area
410*8617a60dSAndroid Build Coastguard Worker  * behind the end of the actual GBB data.
411*8617a60dSAndroid Build Coastguard Worker  *
412*8617a60dSAndroid Build Coastguard Worker  * @param ranges pointer to the ranges container
413*8617a60dSAndroid Build Coastguard Worker  * @param file   pointer to the AP firmware file layout descriptor
414*8617a60dSAndroid Build Coastguard Worker  */
add_gbb(struct gscvd_ro_ranges * ranges,const struct file_buf * file)415*8617a60dSAndroid Build Coastguard Worker static int add_gbb(struct gscvd_ro_ranges *ranges, const struct file_buf *file)
416*8617a60dSAndroid Build Coastguard Worker {
417*8617a60dSAndroid Build Coastguard Worker 	if (!file->gbb_area) {
418*8617a60dSAndroid Build Coastguard Worker 		ERROR("Could not find a GBB area in the FMAP.\n");
419*8617a60dSAndroid Build Coastguard Worker 		return 1;
420*8617a60dSAndroid Build Coastguard Worker 	}
421*8617a60dSAndroid Build Coastguard Worker 
422*8617a60dSAndroid Build Coastguard Worker 	const struct vb2_gbb_header *gbb = (void *)(file->data +
423*8617a60dSAndroid Build Coastguard Worker 					      file->gbb_area->area_offset);
424*8617a60dSAndroid Build Coastguard Worker 	uint32_t lower_key_offset = VB2_MIN(gbb->rootkey_offset,
425*8617a60dSAndroid Build Coastguard Worker 					    gbb->recovery_key_offset);
426*8617a60dSAndroid Build Coastguard Worker 	if (gbb->hwid_offset > lower_key_offset) {
427*8617a60dSAndroid Build Coastguard Worker 		ERROR("Weird GBB layout (HWID should come first)\n");
428*8617a60dSAndroid Build Coastguard Worker 		return 1;
429*8617a60dSAndroid Build Coastguard Worker 	}
430*8617a60dSAndroid Build Coastguard Worker 
431*8617a60dSAndroid Build Coastguard Worker 	if (ranges->range_count >= ARRAY_SIZE(ranges->ranges) - 2) {
432*8617a60dSAndroid Build Coastguard Worker 		ERROR("Too many ranges, can't fit GBB!\n");
433*8617a60dSAndroid Build Coastguard Worker 		return 1;
434*8617a60dSAndroid Build Coastguard Worker 	}
435*8617a60dSAndroid Build Coastguard Worker 
436*8617a60dSAndroid Build Coastguard Worker 	ranges->ranges[ranges->range_count].offset =
437*8617a60dSAndroid Build Coastguard Worker 		file->gbb_area->area_offset;
438*8617a60dSAndroid Build Coastguard Worker 	ranges->ranges[ranges->range_count].size =
439*8617a60dSAndroid Build Coastguard Worker 		offsetof(struct vb2_gbb_header, hwid_digest);
440*8617a60dSAndroid Build Coastguard Worker 	ranges->range_count++;
441*8617a60dSAndroid Build Coastguard Worker 
442*8617a60dSAndroid Build Coastguard Worker 	ranges->ranges[ranges->range_count].offset =
443*8617a60dSAndroid Build Coastguard Worker 		file->gbb_area->area_offset + lower_key_offset;
444*8617a60dSAndroid Build Coastguard Worker 	ranges->ranges[ranges->range_count].size =
445*8617a60dSAndroid Build Coastguard Worker 		file->gbb_maxlen - lower_key_offset;
446*8617a60dSAndroid Build Coastguard Worker 	ranges->range_count++;
447*8617a60dSAndroid Build Coastguard Worker 
448*8617a60dSAndroid Build Coastguard Worker 	return 0;
449*8617a60dSAndroid Build Coastguard Worker }
450*8617a60dSAndroid Build Coastguard Worker 
451*8617a60dSAndroid Build Coastguard Worker /**
452*8617a60dSAndroid Build Coastguard Worker  * Extend AP RO hash digest with data from an address range.
453*8617a60dSAndroid Build Coastguard Worker  *
454*8617a60dSAndroid Build Coastguard Worker  * If the flags_offset value is non zero and happens to fall into the passed
455*8617a60dSAndroid Build Coastguard Worker  * in range, do not read values from flash in the flags_offset..+flags_size
456*8617a60dSAndroid Build Coastguard Worker  * range, instead feed zeros to the hashing function.
457*8617a60dSAndroid Build Coastguard Worker  *
458*8617a60dSAndroid Build Coastguard Worker  * NOTE that flags are expected to fully fit into the range, cases of overlap
459*8617a60dSAndroid Build Coastguard Worker  * are not supported.
460*8617a60dSAndroid Build Coastguard Worker  *
461*8617a60dSAndroid Build Coastguard Worker  * @param ap_firmware_file  pointer to the AP firmware file layout descriptor
462*8617a60dSAndroid Build Coastguard Worker  * @param dc  pointer to the hash calculating context
463*8617a60dSAndroid Build Coastguard Worker  * @param offset  offset of the beginning of the range in AP SPI flash
464*8617a60dSAndroid Build Coastguard Worker  * @param size  size of the range
465*8617a60dSAndroid Build Coastguard Worker  * @param flags_offset  if nonzero - offset of the GBB flags field in
466*8617a60dSAndroid Build Coastguard Worker  *			AP SPI flash
467*8617a60dSAndroid Build Coastguard Worker  *
468*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS or digest extension error, if any.
469*8617a60dSAndroid Build Coastguard Worker  */
extend_digest(const struct file_buf * ap_firmware_file,struct vb2_digest_context * dc,uint32_t offset,uint32_t size,uint32_t flags_offset)470*8617a60dSAndroid Build Coastguard Worker static vb2_error_t extend_digest(const struct file_buf *ap_firmware_file,
471*8617a60dSAndroid Build Coastguard Worker 				 struct vb2_digest_context *dc,
472*8617a60dSAndroid Build Coastguard Worker 				 uint32_t offset,
473*8617a60dSAndroid Build Coastguard Worker 				 uint32_t size,
474*8617a60dSAndroid Build Coastguard Worker 				 uint32_t flags_offset)
475*8617a60dSAndroid Build Coastguard Worker {
476*8617a60dSAndroid Build Coastguard Worker 	/* Define it as array to simplify calling vb2_digest_extend() below. */
477*8617a60dSAndroid Build Coastguard Worker 	const uint8_t flags[sizeof(vb2_gbb_flags_t)] = {0};
478*8617a60dSAndroid Build Coastguard Worker 
479*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("%s: %#x..+%#x\n", __func__, offset, size);
480*8617a60dSAndroid Build Coastguard Worker 
481*8617a60dSAndroid Build Coastguard Worker 	if (flags_offset &&
482*8617a60dSAndroid Build Coastguard Worker 	    (flags_offset >= offset) &&
483*8617a60dSAndroid Build Coastguard Worker 	    (flags_offset < (offset + size))) {
484*8617a60dSAndroid Build Coastguard Worker 		uint32_t flags_size;
485*8617a60dSAndroid Build Coastguard Worker 		vb2_error_t rv;
486*8617a60dSAndroid Build Coastguard Worker 
487*8617a60dSAndroid Build Coastguard Worker 		/*
488*8617a60dSAndroid Build Coastguard Worker 		 * This range includes GBB flags, which need to be zeroized.
489*8617a60dSAndroid Build Coastguard Worker 		 *
490*8617a60dSAndroid Build Coastguard Worker 		 * First get the hash of up to the flags.
491*8617a60dSAndroid Build Coastguard Worker 		 */
492*8617a60dSAndroid Build Coastguard Worker 		rv = vb2_digest_extend(dc, ap_firmware_file->data + offset,
493*8617a60dSAndroid Build Coastguard Worker 				       flags_offset - offset);
494*8617a60dSAndroid Build Coastguard Worker 		if (rv != VB2_SUCCESS)
495*8617a60dSAndroid Build Coastguard Worker 			return rv;
496*8617a60dSAndroid Build Coastguard Worker 
497*8617a60dSAndroid Build Coastguard Worker 		size -= flags_offset - offset;
498*8617a60dSAndroid Build Coastguard Worker 		offset = flags_offset;
499*8617a60dSAndroid Build Coastguard Worker 
500*8617a60dSAndroid Build Coastguard Worker 		/* Now hash the flag space, maybe partially. */
501*8617a60dSAndroid Build Coastguard Worker 		flags_size = VB2_MIN(size, sizeof(flags));
502*8617a60dSAndroid Build Coastguard Worker 		rv = vb2_digest_extend(dc, flags, flags_size);
503*8617a60dSAndroid Build Coastguard Worker 		if (rv != VB2_SUCCESS)
504*8617a60dSAndroid Build Coastguard Worker 			return rv;
505*8617a60dSAndroid Build Coastguard Worker 
506*8617a60dSAndroid Build Coastguard Worker 		/* Update size and offset to cover the rest of the range. */
507*8617a60dSAndroid Build Coastguard Worker 		size -= flags_size;
508*8617a60dSAndroid Build Coastguard Worker 
509*8617a60dSAndroid Build Coastguard Worker 		offset += flags_size;
510*8617a60dSAndroid Build Coastguard Worker 	}
511*8617a60dSAndroid Build Coastguard Worker 
512*8617a60dSAndroid Build Coastguard Worker 	return vb2_digest_extend(dc,ap_firmware_file->data + offset, size);
513*8617a60dSAndroid Build Coastguard Worker }
514*8617a60dSAndroid Build Coastguard Worker 
515*8617a60dSAndroid Build Coastguard Worker /**
516*8617a60dSAndroid Build Coastguard Worker  * Calculate hash of the RO ranges.
517*8617a60dSAndroid Build Coastguard Worker  *
518*8617a60dSAndroid Build Coastguard Worker  * @param ap_firmware_file  pointer to the AP firmware file layout descriptor
519*8617a60dSAndroid Build Coastguard Worker  * @param ranges  pointer to the container of ranges to include in hash
520*8617a60dSAndroid Build Coastguard Worker  *		  calculation
521*8617a60dSAndroid Build Coastguard Worker  * @param hash_alg  algorithm to use for hashing
522*8617a60dSAndroid Build Coastguard Worker  * @param digest  memory to copy the calculated hash to
523*8617a60dSAndroid Build Coastguard Worker  * @param digest_ size requested size of the digest, padded with zeros if the
524*8617a60dSAndroid Build Coastguard Worker  *	          SHA digest size is smaller than digest_size
525*8617a60dSAndroid Build Coastguard Worker  * @param override_gbb_flags  if true, replace GBB flags value with zero
526*8617a60dSAndroid Build Coastguard Worker  *
527*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, -1 on failure.
528*8617a60dSAndroid Build Coastguard Worker  */
calculate_ranges_digest(const struct file_buf * ap_firmware_file,const struct gscvd_ro_ranges * ranges,enum vb2_hash_algorithm hash_alg,void * digest,size_t digest_size,bool override_gbb_flags)529*8617a60dSAndroid Build Coastguard Worker static int calculate_ranges_digest(const struct file_buf *ap_firmware_file,
530*8617a60dSAndroid Build Coastguard Worker 				   const struct gscvd_ro_ranges *ranges,
531*8617a60dSAndroid Build Coastguard Worker 				   enum vb2_hash_algorithm hash_alg,
532*8617a60dSAndroid Build Coastguard Worker 				   void *digest, size_t digest_size,
533*8617a60dSAndroid Build Coastguard Worker 				   bool override_gbb_flags)
534*8617a60dSAndroid Build Coastguard Worker {
535*8617a60dSAndroid Build Coastguard Worker 	struct vb2_digest_context dc;
536*8617a60dSAndroid Build Coastguard Worker 	size_t i;
537*8617a60dSAndroid Build Coastguard Worker 	uint32_t flags_offset = 0;
538*8617a60dSAndroid Build Coastguard Worker 
539*8617a60dSAndroid Build Coastguard Worker 	if (override_gbb_flags && ap_firmware_file->gbb_area)
540*8617a60dSAndroid Build Coastguard Worker 		flags_offset = offsetof(struct vb2_gbb_header, flags) +
541*8617a60dSAndroid Build Coastguard Worker 			ap_firmware_file->gbb_area->area_offset;
542*8617a60dSAndroid Build Coastguard Worker 
543*8617a60dSAndroid Build Coastguard Worker 	/* Calculate the ranges digest. */
544*8617a60dSAndroid Build Coastguard Worker 	if (vb2_digest_init(&dc, false, hash_alg, 0) != VB2_SUCCESS) {
545*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to init digest!\n");
546*8617a60dSAndroid Build Coastguard Worker 		return 1;
547*8617a60dSAndroid Build Coastguard Worker 	}
548*8617a60dSAndroid Build Coastguard Worker 
549*8617a60dSAndroid Build Coastguard Worker 	for (i = 0; i < ranges->range_count; i++) {
550*8617a60dSAndroid Build Coastguard Worker 		if (extend_digest(ap_firmware_file, &dc,
551*8617a60dSAndroid Build Coastguard Worker 				  ranges->ranges[i].offset,
552*8617a60dSAndroid Build Coastguard Worker 				  ranges->ranges[i].size,
553*8617a60dSAndroid Build Coastguard Worker 				  flags_offset) != VB2_SUCCESS) {
554*8617a60dSAndroid Build Coastguard Worker 			ERROR("Failed to extend digest!\n");
555*8617a60dSAndroid Build Coastguard Worker 			return -1;
556*8617a60dSAndroid Build Coastguard Worker 		}
557*8617a60dSAndroid Build Coastguard Worker 	}
558*8617a60dSAndroid Build Coastguard Worker 
559*8617a60dSAndroid Build Coastguard Worker 	memset(digest, 0, digest_size);
560*8617a60dSAndroid Build Coastguard Worker 	if (vb2_digest_finalize(&dc, digest, digest_size) != VB2_SUCCESS) {
561*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to finalize digest!\n");
562*8617a60dSAndroid Build Coastguard Worker 		return -1;
563*8617a60dSAndroid Build Coastguard Worker 	}
564*8617a60dSAndroid Build Coastguard Worker 
565*8617a60dSAndroid Build Coastguard Worker 	return 0;
566*8617a60dSAndroid Build Coastguard Worker }
567*8617a60dSAndroid Build Coastguard Worker 
568*8617a60dSAndroid Build Coastguard Worker /**
569*8617a60dSAndroid Build Coastguard Worker  * Build GSC verification data.
570*8617a60dSAndroid Build Coastguard Worker  *
571*8617a60dSAndroid Build Coastguard Worker  * Calculate size of the structure including the signature and the root key,
572*8617a60dSAndroid Build Coastguard Worker  * allocate memory, fill up the structure, calculate AP RO ranges digest and
573*8617a60dSAndroid Build Coastguard Worker  * then the GVD signature.
574*8617a60dSAndroid Build Coastguard Worker  *
575*8617a60dSAndroid Build Coastguard Worker  * @param ap_firmware_file  pointer to the AP firmware file layout descriptor
576*8617a60dSAndroid Build Coastguard Worker  * @param ranges  pointer to the container of ranges to include in verification
577*8617a60dSAndroid Build Coastguard Worker  * @param root_pubk  pointer to the root pubk container
578*8617a60dSAndroid Build Coastguard Worker  * @param privk   pointer to the private key to use for signing
579*8617a60dSAndroid Build Coastguard Worker  * @param board_id  Board ID value to use.
580*8617a60dSAndroid Build Coastguard Worker  *
581*8617a60dSAndroid Build Coastguard Worker  * @return pointer to the created GVD (to be freed by the caller) on success,
582*8617a60dSAndroid Build Coastguard Worker  *         NULL on failure.
583*8617a60dSAndroid Build Coastguard Worker  */
584*8617a60dSAndroid Build Coastguard Worker static
create_gvd(struct file_buf * ap_firmware_file,struct gscvd_ro_ranges * ranges,const struct vb2_packed_key * root_pubk,const struct vb2_private_key * privk,uint32_t board_id)585*8617a60dSAndroid Build Coastguard Worker struct gsc_verification_data *create_gvd(struct file_buf *ap_firmware_file,
586*8617a60dSAndroid Build Coastguard Worker 					 struct gscvd_ro_ranges *ranges,
587*8617a60dSAndroid Build Coastguard Worker 					 const struct vb2_packed_key *root_pubk,
588*8617a60dSAndroid Build Coastguard Worker 					 const struct vb2_private_key *privk,
589*8617a60dSAndroid Build Coastguard Worker 					 uint32_t board_id)
590*8617a60dSAndroid Build Coastguard Worker {
591*8617a60dSAndroid Build Coastguard Worker 	struct gsc_verification_data *gvd;
592*8617a60dSAndroid Build Coastguard Worker 	size_t total_size;
593*8617a60dSAndroid Build Coastguard Worker 	size_t sig_size;
594*8617a60dSAndroid Build Coastguard Worker 	size_t ranges_size;
595*8617a60dSAndroid Build Coastguard Worker 	struct vb2_signature *sig;
596*8617a60dSAndroid Build Coastguard Worker 	const FmapHeader *fmh;
597*8617a60dSAndroid Build Coastguard Worker 
598*8617a60dSAndroid Build Coastguard Worker 	sig_size = vb2_rsa_sig_size(privk->sig_alg);
599*8617a60dSAndroid Build Coastguard Worker 	ranges_size = ranges->range_count * sizeof(struct gscvd_ro_range);
600*8617a60dSAndroid Build Coastguard Worker 	total_size = sizeof(struct gsc_verification_data) +
601*8617a60dSAndroid Build Coastguard Worker 		root_pubk->key_size + sig_size + ranges_size;
602*8617a60dSAndroid Build Coastguard Worker 
603*8617a60dSAndroid Build Coastguard Worker 	gvd = calloc(total_size, 1);
604*8617a60dSAndroid Build Coastguard Worker 
605*8617a60dSAndroid Build Coastguard Worker 	if (!gvd) {
606*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to allocate %zd bytes for gvd\n", total_size);
607*8617a60dSAndroid Build Coastguard Worker 		return NULL;
608*8617a60dSAndroid Build Coastguard Worker 	}
609*8617a60dSAndroid Build Coastguard Worker 
610*8617a60dSAndroid Build Coastguard Worker 	gvd->gv_magic = GSC_VD_MAGIC;
611*8617a60dSAndroid Build Coastguard Worker 	gvd->size = total_size;
612*8617a60dSAndroid Build Coastguard Worker 	gvd->gsc_board_id = board_id;
613*8617a60dSAndroid Build Coastguard Worker 	gvd->rollback_counter = GSC_VD_ROLLBACK_COUNTER;
614*8617a60dSAndroid Build Coastguard Worker 
615*8617a60dSAndroid Build Coastguard Worker 	/* Guaranteed to succeed. */
616*8617a60dSAndroid Build Coastguard Worker 	fmh = fmap_find(ap_firmware_file->data, ap_firmware_file->len);
617*8617a60dSAndroid Build Coastguard Worker 
618*8617a60dSAndroid Build Coastguard Worker 	gvd->fmap_location = (uintptr_t)fmh - (uintptr_t)ap_firmware_file->data;
619*8617a60dSAndroid Build Coastguard Worker 
620*8617a60dSAndroid Build Coastguard Worker 	gvd->hash_alg = VB2_HASH_SHA256;
621*8617a60dSAndroid Build Coastguard Worker 
622*8617a60dSAndroid Build Coastguard Worker 	if (calculate_ranges_digest(ap_firmware_file, ranges, gvd->hash_alg,
623*8617a60dSAndroid Build Coastguard Worker 				    gvd->ranges_digest,
624*8617a60dSAndroid Build Coastguard Worker 				    sizeof(gvd->ranges_digest),
625*8617a60dSAndroid Build Coastguard Worker 				    true)) {
626*8617a60dSAndroid Build Coastguard Worker 		free(gvd);
627*8617a60dSAndroid Build Coastguard Worker 		return NULL;
628*8617a60dSAndroid Build Coastguard Worker 	}
629*8617a60dSAndroid Build Coastguard Worker 
630*8617a60dSAndroid Build Coastguard Worker 	/* Prepare signature header. */
631*8617a60dSAndroid Build Coastguard Worker 	vb2_init_signature(&gvd->sig_header,
632*8617a60dSAndroid Build Coastguard Worker 			   (uint8_t *)(gvd + 1) + ranges_size,
633*8617a60dSAndroid Build Coastguard Worker 			   sig_size,
634*8617a60dSAndroid Build Coastguard Worker 			   sizeof(struct gsc_verification_data) + ranges_size);
635*8617a60dSAndroid Build Coastguard Worker 
636*8617a60dSAndroid Build Coastguard Worker 	/* Copy root key into the structure. */
637*8617a60dSAndroid Build Coastguard Worker 	vb2_init_packed_key(&gvd->root_key_header,
638*8617a60dSAndroid Build Coastguard Worker 			    (uint8_t *)(gvd + 1) + ranges_size + sig_size,
639*8617a60dSAndroid Build Coastguard Worker 			    root_pubk->key_size);
640*8617a60dSAndroid Build Coastguard Worker 	vb2_copy_packed_key(&gvd->root_key_header, root_pubk);
641*8617a60dSAndroid Build Coastguard Worker 
642*8617a60dSAndroid Build Coastguard Worker 	/* Copy ranges into the ranges section. */
643*8617a60dSAndroid Build Coastguard Worker 	gvd->range_count = ranges->range_count;
644*8617a60dSAndroid Build Coastguard Worker 	memcpy(gvd->ranges, ranges->ranges, ranges_size);
645*8617a60dSAndroid Build Coastguard Worker 
646*8617a60dSAndroid Build Coastguard Worker 	sig = vb2_calculate_signature((uint8_t *)gvd,
647*8617a60dSAndroid Build Coastguard Worker 				      sizeof(struct gsc_verification_data) +
648*8617a60dSAndroid Build Coastguard Worker 				      ranges_size, privk);
649*8617a60dSAndroid Build Coastguard Worker 	if (!sig) {
650*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to calculate signature\n");
651*8617a60dSAndroid Build Coastguard Worker 		free(gvd);
652*8617a60dSAndroid Build Coastguard Worker 		return NULL;
653*8617a60dSAndroid Build Coastguard Worker 	}
654*8617a60dSAndroid Build Coastguard Worker 
655*8617a60dSAndroid Build Coastguard Worker 	/* Copy signature body into GVD after some basic checks. */
656*8617a60dSAndroid Build Coastguard Worker 	if ((sig_size == sig->sig_size) &&
657*8617a60dSAndroid Build Coastguard Worker 	    (gvd->sig_header.data_size == sig->data_size)) {
658*8617a60dSAndroid Build Coastguard Worker 		vb2_copy_signature(&gvd->sig_header, sig);
659*8617a60dSAndroid Build Coastguard Worker 	} else {
660*8617a60dSAndroid Build Coastguard Worker 		ERROR("Inconsistent signature headers\n");
661*8617a60dSAndroid Build Coastguard Worker 		free(sig);
662*8617a60dSAndroid Build Coastguard Worker 		free(gvd);
663*8617a60dSAndroid Build Coastguard Worker 		return NULL;
664*8617a60dSAndroid Build Coastguard Worker 	}
665*8617a60dSAndroid Build Coastguard Worker 
666*8617a60dSAndroid Build Coastguard Worker 	free(sig);
667*8617a60dSAndroid Build Coastguard Worker 
668*8617a60dSAndroid Build Coastguard Worker 	return gvd;
669*8617a60dSAndroid Build Coastguard Worker }
670*8617a60dSAndroid Build Coastguard Worker 
671*8617a60dSAndroid Build Coastguard Worker /**
672*8617a60dSAndroid Build Coastguard Worker  * Fill RO_GSCVD FMAP area.
673*8617a60dSAndroid Build Coastguard Worker  *
674*8617a60dSAndroid Build Coastguard Worker  * All trust chain components have been verified, AP RO sections digest
675*8617a60dSAndroid Build Coastguard Worker  * calculated, and GVD signature created; put it all together in the dedicated
676*8617a60dSAndroid Build Coastguard Worker  * FMAP area and save in a binary blob if requested.
677*8617a60dSAndroid Build Coastguard Worker  *
678*8617a60dSAndroid Build Coastguard Worker  * @param ap_firmware_file  pointer to the AP firmware file layout descriptor
679*8617a60dSAndroid Build Coastguard Worker  * @param gvd  pointer to the GVD header
680*8617a60dSAndroid Build Coastguard Worker  * @param keyblock  pointer to the keyblock container
681*8617a60dSAndroid Build Coastguard Worker  * @param gscvd_file_name  if not NULL the name of the file to save the
682*8617a60dSAndroid Build Coastguard Worker  *			RO_GSCVD section in.
683*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, -1 on failure
684*8617a60dSAndroid Build Coastguard Worker  */
fill_gvd_area(struct file_buf * ap_firmware_file,struct gsc_verification_data * gvd,struct vb2_keyblock * keyblock,const char * gscvd_file_name)685*8617a60dSAndroid Build Coastguard Worker static int fill_gvd_area(struct file_buf *ap_firmware_file,
686*8617a60dSAndroid Build Coastguard Worker 			 struct gsc_verification_data *gvd,
687*8617a60dSAndroid Build Coastguard Worker 			 struct vb2_keyblock *keyblock,
688*8617a60dSAndroid Build Coastguard Worker 			 const char *gscvd_file_name)
689*8617a60dSAndroid Build Coastguard Worker {
690*8617a60dSAndroid Build Coastguard Worker 	size_t total;
691*8617a60dSAndroid Build Coastguard Worker 	uint8_t *cursor;
692*8617a60dSAndroid Build Coastguard Worker 
693*8617a60dSAndroid Build Coastguard Worker 	/* How much room is needed for the whole thing? */
694*8617a60dSAndroid Build Coastguard Worker 	total = gvd->size + keyblock->keyblock_size;
695*8617a60dSAndroid Build Coastguard Worker 
696*8617a60dSAndroid Build Coastguard Worker 	if (total > ap_firmware_file->ro_gscvd->area_size) {
697*8617a60dSAndroid Build Coastguard Worker 		ERROR("GVD section does not fit, %zd > %d\n",
698*8617a60dSAndroid Build Coastguard Worker 		      total, ap_firmware_file->ro_gscvd->area_size);
699*8617a60dSAndroid Build Coastguard Worker 		return -1;
700*8617a60dSAndroid Build Coastguard Worker 	}
701*8617a60dSAndroid Build Coastguard Worker 
702*8617a60dSAndroid Build Coastguard Worker 	cursor = ap_firmware_file->data +
703*8617a60dSAndroid Build Coastguard Worker 		 ap_firmware_file->ro_gscvd->area_offset;
704*8617a60dSAndroid Build Coastguard Worker 
705*8617a60dSAndroid Build Coastguard Worker 	/* Copy GSC verification data */
706*8617a60dSAndroid Build Coastguard Worker 	memcpy(cursor, gvd, gvd->size);
707*8617a60dSAndroid Build Coastguard Worker 	cursor += gvd->size;
708*8617a60dSAndroid Build Coastguard Worker 
709*8617a60dSAndroid Build Coastguard Worker 	/* Keyblock, size includes everything. */
710*8617a60dSAndroid Build Coastguard Worker 	memcpy(cursor, keyblock, keyblock->keyblock_size);
711*8617a60dSAndroid Build Coastguard Worker 
712*8617a60dSAndroid Build Coastguard Worker 	if (gscvd_file_name) {
713*8617a60dSAndroid Build Coastguard Worker 		if (vb2_write_file(gscvd_file_name, cursor - gvd->size,
714*8617a60dSAndroid Build Coastguard Worker 				   total) != VB2_SUCCESS)
715*8617a60dSAndroid Build Coastguard Worker 			return -1;
716*8617a60dSAndroid Build Coastguard Worker 	}
717*8617a60dSAndroid Build Coastguard Worker 	return 0;
718*8617a60dSAndroid Build Coastguard Worker }
719*8617a60dSAndroid Build Coastguard Worker 
720*8617a60dSAndroid Build Coastguard Worker /**
721*8617a60dSAndroid Build Coastguard Worker  * Initialize a work buffer structure.
722*8617a60dSAndroid Build Coastguard Worker  *
723*8617a60dSAndroid Build Coastguard Worker  * Embedded vboot reference code does not use malloc/free, it uses the so
724*8617a60dSAndroid Build Coastguard Worker  * called work buffer structure to provide a poor man's memory management
725*8617a60dSAndroid Build Coastguard Worker  * tool. This program uses some of the embedded library functions, let's
726*8617a60dSAndroid Build Coastguard Worker  * implement work buffer support to keep the embedded code happy.
727*8617a60dSAndroid Build Coastguard Worker  *
728*8617a60dSAndroid Build Coastguard Worker  * @param wb  pointer to the workubffer structure to initialize
729*8617a60dSAndroid Build Coastguard Worker  * @param size  size of the buffer to allocate
730*8617a60dSAndroid Build Coastguard Worker  *
731*8617a60dSAndroid Build Coastguard Worker  * @return pointer to the allocated buffer on success, NULL on failure.
732*8617a60dSAndroid Build Coastguard Worker  */
init_wb(struct vb2_workbuf * wb,size_t size)733*8617a60dSAndroid Build Coastguard Worker static void *init_wb(struct vb2_workbuf *wb, size_t size)
734*8617a60dSAndroid Build Coastguard Worker {
735*8617a60dSAndroid Build Coastguard Worker 	void *buf = malloc(size);
736*8617a60dSAndroid Build Coastguard Worker 
737*8617a60dSAndroid Build Coastguard Worker 	if (!buf)
738*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to allocate workblock of %zd\n", size);
739*8617a60dSAndroid Build Coastguard Worker 	else
740*8617a60dSAndroid Build Coastguard Worker 		vb2_workbuf_init(wb, buf, size);
741*8617a60dSAndroid Build Coastguard Worker 
742*8617a60dSAndroid Build Coastguard Worker 	return buf;
743*8617a60dSAndroid Build Coastguard Worker }
744*8617a60dSAndroid Build Coastguard Worker 
745*8617a60dSAndroid Build Coastguard Worker /**
746*8617a60dSAndroid Build Coastguard Worker  * Validate that platform key keyblock was signed by the root key.
747*8617a60dSAndroid Build Coastguard Worker  *
748*8617a60dSAndroid Build Coastguard Worker  * This function performs the same step the GSC is supposed to perform:
749*8617a60dSAndroid Build Coastguard Worker  * validate the platform key keyblock signature using the root public key.
750*8617a60dSAndroid Build Coastguard Worker  *
751*8617a60dSAndroid Build Coastguard Worker  * @param root_pubk  pointer to the root public key container
752*8617a60dSAndroid Build Coastguard Worker  * @param kblock  pointer to the platform public key keyblock
753*8617a60dSAndroid Build Coastguard Worker  *
754*8617a60dSAndroid Build Coastguard Worker  * @return 0 on success, -1 on failure
755*8617a60dSAndroid Build Coastguard Worker  */
validate_pubk_signature(const struct vb2_packed_key * root_pubk,struct vb2_keyblock * kblock)756*8617a60dSAndroid Build Coastguard Worker static int validate_pubk_signature(const struct vb2_packed_key *root_pubk,
757*8617a60dSAndroid Build Coastguard Worker 				   struct vb2_keyblock *kblock)
758*8617a60dSAndroid Build Coastguard Worker {
759*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key pubk;
760*8617a60dSAndroid Build Coastguard Worker 	struct vb2_workbuf wb;
761*8617a60dSAndroid Build Coastguard Worker 	uint32_t kbsize;
762*8617a60dSAndroid Build Coastguard Worker 	int rv;
763*8617a60dSAndroid Build Coastguard Worker 	void *buf;
764*8617a60dSAndroid Build Coastguard Worker 
765*8617a60dSAndroid Build Coastguard Worker 	if (vb2_unpack_key(&pubk, root_pubk) != VB2_SUCCESS) {
766*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to unpack public key\n");
767*8617a60dSAndroid Build Coastguard Worker 		return -1;
768*8617a60dSAndroid Build Coastguard Worker 	}
769*8617a60dSAndroid Build Coastguard Worker 
770*8617a60dSAndroid Build Coastguard Worker 	/* Let's create an ample sized work buffer. */
771*8617a60dSAndroid Build Coastguard Worker 	buf = init_wb(&wb, 8192);
772*8617a60dSAndroid Build Coastguard Worker 	if (!buf)
773*8617a60dSAndroid Build Coastguard Worker 		return -1;
774*8617a60dSAndroid Build Coastguard Worker 
775*8617a60dSAndroid Build Coastguard Worker 	rv = -1;
776*8617a60dSAndroid Build Coastguard Worker 	do {
777*8617a60dSAndroid Build Coastguard Worker 		void *work;
778*8617a60dSAndroid Build Coastguard Worker 
779*8617a60dSAndroid Build Coastguard Worker 		kbsize = kblock->keyblock_size;
780*8617a60dSAndroid Build Coastguard Worker 		work = vb2_workbuf_alloc(&wb, kbsize);
781*8617a60dSAndroid Build Coastguard Worker 		if (!work) {
782*8617a60dSAndroid Build Coastguard Worker 			ERROR("Failed to allocate workblock space %d\n",
783*8617a60dSAndroid Build Coastguard Worker 			      kbsize);
784*8617a60dSAndroid Build Coastguard Worker 			break;
785*8617a60dSAndroid Build Coastguard Worker 		}
786*8617a60dSAndroid Build Coastguard Worker 
787*8617a60dSAndroid Build Coastguard Worker 		memcpy(work, kblock, kbsize);
788*8617a60dSAndroid Build Coastguard Worker 
789*8617a60dSAndroid Build Coastguard Worker 		if (vb2_verify_keyblock(work, kbsize, &pubk, &wb) !=
790*8617a60dSAndroid Build Coastguard Worker 		    VB2_SUCCESS) {
791*8617a60dSAndroid Build Coastguard Worker 			ERROR("Root and keyblock mismatch\n");
792*8617a60dSAndroid Build Coastguard Worker 			break;
793*8617a60dSAndroid Build Coastguard Worker 		}
794*8617a60dSAndroid Build Coastguard Worker 
795*8617a60dSAndroid Build Coastguard Worker 		rv = 0;
796*8617a60dSAndroid Build Coastguard Worker 	} while (false);
797*8617a60dSAndroid Build Coastguard Worker 
798*8617a60dSAndroid Build Coastguard Worker 	free(buf);
799*8617a60dSAndroid Build Coastguard Worker 
800*8617a60dSAndroid Build Coastguard Worker 	return rv;
801*8617a60dSAndroid Build Coastguard Worker }
802*8617a60dSAndroid Build Coastguard Worker 
803*8617a60dSAndroid Build Coastguard Worker /**
804*8617a60dSAndroid Build Coastguard Worker  * Validate that private and public parts of the platform key match.
805*8617a60dSAndroid Build Coastguard Worker  *
806*8617a60dSAndroid Build Coastguard Worker  * This is a fairly routine validation, the N components of the private and
807*8617a60dSAndroid Build Coastguard Worker  * public RSA keys are compared.
808*8617a60dSAndroid Build Coastguard Worker  *
809*8617a60dSAndroid Build Coastguard Worker  * @param keyblock  pointer to the keyblock containing the public key
810*8617a60dSAndroid Build Coastguard Worker  * @param plat_privk  pointer to the matching private key
811*8617a60dSAndroid Build Coastguard Worker  *
812*8617a60dSAndroid Build Coastguard Worker  * @return 0 on success, nonzero on failure
813*8617a60dSAndroid Build Coastguard Worker  */
validate_privk(struct vb2_keyblock * kblock,struct vb2_private_key * plat_privk)814*8617a60dSAndroid Build Coastguard Worker static int validate_privk(struct vb2_keyblock *kblock,
815*8617a60dSAndroid Build Coastguard Worker 			  struct vb2_private_key *plat_privk)
816*8617a60dSAndroid Build Coastguard Worker {
817*8617a60dSAndroid Build Coastguard Worker 	BIGNUM *privn;
818*8617a60dSAndroid Build Coastguard Worker 	BIGNUM *pubn;
819*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key pubk;
820*8617a60dSAndroid Build Coastguard Worker 	int rv = -1; // Speculatively set to error return value.
821*8617a60dSAndroid Build Coastguard Worker 
822*8617a60dSAndroid Build Coastguard Worker 	privn = pubn = NULL;
823*8617a60dSAndroid Build Coastguard Worker 
824*8617a60dSAndroid Build Coastguard Worker 	if (plat_privk->key_location != PRIVATE_KEY_P11) {
825*8617a60dSAndroid Build Coastguard Worker 		RSA_get0_key(plat_privk->rsa_private_key, (const BIGNUM **)&privn,
826*8617a60dSAndroid Build Coastguard Worker 			     NULL, NULL);
827*8617a60dSAndroid Build Coastguard Worker 	} else {
828*8617a60dSAndroid Build Coastguard Worker 		uint32_t size;
829*8617a60dSAndroid Build Coastguard Worker 		uint8_t *bytes;
830*8617a60dSAndroid Build Coastguard Worker 
831*8617a60dSAndroid Build Coastguard Worker 		bytes = pkcs11_get_modulus(plat_privk->p11_key, &size);
832*8617a60dSAndroid Build Coastguard Worker 		if (bytes == NULL) {
833*8617a60dSAndroid Build Coastguard Worker 			ERROR("Failed to retrieve private key modulus\n");
834*8617a60dSAndroid Build Coastguard Worker 			return rv;
835*8617a60dSAndroid Build Coastguard Worker 		}
836*8617a60dSAndroid Build Coastguard Worker 
837*8617a60dSAndroid Build Coastguard Worker 		privn = BN_bin2bn(bytes, size, NULL);
838*8617a60dSAndroid Build Coastguard Worker 		free(bytes);
839*8617a60dSAndroid Build Coastguard Worker 
840*8617a60dSAndroid Build Coastguard Worker 		if (!privn) {
841*8617a60dSAndroid Build Coastguard Worker 			ERROR("Failed to allocate BN for priv key modulus\n");
842*8617a60dSAndroid Build Coastguard Worker 			return rv;
843*8617a60dSAndroid Build Coastguard Worker 		}
844*8617a60dSAndroid Build Coastguard Worker 	}
845*8617a60dSAndroid Build Coastguard Worker 
846*8617a60dSAndroid Build Coastguard Worker 	if (vb2_unpack_key(&pubk, &kblock->data_key) != VB2_SUCCESS) {
847*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to unpack public key\n");
848*8617a60dSAndroid Build Coastguard Worker 		return rv;
849*8617a60dSAndroid Build Coastguard Worker 	}
850*8617a60dSAndroid Build Coastguard Worker 
851*8617a60dSAndroid Build Coastguard Worker 	pubn = BN_lebin2bn((uint8_t *)pubk.n, vb2_rsa_sig_size(pubk.sig_alg),
852*8617a60dSAndroid Build Coastguard Worker 			   NULL);
853*8617a60dSAndroid Build Coastguard Worker 	if (pubn) {
854*8617a60dSAndroid Build Coastguard Worker 		rv = BN_cmp(pubn, privn);
855*8617a60dSAndroid Build Coastguard Worker 		BN_free(pubn);
856*8617a60dSAndroid Build Coastguard Worker 		if (rv)
857*8617a60dSAndroid Build Coastguard Worker 			ERROR("Public/private key N mismatch!\n");
858*8617a60dSAndroid Build Coastguard Worker 	} else {
859*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to allocate BN for pub key modulus\n");
860*8617a60dSAndroid Build Coastguard Worker 	}
861*8617a60dSAndroid Build Coastguard Worker 
862*8617a60dSAndroid Build Coastguard Worker 	if (plat_privk->key_location == PRIVATE_KEY_P11)
863*8617a60dSAndroid Build Coastguard Worker 		BN_free(privn);
864*8617a60dSAndroid Build Coastguard Worker 
865*8617a60dSAndroid Build Coastguard Worker 	return rv;
866*8617a60dSAndroid Build Coastguard Worker }
867*8617a60dSAndroid Build Coastguard Worker 
868*8617a60dSAndroid Build Coastguard Worker /**
869*8617a60dSAndroid Build Coastguard Worker  * Copy ranges from AP firmware file into gscvd_ro_ranges container
870*8617a60dSAndroid Build Coastguard Worker  *
871*8617a60dSAndroid Build Coastguard Worker  * While copying the ranges verify that they do not overlap.
872*8617a60dSAndroid Build Coastguard Worker  *
873*8617a60dSAndroid Build Coastguard Worker  * @param ap_firmware_file  pointer to the AP firmware file layout descriptor
874*8617a60dSAndroid Build Coastguard Worker  * @param gvd  pointer to the GVD header followed by the ranges
875*8617a60dSAndroid Build Coastguard Worker  * @param ranges  pointer to the ranges container to copy ranges to
876*8617a60dSAndroid Build Coastguard Worker  *
877*8617a60dSAndroid Build Coastguard Worker  * @return 0 on successful copy nonzero on errors.
878*8617a60dSAndroid Build Coastguard Worker  */
copy_ranges(const struct file_buf * ap_firmware_file,const struct gsc_verification_data * gvd,struct gscvd_ro_ranges * ranges)879*8617a60dSAndroid Build Coastguard Worker static int copy_ranges(const struct file_buf *ap_firmware_file,
880*8617a60dSAndroid Build Coastguard Worker 		       const struct gsc_verification_data *gvd,
881*8617a60dSAndroid Build Coastguard Worker 		       struct gscvd_ro_ranges *ranges)
882*8617a60dSAndroid Build Coastguard Worker {
883*8617a60dSAndroid Build Coastguard Worker 	ranges->range_count = gvd->range_count;
884*8617a60dSAndroid Build Coastguard Worker 	memcpy(ranges->ranges, gvd->ranges,
885*8617a60dSAndroid Build Coastguard Worker 	       sizeof(ranges->ranges[0]) * ranges->range_count);
886*8617a60dSAndroid Build Coastguard Worker 
887*8617a60dSAndroid Build Coastguard Worker 	return verify_ranges(ranges, ap_firmware_file);
888*8617a60dSAndroid Build Coastguard Worker }
889*8617a60dSAndroid Build Coastguard Worker 
890*8617a60dSAndroid Build Coastguard Worker /**
891*8617a60dSAndroid Build Coastguard Worker  * Basic validation of GVD included in a AP firmware file.
892*8617a60dSAndroid Build Coastguard Worker  *
893*8617a60dSAndroid Build Coastguard Worker  * This is not a cryptographic verification, just a check that the structure
894*8617a60dSAndroid Build Coastguard Worker  * makes sense and the expected values are found in certain fields.
895*8617a60dSAndroid Build Coastguard Worker  *
896*8617a60dSAndroid Build Coastguard Worker  * @param gvd  pointer to the GVD header followed by the ranges
897*8617a60dSAndroid Build Coastguard Worker  * @param ap_firmware_file  pointer to the AP firmware file layout descriptor
898*8617a60dSAndroid Build Coastguard Worker  *
899*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, -1 on failure.
900*8617a60dSAndroid Build Coastguard Worker  */
validate_gvd(const struct gsc_verification_data * gvd,const struct file_buf * ap_firmware_file)901*8617a60dSAndroid Build Coastguard Worker static int validate_gvd(const struct gsc_verification_data *gvd,
902*8617a60dSAndroid Build Coastguard Worker 			const struct file_buf *ap_firmware_file)
903*8617a60dSAndroid Build Coastguard Worker {
904*8617a60dSAndroid Build Coastguard Worker 	const FmapHeader *fmh;
905*8617a60dSAndroid Build Coastguard Worker 
906*8617a60dSAndroid Build Coastguard Worker 	if (gvd->gv_magic != GSC_VD_MAGIC) {
907*8617a60dSAndroid Build Coastguard Worker 		ERROR("Incorrect gscvd magic %x\n", gvd->gv_magic);
908*8617a60dSAndroid Build Coastguard Worker 		return -1;
909*8617a60dSAndroid Build Coastguard Worker 	}
910*8617a60dSAndroid Build Coastguard Worker 
911*8617a60dSAndroid Build Coastguard Worker 	if (!gvd->range_count || (gvd->range_count > MAX_RANGES)) {
912*8617a60dSAndroid Build Coastguard Worker 		ERROR("Incorrect gscvd range count %d\n", gvd->range_count);
913*8617a60dSAndroid Build Coastguard Worker 		return -1;
914*8617a60dSAndroid Build Coastguard Worker 	}
915*8617a60dSAndroid Build Coastguard Worker 
916*8617a60dSAndroid Build Coastguard Worker 	/* Guaranteed to succeed. */
917*8617a60dSAndroid Build Coastguard Worker 	fmh = fmap_find(ap_firmware_file->data, ap_firmware_file->len);
918*8617a60dSAndroid Build Coastguard Worker 
919*8617a60dSAndroid Build Coastguard Worker 	if (gvd->fmap_location !=
920*8617a60dSAndroid Build Coastguard Worker 	    ((uintptr_t)fmh - (uintptr_t)ap_firmware_file->data)) {
921*8617a60dSAndroid Build Coastguard Worker 		ERROR("Incorrect gscvd fmap offset %x\n", gvd->fmap_location);
922*8617a60dSAndroid Build Coastguard Worker 		return -1;
923*8617a60dSAndroid Build Coastguard Worker 	}
924*8617a60dSAndroid Build Coastguard Worker 
925*8617a60dSAndroid Build Coastguard Worker 	/* Make sure signature and root key fit. */
926*8617a60dSAndroid Build Coastguard Worker 	if (vb2_verify_signature_inside(gvd, gvd->size, &gvd->sig_header) !=
927*8617a60dSAndroid Build Coastguard Worker 	    VB2_SUCCESS) {
928*8617a60dSAndroid Build Coastguard Worker 		ERROR("Corrupted signature header in GVD\n");
929*8617a60dSAndroid Build Coastguard Worker 		return -1;
930*8617a60dSAndroid Build Coastguard Worker 	}
931*8617a60dSAndroid Build Coastguard Worker 
932*8617a60dSAndroid Build Coastguard Worker 	if (vb2_verify_packed_key_inside(gvd, gvd->size,
933*8617a60dSAndroid Build Coastguard Worker 					 &gvd->root_key_header) !=
934*8617a60dSAndroid Build Coastguard Worker 	    VB2_SUCCESS) {
935*8617a60dSAndroid Build Coastguard Worker 		ERROR("Corrupted root key header in GVD\n");
936*8617a60dSAndroid Build Coastguard Worker 		return -1;
937*8617a60dSAndroid Build Coastguard Worker 	}
938*8617a60dSAndroid Build Coastguard Worker 
939*8617a60dSAndroid Build Coastguard Worker 	return 0;
940*8617a60dSAndroid Build Coastguard Worker }
941*8617a60dSAndroid Build Coastguard Worker 
942*8617a60dSAndroid Build Coastguard Worker /**
943*8617a60dSAndroid Build Coastguard Worker  * Validate GVD signature.
944*8617a60dSAndroid Build Coastguard Worker  *
945*8617a60dSAndroid Build Coastguard Worker  * Given the entire GVD space (header plus ranges array), the signature and
946*8617a60dSAndroid Build Coastguard Worker  * the public key, verify that the signature matches.
947*8617a60dSAndroid Build Coastguard Worker  *
948*8617a60dSAndroid Build Coastguard Worker  * @param gvd  pointer to gsc_verification_data followed by the ranges array
949*8617a60dSAndroid Build Coastguard Worker  * @param gvd_signature  pointer to the vb2 signature container
950*8617a60dSAndroid Build Coastguard Worker  * @param packedk  pointer to the keyblock containing the public key
951*8617a60dSAndroid Build Coastguard Worker  *
952*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, non-zero on failure
953*8617a60dSAndroid Build Coastguard Worker  */
validate_gvd_signature(struct gsc_verification_data * gvd,const struct vb2_packed_key * packedk)954*8617a60dSAndroid Build Coastguard Worker static int validate_gvd_signature(struct gsc_verification_data *gvd,
955*8617a60dSAndroid Build Coastguard Worker 				  const struct vb2_packed_key *packedk)
956*8617a60dSAndroid Build Coastguard Worker {
957*8617a60dSAndroid Build Coastguard Worker 	struct vb2_workbuf wb;
958*8617a60dSAndroid Build Coastguard Worker 	void *buf;
959*8617a60dSAndroid Build Coastguard Worker 	int rv;
960*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key pubk;
961*8617a60dSAndroid Build Coastguard Worker 	size_t signed_size;
962*8617a60dSAndroid Build Coastguard Worker 
963*8617a60dSAndroid Build Coastguard Worker 	/* Extract public key from the public key keyblock. */
964*8617a60dSAndroid Build Coastguard Worker 	if (vb2_unpack_key(&pubk, packedk) != VB2_SUCCESS) {
965*8617a60dSAndroid Build Coastguard Worker 		ERROR("Failed to unpack public key\n");
966*8617a60dSAndroid Build Coastguard Worker 		return -1;
967*8617a60dSAndroid Build Coastguard Worker 	}
968*8617a60dSAndroid Build Coastguard Worker 
969*8617a60dSAndroid Build Coastguard Worker 	/* Let's create an ample sized work buffer. */
970*8617a60dSAndroid Build Coastguard Worker 	buf = init_wb(&wb, 8192);
971*8617a60dSAndroid Build Coastguard Worker 	if (!buf)
972*8617a60dSAndroid Build Coastguard Worker 		return -1;
973*8617a60dSAndroid Build Coastguard Worker 
974*8617a60dSAndroid Build Coastguard Worker 	signed_size = sizeof(struct gsc_verification_data) +
975*8617a60dSAndroid Build Coastguard Worker 		gvd->range_count * sizeof(gvd->ranges[0]);
976*8617a60dSAndroid Build Coastguard Worker 
977*8617a60dSAndroid Build Coastguard Worker 	rv = vb2_verify_data((const uint8_t *)gvd, signed_size,
978*8617a60dSAndroid Build Coastguard Worker 			     &gvd->sig_header,
979*8617a60dSAndroid Build Coastguard Worker 			     &pubk, &wb);
980*8617a60dSAndroid Build Coastguard Worker 
981*8617a60dSAndroid Build Coastguard Worker 	free(buf);
982*8617a60dSAndroid Build Coastguard Worker 	return rv;
983*8617a60dSAndroid Build Coastguard Worker }
984*8617a60dSAndroid Build Coastguard Worker 
985*8617a60dSAndroid Build Coastguard Worker /*
986*8617a60dSAndroid Build Coastguard Worker  * Try retrieving GVD ranges from the passed in AP firmware file.
987*8617a60dSAndroid Build Coastguard Worker  *
988*8617a60dSAndroid Build Coastguard Worker  * The passed in ranges structure is set to the set of ranges retrieved from
989*8617a60dSAndroid Build Coastguard Worker  * the firmware file, if any.
990*8617a60dSAndroid Build Coastguard Worker  */
try_retrieving_ranges_from_the_image(const char * file_name,struct gscvd_ro_ranges * ranges,struct file_buf * ap_firmware_file)991*8617a60dSAndroid Build Coastguard Worker static void try_retrieving_ranges_from_the_image(const char *file_name,
992*8617a60dSAndroid Build Coastguard Worker 						 struct gscvd_ro_ranges *ranges,
993*8617a60dSAndroid Build Coastguard Worker 						 struct file_buf
994*8617a60dSAndroid Build Coastguard Worker 						 *ap_firmware_file)
995*8617a60dSAndroid Build Coastguard Worker {
996*8617a60dSAndroid Build Coastguard Worker 	struct gsc_verification_data *gvd;
997*8617a60dSAndroid Build Coastguard Worker 	size_t i;
998*8617a60dSAndroid Build Coastguard Worker 
999*8617a60dSAndroid Build Coastguard Worker 	ranges->range_count = 0;
1000*8617a60dSAndroid Build Coastguard Worker 
1001*8617a60dSAndroid Build Coastguard Worker 	/* Look for ranges in GVD and copy them if found. */
1002*8617a60dSAndroid Build Coastguard Worker 	gvd = (struct gsc_verification_data
1003*8617a60dSAndroid Build Coastguard Worker 	       *)(ap_firmware_file->data +
1004*8617a60dSAndroid Build Coastguard Worker 		  ap_firmware_file->ro_gscvd->area_offset);
1005*8617a60dSAndroid Build Coastguard Worker 
1006*8617a60dSAndroid Build Coastguard Worker 	if (validate_gvd(gvd, ap_firmware_file))
1007*8617a60dSAndroid Build Coastguard Worker 		return;
1008*8617a60dSAndroid Build Coastguard Worker 
1009*8617a60dSAndroid Build Coastguard Worker 	if (copy_ranges(ap_firmware_file, gvd, ranges))
1010*8617a60dSAndroid Build Coastguard Worker 		return;
1011*8617a60dSAndroid Build Coastguard Worker 
1012*8617a60dSAndroid Build Coastguard Worker 	if (!ranges->range_count) {
1013*8617a60dSAndroid Build Coastguard Worker 		printf("No ranges found in the input file\n");
1014*8617a60dSAndroid Build Coastguard Worker 	} else {
1015*8617a60dSAndroid Build Coastguard Worker 		printf("Will re-sign the following %zd ranges:\n",
1016*8617a60dSAndroid Build Coastguard Worker 		       ranges->range_count);
1017*8617a60dSAndroid Build Coastguard Worker 		for (i = 0; i < ranges->range_count; i++) {
1018*8617a60dSAndroid Build Coastguard Worker 			printf("%08x:%08x\n",
1019*8617a60dSAndroid Build Coastguard Worker 			       ranges->ranges[i].offset,
1020*8617a60dSAndroid Build Coastguard Worker 			       ranges->ranges[i].size);
1021*8617a60dSAndroid Build Coastguard Worker 		}
1022*8617a60dSAndroid Build Coastguard Worker 	}
1023*8617a60dSAndroid Build Coastguard Worker }
1024*8617a60dSAndroid Build Coastguard Worker 
1025*8617a60dSAndroid Build Coastguard Worker /*
1026*8617a60dSAndroid Build Coastguard Worker  * Calculate ranges digest and compare it with the value stored in gvd, with
1027*8617a60dSAndroid Build Coastguard Worker  * or without ignoring GBB flags, as requested by the caller.
1028*8617a60dSAndroid Build Coastguard Worker  *
1029*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, nonzero on failure.
1030*8617a60dSAndroid Build Coastguard Worker  */
validate_digest(struct file_buf * ap_firmware_file,const struct gscvd_ro_ranges * ranges,const struct gsc_verification_data * gvd,bool override_gbb_flags)1031*8617a60dSAndroid Build Coastguard Worker static int validate_digest(struct file_buf *ap_firmware_file,
1032*8617a60dSAndroid Build Coastguard Worker 			   const struct gscvd_ro_ranges *ranges,
1033*8617a60dSAndroid Build Coastguard Worker 			   const struct gsc_verification_data *gvd,
1034*8617a60dSAndroid Build Coastguard Worker 			   bool override_gbb_flags)
1035*8617a60dSAndroid Build Coastguard Worker {
1036*8617a60dSAndroid Build Coastguard Worker 	uint8_t digest[sizeof(gvd->ranges_digest)];
1037*8617a60dSAndroid Build Coastguard Worker 
1038*8617a60dSAndroid Build Coastguard Worker 	if (calculate_ranges_digest(ap_firmware_file, ranges,
1039*8617a60dSAndroid Build Coastguard Worker 				    gvd->hash_alg, digest,
1040*8617a60dSAndroid Build Coastguard Worker 				    sizeof(digest),
1041*8617a60dSAndroid Build Coastguard Worker 				    override_gbb_flags)) {
1042*8617a60dSAndroid Build Coastguard Worker 		return 1;
1043*8617a60dSAndroid Build Coastguard Worker 	}
1044*8617a60dSAndroid Build Coastguard Worker 
1045*8617a60dSAndroid Build Coastguard Worker 	return memcmp(digest, gvd->ranges_digest, sizeof(digest));
1046*8617a60dSAndroid Build Coastguard Worker }
1047*8617a60dSAndroid Build Coastguard Worker 
1048*8617a60dSAndroid Build Coastguard Worker /*
1049*8617a60dSAndroid Build Coastguard Worker  * Validate GVD of the passed in AP firmware file and possibly the root key hash
1050*8617a60dSAndroid Build Coastguard Worker  *
1051*8617a60dSAndroid Build Coastguard Worker  * The input parameters are the subset of the command line, the first argv
1052*8617a60dSAndroid Build Coastguard Worker  * string is the AP firmware file name, the second string, if present, is the
1053*8617a60dSAndroid Build Coastguard Worker  * hash of the root public key included in the RO_GSCVD area of the AP
1054*8617a60dSAndroid Build Coastguard Worker  * firmware file.
1055*8617a60dSAndroid Build Coastguard Worker  *
1056*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, nonzero on failure.
1057*8617a60dSAndroid Build Coastguard Worker  */
validate_gscvd(int argc,char * argv[])1058*8617a60dSAndroid Build Coastguard Worker static int validate_gscvd(int argc, char *argv[])
1059*8617a60dSAndroid Build Coastguard Worker {
1060*8617a60dSAndroid Build Coastguard Worker 	struct file_buf ap_firmware_file;
1061*8617a60dSAndroid Build Coastguard Worker 	int rv;
1062*8617a60dSAndroid Build Coastguard Worker 	struct gscvd_ro_ranges ranges;
1063*8617a60dSAndroid Build Coastguard Worker 	struct gsc_verification_data *gvd;
1064*8617a60dSAndroid Build Coastguard Worker 	const char *file_name;
1065*8617a60dSAndroid Build Coastguard Worker 	struct vb2_hash root_key_digest = { .algo = VB2_HASH_SHA256 };
1066*8617a60dSAndroid Build Coastguard Worker 
1067*8617a60dSAndroid Build Coastguard Worker 	/* Guaranteed to be available. */
1068*8617a60dSAndroid Build Coastguard Worker 	file_name = argv[0];
1069*8617a60dSAndroid Build Coastguard Worker 
1070*8617a60dSAndroid Build Coastguard Worker 	if (argc > 1)
1071*8617a60dSAndroid Build Coastguard Worker 		parse_digest_or_die(root_key_digest.sha256,
1072*8617a60dSAndroid Build Coastguard Worker 				    sizeof(root_key_digest.sha256),
1073*8617a60dSAndroid Build Coastguard Worker 				    argv[1]);
1074*8617a60dSAndroid Build Coastguard Worker 
1075*8617a60dSAndroid Build Coastguard Worker 	do {
1076*8617a60dSAndroid Build Coastguard Worker 		struct vb2_keyblock *kblock;
1077*8617a60dSAndroid Build Coastguard Worker 
1078*8617a60dSAndroid Build Coastguard Worker 		rv = -1; /* Speculative, will be cleared on success. */
1079*8617a60dSAndroid Build Coastguard Worker 
1080*8617a60dSAndroid Build Coastguard Worker 		if (load_ap_firmware(file_name, &ap_firmware_file, FILE_RO))
1081*8617a60dSAndroid Build Coastguard Worker 			break;
1082*8617a60dSAndroid Build Coastguard Worker 
1083*8617a60dSAndroid Build Coastguard Worker 		/* Copy ranges from gscvd to local structure. */
1084*8617a60dSAndroid Build Coastguard Worker 		gvd = (struct gsc_verification_data
1085*8617a60dSAndroid Build Coastguard Worker 			       *)(ap_firmware_file.data +
1086*8617a60dSAndroid Build Coastguard Worker 				  ap_firmware_file.ro_gscvd->area_offset);
1087*8617a60dSAndroid Build Coastguard Worker 
1088*8617a60dSAndroid Build Coastguard Worker 		if (validate_gvd(gvd, &ap_firmware_file))
1089*8617a60dSAndroid Build Coastguard Worker 			break;
1090*8617a60dSAndroid Build Coastguard Worker 
1091*8617a60dSAndroid Build Coastguard Worker 		if (copy_ranges(&ap_firmware_file, gvd, &ranges))
1092*8617a60dSAndroid Build Coastguard Worker 			break;
1093*8617a60dSAndroid Build Coastguard Worker 
1094*8617a60dSAndroid Build Coastguard Worker 		/* First try validating without ignoring GBB flags. */
1095*8617a60dSAndroid Build Coastguard Worker 		if (validate_digest(&ap_firmware_file, &ranges, gvd, false)) {
1096*8617a60dSAndroid Build Coastguard Worker 			/* It failed, maybe GBB flags are not cleared yet. */
1097*8617a60dSAndroid Build Coastguard Worker 			if (validate_digest(&ap_firmware_file, &ranges,
1098*8617a60dSAndroid Build Coastguard Worker 					    gvd, true)) {
1099*8617a60dSAndroid Build Coastguard Worker 				ERROR("Ranges digest mismatch\n");
1100*8617a60dSAndroid Build Coastguard Worker 				break;
1101*8617a60dSAndroid Build Coastguard Worker 			}
1102*8617a60dSAndroid Build Coastguard Worker 			WARN("Ranges digest matches with zeroed GBB flags\n");
1103*8617a60dSAndroid Build Coastguard Worker 		}
1104*8617a60dSAndroid Build Coastguard Worker 
1105*8617a60dSAndroid Build Coastguard Worker 		/* Find the keyblock. */
1106*8617a60dSAndroid Build Coastguard Worker 		kblock = (struct vb2_keyblock *)((uintptr_t)gvd + gvd->size);
1107*8617a60dSAndroid Build Coastguard Worker 
1108*8617a60dSAndroid Build Coastguard Worker 		if ((argc > 1) && (vb2_hash_verify(false,
1109*8617a60dSAndroid Build Coastguard Worker 				vb2_packed_key_data(&gvd->root_key_header),
1110*8617a60dSAndroid Build Coastguard Worker 				gvd->root_key_header.key_size,
1111*8617a60dSAndroid Build Coastguard Worker 				&root_key_digest) != VB2_SUCCESS)) {
1112*8617a60dSAndroid Build Coastguard Worker 			ERROR("Sha256 mismatch\n");
1113*8617a60dSAndroid Build Coastguard Worker 			break;
1114*8617a60dSAndroid Build Coastguard Worker 		}
1115*8617a60dSAndroid Build Coastguard Worker 
1116*8617a60dSAndroid Build Coastguard Worker 		if (validate_pubk_signature(&gvd->root_key_header, kblock)) {
1117*8617a60dSAndroid Build Coastguard Worker 			ERROR("Keyblock not signed by root key\n");
1118*8617a60dSAndroid Build Coastguard Worker 			break;
1119*8617a60dSAndroid Build Coastguard Worker 		}
1120*8617a60dSAndroid Build Coastguard Worker 
1121*8617a60dSAndroid Build Coastguard Worker 		if (validate_gvd_signature(gvd, &kblock->data_key)) {
1122*8617a60dSAndroid Build Coastguard Worker 			ERROR("GVD not signed by platform key\n");
1123*8617a60dSAndroid Build Coastguard Worker 			break;
1124*8617a60dSAndroid Build Coastguard Worker 		}
1125*8617a60dSAndroid Build Coastguard Worker 
1126*8617a60dSAndroid Build Coastguard Worker 		rv = 0;
1127*8617a60dSAndroid Build Coastguard Worker 	} while (false);
1128*8617a60dSAndroid Build Coastguard Worker 
1129*8617a60dSAndroid Build Coastguard Worker 	if (ap_firmware_file.fd != -1)
1130*8617a60dSAndroid Build Coastguard Worker 		futil_unmap_and_close_file(ap_firmware_file.fd, FILE_RO,
1131*8617a60dSAndroid Build Coastguard Worker 					   ap_firmware_file.data,
1132*8617a60dSAndroid Build Coastguard Worker 					   ap_firmware_file.len);
1133*8617a60dSAndroid Build Coastguard Worker 
1134*8617a60dSAndroid Build Coastguard Worker 	return rv;
1135*8617a60dSAndroid Build Coastguard Worker }
1136*8617a60dSAndroid Build Coastguard Worker 
1137*8617a60dSAndroid Build Coastguard Worker /**
1138*8617a60dSAndroid Build Coastguard Worker  * Calculate and report sha256 hash of the public key body.
1139*8617a60dSAndroid Build Coastguard Worker  *
1140*8617a60dSAndroid Build Coastguard Worker  * The hash will be incorporated into GVC firmware to allow it to validate the
1141*8617a60dSAndroid Build Coastguard Worker  * root key.
1142*8617a60dSAndroid Build Coastguard Worker  *
1143*8617a60dSAndroid Build Coastguard Worker  * @param pubk pointer to the public key to process.
1144*8617a60dSAndroid Build Coastguard Worker  */
dump_pubk_hash(const struct vb2_packed_key * pubk)1145*8617a60dSAndroid Build Coastguard Worker static void dump_pubk_hash(const struct vb2_packed_key *pubk)
1146*8617a60dSAndroid Build Coastguard Worker {
1147*8617a60dSAndroid Build Coastguard Worker 	struct vb2_hash hash;
1148*8617a60dSAndroid Build Coastguard Worker 	size_t i;
1149*8617a60dSAndroid Build Coastguard Worker 
1150*8617a60dSAndroid Build Coastguard Worker 	vb2_hash_calculate(false, vb2_packed_key_data(pubk), pubk->key_size,
1151*8617a60dSAndroid Build Coastguard Worker 			   VB2_HASH_SHA256, &hash);
1152*8617a60dSAndroid Build Coastguard Worker 
1153*8617a60dSAndroid Build Coastguard Worker 	printf("Root key body sha256 hash:\n");
1154*8617a60dSAndroid Build Coastguard Worker 
1155*8617a60dSAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(hash.sha256); i++)
1156*8617a60dSAndroid Build Coastguard Worker 		printf("%02x", hash.sha256[i]);
1157*8617a60dSAndroid Build Coastguard Worker 
1158*8617a60dSAndroid Build Coastguard Worker 	printf("\n");
1159*8617a60dSAndroid Build Coastguard Worker }
1160*8617a60dSAndroid Build Coastguard Worker 
1161*8617a60dSAndroid Build Coastguard Worker /**
1162*8617a60dSAndroid Build Coastguard Worker  * The main function of this futilty option.
1163*8617a60dSAndroid Build Coastguard Worker  *
1164*8617a60dSAndroid Build Coastguard Worker  * See the usage string for input details.
1165*8617a60dSAndroid Build Coastguard Worker  *
1166*8617a60dSAndroid Build Coastguard Worker  * @return zero on success, nonzero on failure.
1167*8617a60dSAndroid Build Coastguard Worker  */
do_gscvd(int argc,char * argv[])1168*8617a60dSAndroid Build Coastguard Worker static int do_gscvd(int argc, char *argv[])
1169*8617a60dSAndroid Build Coastguard Worker {
1170*8617a60dSAndroid Build Coastguard Worker 	int i;
1171*8617a60dSAndroid Build Coastguard Worker 	int longindex;
1172*8617a60dSAndroid Build Coastguard Worker 	bool do_gbb = false;
1173*8617a60dSAndroid Build Coastguard Worker 	char *infile = NULL;
1174*8617a60dSAndroid Build Coastguard Worker 	char *outfile = NULL;
1175*8617a60dSAndroid Build Coastguard Worker 	char *work_file = NULL;
1176*8617a60dSAndroid Build Coastguard Worker 	struct gscvd_ro_ranges ranges;
1177*8617a60dSAndroid Build Coastguard Worker 	int errorcount = 0;
1178*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *root_pubk = NULL;
1179*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *kblock = NULL;
1180*8617a60dSAndroid Build Coastguard Worker 	struct vb2_private_key *plat_privk = NULL;
1181*8617a60dSAndroid Build Coastguard Worker 	struct gsc_verification_data *gvd = NULL;
1182*8617a60dSAndroid Build Coastguard Worker 	struct file_buf ap_firmware_file = { .fd = -1 };
1183*8617a60dSAndroid Build Coastguard Worker 	uint32_t board_id = UINT32_MAX;
1184*8617a60dSAndroid Build Coastguard Worker 	char *ro_gscvd_file = NULL;
1185*8617a60dSAndroid Build Coastguard Worker 	int rv = 0;
1186*8617a60dSAndroid Build Coastguard Worker 
1187*8617a60dSAndroid Build Coastguard Worker 	ranges.range_count = 0;
1188*8617a60dSAndroid Build Coastguard Worker 
1189*8617a60dSAndroid Build Coastguard Worker 	while ((i = getopt_long(argc, argv, short_opts, long_opts,
1190*8617a60dSAndroid Build Coastguard Worker 				&longindex)) != -1) {
1191*8617a60dSAndroid Build Coastguard Worker 		switch (i) {
1192*8617a60dSAndroid Build Coastguard Worker 		case OPT_OUTFILE:
1193*8617a60dSAndroid Build Coastguard Worker 			outfile = optarg;
1194*8617a60dSAndroid Build Coastguard Worker 			break;
1195*8617a60dSAndroid Build Coastguard Worker 		case OPT_RO_GSCVD_FILE:
1196*8617a60dSAndroid Build Coastguard Worker 			ro_gscvd_file = optarg;
1197*8617a60dSAndroid Build Coastguard Worker 			break;
1198*8617a60dSAndroid Build Coastguard Worker 		case 'R':
1199*8617a60dSAndroid Build Coastguard Worker 			if (parse_ranges(optarg, &ranges)) {
1200*8617a60dSAndroid Build Coastguard Worker 				ERROR("Could not parse ranges\n");
1201*8617a60dSAndroid Build Coastguard Worker 				/* Error message has been already printed. */
1202*8617a60dSAndroid Build Coastguard Worker 				errorcount++;
1203*8617a60dSAndroid Build Coastguard Worker 			}
1204*8617a60dSAndroid Build Coastguard Worker 			break;
1205*8617a60dSAndroid Build Coastguard Worker 		case 'G':
1206*8617a60dSAndroid Build Coastguard Worker 			do_gbb = true;
1207*8617a60dSAndroid Build Coastguard Worker 			break;
1208*8617a60dSAndroid Build Coastguard Worker 		case 'b': {
1209*8617a60dSAndroid Build Coastguard Worker 			char *e;
1210*8617a60dSAndroid Build Coastguard Worker 			long long bid;
1211*8617a60dSAndroid Build Coastguard Worker 
1212*8617a60dSAndroid Build Coastguard Worker 			if (strlen(optarg) == 4) {
1213*8617a60dSAndroid Build Coastguard Worker 				board_id = optarg[0] << 24 |
1214*8617a60dSAndroid Build Coastguard Worker 					   optarg[1] << 16 |
1215*8617a60dSAndroid Build Coastguard Worker 					   optarg[2] << 8 |
1216*8617a60dSAndroid Build Coastguard Worker 					   optarg[3];
1217*8617a60dSAndroid Build Coastguard Worker 				break;
1218*8617a60dSAndroid Build Coastguard Worker 			}
1219*8617a60dSAndroid Build Coastguard Worker 
1220*8617a60dSAndroid Build Coastguard Worker 			bid = strtoull(optarg, &e, 16);
1221*8617a60dSAndroid Build Coastguard Worker 			if (*e || (bid >= UINT32_MAX)) {
1222*8617a60dSAndroid Build Coastguard Worker 				ERROR("Cannot parse Board ID '%s'\n",
1223*8617a60dSAndroid Build Coastguard Worker 				      optarg);
1224*8617a60dSAndroid Build Coastguard Worker 				errorcount++;
1225*8617a60dSAndroid Build Coastguard Worker 			} else {
1226*8617a60dSAndroid Build Coastguard Worker 				board_id = (uint32_t)bid;
1227*8617a60dSAndroid Build Coastguard Worker 			}
1228*8617a60dSAndroid Build Coastguard Worker 			break;
1229*8617a60dSAndroid Build Coastguard Worker 		}
1230*8617a60dSAndroid Build Coastguard Worker 		case 'r':
1231*8617a60dSAndroid Build Coastguard Worker 			root_pubk = vb2_read_packed_key(optarg);
1232*8617a60dSAndroid Build Coastguard Worker 			if (!root_pubk) {
1233*8617a60dSAndroid Build Coastguard Worker 				ERROR("Could not read %s\n", optarg);
1234*8617a60dSAndroid Build Coastguard Worker 				errorcount++;
1235*8617a60dSAndroid Build Coastguard Worker 			}
1236*8617a60dSAndroid Build Coastguard Worker 			break;
1237*8617a60dSAndroid Build Coastguard Worker 		case 'k':
1238*8617a60dSAndroid Build Coastguard Worker 			kblock = vb2_read_keyblock(optarg);
1239*8617a60dSAndroid Build Coastguard Worker 			if (!kblock) {
1240*8617a60dSAndroid Build Coastguard Worker 				ERROR("Could not read %s\n", optarg);
1241*8617a60dSAndroid Build Coastguard Worker 				errorcount++;
1242*8617a60dSAndroid Build Coastguard Worker 			}
1243*8617a60dSAndroid Build Coastguard Worker 			break;
1244*8617a60dSAndroid Build Coastguard Worker 		case 'p':
1245*8617a60dSAndroid Build Coastguard Worker 			plat_privk = vb2_read_private_key(optarg);
1246*8617a60dSAndroid Build Coastguard Worker 			if (!plat_privk) {
1247*8617a60dSAndroid Build Coastguard Worker 				ERROR("Could not read %s\n", optarg);
1248*8617a60dSAndroid Build Coastguard Worker 				errorcount++;
1249*8617a60dSAndroid Build Coastguard Worker 			}
1250*8617a60dSAndroid Build Coastguard Worker 			break;
1251*8617a60dSAndroid Build Coastguard Worker 		case 'h':
1252*8617a60dSAndroid Build Coastguard Worker 			printf("%s", usage);
1253*8617a60dSAndroid Build Coastguard Worker 			return 0;
1254*8617a60dSAndroid Build Coastguard Worker 		case '?':
1255*8617a60dSAndroid Build Coastguard Worker 			if (optopt)
1256*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unrecognized option: -%c\n", optopt);
1257*8617a60dSAndroid Build Coastguard Worker 			else
1258*8617a60dSAndroid Build Coastguard Worker 				ERROR("Unrecognized option: %s\n",
1259*8617a60dSAndroid Build Coastguard Worker 				      argv[optind - 1]);
1260*8617a60dSAndroid Build Coastguard Worker 			errorcount++;
1261*8617a60dSAndroid Build Coastguard Worker 			break;
1262*8617a60dSAndroid Build Coastguard Worker 		case ':':
1263*8617a60dSAndroid Build Coastguard Worker 			ERROR("Missing argument to -%c\n", optopt);
1264*8617a60dSAndroid Build Coastguard Worker 			errorcount++;
1265*8617a60dSAndroid Build Coastguard Worker 			break;
1266*8617a60dSAndroid Build Coastguard Worker 		case 0: /* handled option */
1267*8617a60dSAndroid Build Coastguard Worker 			break;
1268*8617a60dSAndroid Build Coastguard Worker 		default:
1269*8617a60dSAndroid Build Coastguard Worker 			FATAL("Unrecognized getopt output: %d\n", i);
1270*8617a60dSAndroid Build Coastguard Worker 		}
1271*8617a60dSAndroid Build Coastguard Worker 	}
1272*8617a60dSAndroid Build Coastguard Worker 
1273*8617a60dSAndroid Build Coastguard Worker 	if ((optind == 1) && (argc > 1)) {
1274*8617a60dSAndroid Build Coastguard Worker 		if (ro_gscvd_file) {
1275*8617a60dSAndroid Build Coastguard Worker 			ERROR("Unexpected --gscvd_out in command line\n");
1276*8617a60dSAndroid Build Coastguard Worker 			goto usage_out;
1277*8617a60dSAndroid Build Coastguard Worker 		}
1278*8617a60dSAndroid Build Coastguard Worker 		/* This must be a validation request. */
1279*8617a60dSAndroid Build Coastguard Worker 		return validate_gscvd(argc - 1, argv + 1);
1280*8617a60dSAndroid Build Coastguard Worker 	}
1281*8617a60dSAndroid Build Coastguard Worker 
1282*8617a60dSAndroid Build Coastguard Worker 	if (errorcount) /* Error message(s) should have been printed by now. */
1283*8617a60dSAndroid Build Coastguard Worker 		goto usage_out;
1284*8617a60dSAndroid Build Coastguard Worker 
1285*8617a60dSAndroid Build Coastguard Worker 	if (!root_pubk) {
1286*8617a60dSAndroid Build Coastguard Worker 		ERROR("Missing --root_pub_key argument\n");
1287*8617a60dSAndroid Build Coastguard Worker 		goto usage_out;
1288*8617a60dSAndroid Build Coastguard Worker 	} else if (argc == 3) {
1289*8617a60dSAndroid Build Coastguard Worker 		if (ro_gscvd_file) {
1290*8617a60dSAndroid Build Coastguard Worker 			ERROR("Unexpected --gscvd_out in command line\n");
1291*8617a60dSAndroid Build Coastguard Worker 			goto usage_out;
1292*8617a60dSAndroid Build Coastguard Worker 		}
1293*8617a60dSAndroid Build Coastguard Worker 		/*
1294*8617a60dSAndroid Build Coastguard Worker 		 * This is a request to print out the hash of the root pub key
1295*8617a60dSAndroid Build Coastguard Worker 		 * payload.
1296*8617a60dSAndroid Build Coastguard Worker 		 */
1297*8617a60dSAndroid Build Coastguard Worker 		dump_pubk_hash(root_pubk);
1298*8617a60dSAndroid Build Coastguard Worker 		return 0;
1299*8617a60dSAndroid Build Coastguard Worker 	}
1300*8617a60dSAndroid Build Coastguard Worker 
1301*8617a60dSAndroid Build Coastguard Worker 	if (optind != (argc - 1)) {
1302*8617a60dSAndroid Build Coastguard Worker 		ERROR("Misformatted command line\n");
1303*8617a60dSAndroid Build Coastguard Worker 		goto usage_out;
1304*8617a60dSAndroid Build Coastguard Worker 	}
1305*8617a60dSAndroid Build Coastguard Worker 
1306*8617a60dSAndroid Build Coastguard Worker 	infile = argv[optind];
1307*8617a60dSAndroid Build Coastguard Worker 
1308*8617a60dSAndroid Build Coastguard Worker 	if (!kblock) {
1309*8617a60dSAndroid Build Coastguard Worker 		ERROR("Missing --keyblock argument\n");
1310*8617a60dSAndroid Build Coastguard Worker 		goto usage_out;
1311*8617a60dSAndroid Build Coastguard Worker 	}
1312*8617a60dSAndroid Build Coastguard Worker 
1313*8617a60dSAndroid Build Coastguard Worker 	if (!plat_privk) {
1314*8617a60dSAndroid Build Coastguard Worker 		ERROR("Missing --platform_priv argument\n");
1315*8617a60dSAndroid Build Coastguard Worker 		goto usage_out;
1316*8617a60dSAndroid Build Coastguard Worker 	}
1317*8617a60dSAndroid Build Coastguard Worker 
1318*8617a60dSAndroid Build Coastguard Worker 	if (board_id == UINT32_MAX) {
1319*8617a60dSAndroid Build Coastguard Worker 		ERROR("Missing --board_id argument\n");
1320*8617a60dSAndroid Build Coastguard Worker 		goto usage_out;
1321*8617a60dSAndroid Build Coastguard Worker 	}
1322*8617a60dSAndroid Build Coastguard Worker 
1323*8617a60dSAndroid Build Coastguard Worker 	if (outfile) {
1324*8617a60dSAndroid Build Coastguard Worker 		if (futil_copy_file(infile, outfile) < 0)
1325*8617a60dSAndroid Build Coastguard Worker 			exit(1);
1326*8617a60dSAndroid Build Coastguard Worker 		work_file = outfile;
1327*8617a60dSAndroid Build Coastguard Worker 	} else {
1328*8617a60dSAndroid Build Coastguard Worker 		work_file = infile;
1329*8617a60dSAndroid Build Coastguard Worker 	}
1330*8617a60dSAndroid Build Coastguard Worker 
1331*8617a60dSAndroid Build Coastguard Worker 	do {
1332*8617a60dSAndroid Build Coastguard Worker 		rv = 1; /* Speculative, will be cleared on success. */
1333*8617a60dSAndroid Build Coastguard Worker 
1334*8617a60dSAndroid Build Coastguard Worker 		if (validate_pubk_signature(root_pubk, kblock))
1335*8617a60dSAndroid Build Coastguard Worker 			break;
1336*8617a60dSAndroid Build Coastguard Worker 
1337*8617a60dSAndroid Build Coastguard Worker 		if (validate_privk(kblock, plat_privk))
1338*8617a60dSAndroid Build Coastguard Worker 			break;
1339*8617a60dSAndroid Build Coastguard Worker 
1340*8617a60dSAndroid Build Coastguard Worker 		if (load_ap_firmware(work_file, &ap_firmware_file, FILE_RW))
1341*8617a60dSAndroid Build Coastguard Worker 			break;
1342*8617a60dSAndroid Build Coastguard Worker 
1343*8617a60dSAndroid Build Coastguard Worker 		if (!ranges.range_count)
1344*8617a60dSAndroid Build Coastguard Worker 			try_retrieving_ranges_from_the_image(infile,
1345*8617a60dSAndroid Build Coastguard Worker 							     &ranges,
1346*8617a60dSAndroid Build Coastguard Worker 							     &ap_firmware_file);
1347*8617a60dSAndroid Build Coastguard Worker 
1348*8617a60dSAndroid Build Coastguard Worker 		if (!ranges.range_count && !do_gbb) {
1349*8617a60dSAndroid Build Coastguard Worker 			ERROR("Missing --ranges argument and no ranges in the input file\n");
1350*8617a60dSAndroid Build Coastguard Worker 			break;
1351*8617a60dSAndroid Build Coastguard Worker 		}
1352*8617a60dSAndroid Build Coastguard Worker 
1353*8617a60dSAndroid Build Coastguard Worker 		if (do_gbb && add_gbb(&ranges, &ap_firmware_file))
1354*8617a60dSAndroid Build Coastguard Worker 			break;
1355*8617a60dSAndroid Build Coastguard Worker 
1356*8617a60dSAndroid Build Coastguard Worker 		if (verify_ranges(&ranges, &ap_firmware_file))
1357*8617a60dSAndroid Build Coastguard Worker 			break;
1358*8617a60dSAndroid Build Coastguard Worker 
1359*8617a60dSAndroid Build Coastguard Worker 		gvd = create_gvd(&ap_firmware_file, &ranges,
1360*8617a60dSAndroid Build Coastguard Worker 				 root_pubk, plat_privk, board_id);
1361*8617a60dSAndroid Build Coastguard Worker 		if (!gvd)
1362*8617a60dSAndroid Build Coastguard Worker 			break;
1363*8617a60dSAndroid Build Coastguard Worker 
1364*8617a60dSAndroid Build Coastguard Worker 		if (fill_gvd_area(&ap_firmware_file, gvd,
1365*8617a60dSAndroid Build Coastguard Worker 				  kblock, ro_gscvd_file))
1366*8617a60dSAndroid Build Coastguard Worker 			break;
1367*8617a60dSAndroid Build Coastguard Worker 
1368*8617a60dSAndroid Build Coastguard Worker 		rv = 0;
1369*8617a60dSAndroid Build Coastguard Worker 	} while (false);
1370*8617a60dSAndroid Build Coastguard Worker 
1371*8617a60dSAndroid Build Coastguard Worker 	free(gvd);
1372*8617a60dSAndroid Build Coastguard Worker 	free(root_pubk);
1373*8617a60dSAndroid Build Coastguard Worker 	free(kblock);
1374*8617a60dSAndroid Build Coastguard Worker 	vb2_free_private_key(plat_privk);
1375*8617a60dSAndroid Build Coastguard Worker 
1376*8617a60dSAndroid Build Coastguard Worker 	if (ap_firmware_file.fd != -1)
1377*8617a60dSAndroid Build Coastguard Worker 		futil_unmap_and_close_file(ap_firmware_file.fd, FILE_RW,
1378*8617a60dSAndroid Build Coastguard Worker 					   ap_firmware_file.data,
1379*8617a60dSAndroid Build Coastguard Worker 					   ap_firmware_file.len);
1380*8617a60dSAndroid Build Coastguard Worker 
1381*8617a60dSAndroid Build Coastguard Worker 	return rv;
1382*8617a60dSAndroid Build Coastguard Worker 
1383*8617a60dSAndroid Build Coastguard Worker usage_out:
1384*8617a60dSAndroid Build Coastguard Worker 	fputs(usage, stderr);
1385*8617a60dSAndroid Build Coastguard Worker 	return 1;
1386*8617a60dSAndroid Build Coastguard Worker }
1387*8617a60dSAndroid Build Coastguard Worker 
1388*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(gscvd, do_gscvd, VBOOT_VERSION_2_1,
1389*8617a60dSAndroid Build Coastguard Worker 		      "Create RO verification structure");
1390