xref: /aosp_15_r20/external/vboot_reference/futility/misc.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2014 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  */
5*8617a60dSAndroid Build Coastguard Worker 
6*8617a60dSAndroid Build Coastguard Worker #include <assert.h>
7*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
8*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
9*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
10*8617a60dSAndroid Build Coastguard Worker #include <linux/fs.h>		/* For BLKGETSIZE64 */
11*8617a60dSAndroid Build Coastguard Worker #include <sys/sendfile.h>
12*8617a60dSAndroid Build Coastguard Worker #else
13*8617a60dSAndroid Build Coastguard Worker #include <copyfile.h>
14*8617a60dSAndroid Build Coastguard Worker #endif
15*8617a60dSAndroid Build Coastguard Worker #include <stdarg.h>
16*8617a60dSAndroid Build Coastguard Worker #include <stdint.h>
17*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
18*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
19*8617a60dSAndroid Build Coastguard Worker #include <string.h>
20*8617a60dSAndroid Build Coastguard Worker #include <sys/ioctl.h>
21*8617a60dSAndroid Build Coastguard Worker #include <sys/mman.h>
22*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
23*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
24*8617a60dSAndroid Build Coastguard Worker #include <sys/wait.h>
25*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
26*8617a60dSAndroid Build Coastguard Worker 
27*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
28*8617a60dSAndroid Build Coastguard Worker #include "2sha.h"
29*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
30*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
31*8617a60dSAndroid Build Coastguard Worker #include "file_type.h"
32*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
33*8617a60dSAndroid Build Coastguard Worker #include "futility_options.h"
34*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
35*8617a60dSAndroid Build Coastguard Worker 
36*8617a60dSAndroid Build Coastguard Worker /* Default is to support everything we can */
37*8617a60dSAndroid Build Coastguard Worker enum vboot_version vboot_version = VBOOT_VERSION_ALL;
38*8617a60dSAndroid Build Coastguard Worker 
39*8617a60dSAndroid Build Coastguard Worker int debugging_enabled;
vb2ex_printf(const char * func,const char * format,...)40*8617a60dSAndroid Build Coastguard Worker void vb2ex_printf(const char *func, const char *format, ...)
41*8617a60dSAndroid Build Coastguard Worker {
42*8617a60dSAndroid Build Coastguard Worker 	if (!debugging_enabled)
43*8617a60dSAndroid Build Coastguard Worker 		return;
44*8617a60dSAndroid Build Coastguard Worker 
45*8617a60dSAndroid Build Coastguard Worker 	va_list ap;
46*8617a60dSAndroid Build Coastguard Worker 	va_start(ap, format);
47*8617a60dSAndroid Build Coastguard Worker 	if (func)
48*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "DEBUG: %s: ", func);
49*8617a60dSAndroid Build Coastguard Worker 	vfprintf(stderr, format, ap);
50*8617a60dSAndroid Build Coastguard Worker 	va_end(ap);
51*8617a60dSAndroid Build Coastguard Worker }
52*8617a60dSAndroid Build Coastguard Worker 
is_null_terminated(const char * s,int len)53*8617a60dSAndroid Build Coastguard Worker static int is_null_terminated(const char *s, int len)
54*8617a60dSAndroid Build Coastguard Worker {
55*8617a60dSAndroid Build Coastguard Worker 	len--;
56*8617a60dSAndroid Build Coastguard Worker 	s += len;
57*8617a60dSAndroid Build Coastguard Worker 	while (len-- >= 0)
58*8617a60dSAndroid Build Coastguard Worker 		if (!*s--)
59*8617a60dSAndroid Build Coastguard Worker 			return 1;
60*8617a60dSAndroid Build Coastguard Worker 	return 0;
61*8617a60dSAndroid Build Coastguard Worker }
62*8617a60dSAndroid Build Coastguard Worker 
max(uint32_t a,uint32_t b)63*8617a60dSAndroid Build Coastguard Worker static inline uint32_t max(uint32_t a, uint32_t b)
64*8617a60dSAndroid Build Coastguard Worker {
65*8617a60dSAndroid Build Coastguard Worker 	return a > b ? a : b;
66*8617a60dSAndroid Build Coastguard Worker }
67*8617a60dSAndroid Build Coastguard Worker 
ft_recognize_gbb(uint8_t * buf,uint32_t len)68*8617a60dSAndroid Build Coastguard Worker enum futil_file_type ft_recognize_gbb(uint8_t *buf, uint32_t len)
69*8617a60dSAndroid Build Coastguard Worker {
70*8617a60dSAndroid Build Coastguard Worker 	struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)buf;
71*8617a60dSAndroid Build Coastguard Worker 
72*8617a60dSAndroid Build Coastguard Worker 	if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE))
73*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
74*8617a60dSAndroid Build Coastguard Worker 	if (gbb->major_version > VB2_GBB_MAJOR_VER)
75*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
76*8617a60dSAndroid Build Coastguard Worker 	if (sizeof(struct vb2_gbb_header) > len)
77*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
78*8617a60dSAndroid Build Coastguard Worker 
79*8617a60dSAndroid Build Coastguard Worker 	/* close enough */
80*8617a60dSAndroid Build Coastguard Worker 	return FILE_TYPE_GBB;
81*8617a60dSAndroid Build Coastguard Worker }
82*8617a60dSAndroid Build Coastguard Worker 
futil_valid_gbb_header(struct vb2_gbb_header * gbb,uint32_t len,uint32_t * maxlen_ptr)83*8617a60dSAndroid Build Coastguard Worker int futil_valid_gbb_header(struct vb2_gbb_header *gbb, uint32_t len,
84*8617a60dSAndroid Build Coastguard Worker 			   uint32_t *maxlen_ptr)
85*8617a60dSAndroid Build Coastguard Worker {
86*8617a60dSAndroid Build Coastguard Worker 	if (len < sizeof(struct vb2_gbb_header))
87*8617a60dSAndroid Build Coastguard Worker 		return 0;
88*8617a60dSAndroid Build Coastguard Worker 
89*8617a60dSAndroid Build Coastguard Worker 	if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE))
90*8617a60dSAndroid Build Coastguard Worker 		return 0;
91*8617a60dSAndroid Build Coastguard Worker 	if (gbb->major_version != VB2_GBB_MAJOR_VER)
92*8617a60dSAndroid Build Coastguard Worker 		return 0;
93*8617a60dSAndroid Build Coastguard Worker 
94*8617a60dSAndroid Build Coastguard Worker 	/* Check limits first, to help identify problems */
95*8617a60dSAndroid Build Coastguard Worker 	if (maxlen_ptr) {
96*8617a60dSAndroid Build Coastguard Worker 		uint32_t maxlen = gbb->header_size;
97*8617a60dSAndroid Build Coastguard Worker 		maxlen = max(maxlen,
98*8617a60dSAndroid Build Coastguard Worker 			     gbb->hwid_offset + gbb->hwid_size);
99*8617a60dSAndroid Build Coastguard Worker 		maxlen = max(maxlen,
100*8617a60dSAndroid Build Coastguard Worker 			     gbb->rootkey_offset + gbb->rootkey_size);
101*8617a60dSAndroid Build Coastguard Worker 		maxlen = max(maxlen,
102*8617a60dSAndroid Build Coastguard Worker 			     gbb->bmpfv_offset + gbb->bmpfv_size);
103*8617a60dSAndroid Build Coastguard Worker 		maxlen = max(maxlen,
104*8617a60dSAndroid Build Coastguard Worker 			     gbb->recovery_key_offset + gbb->recovery_key_size);
105*8617a60dSAndroid Build Coastguard Worker 		*maxlen_ptr = maxlen;
106*8617a60dSAndroid Build Coastguard Worker 	}
107*8617a60dSAndroid Build Coastguard Worker 
108*8617a60dSAndroid Build Coastguard Worker 	if (gbb->header_size != EXPECTED_VB2_GBB_HEADER_SIZE ||
109*8617a60dSAndroid Build Coastguard Worker 	    gbb->header_size > len)
110*8617a60dSAndroid Build Coastguard Worker 		return 0;
111*8617a60dSAndroid Build Coastguard Worker 	if (gbb->hwid_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
112*8617a60dSAndroid Build Coastguard Worker 		return 0;
113*8617a60dSAndroid Build Coastguard Worker 	if ((uint64_t)gbb->hwid_offset + gbb->hwid_size > len)
114*8617a60dSAndroid Build Coastguard Worker 		return 0;
115*8617a60dSAndroid Build Coastguard Worker 	if (gbb->hwid_size) {
116*8617a60dSAndroid Build Coastguard Worker 		const char *s = (const char *)
117*8617a60dSAndroid Build Coastguard Worker 			((uint8_t *)gbb + gbb->hwid_offset);
118*8617a60dSAndroid Build Coastguard Worker 		if (!is_null_terminated(s, gbb->hwid_size))
119*8617a60dSAndroid Build Coastguard Worker 			return 0;
120*8617a60dSAndroid Build Coastguard Worker 	}
121*8617a60dSAndroid Build Coastguard Worker 	if (gbb->rootkey_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
122*8617a60dSAndroid Build Coastguard Worker 		return 0;
123*8617a60dSAndroid Build Coastguard Worker 	if ((uint64_t)gbb->rootkey_offset + gbb->rootkey_size > len)
124*8617a60dSAndroid Build Coastguard Worker 		return 0;
125*8617a60dSAndroid Build Coastguard Worker 
126*8617a60dSAndroid Build Coastguard Worker 	if (gbb->bmpfv_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
127*8617a60dSAndroid Build Coastguard Worker 		return 0;
128*8617a60dSAndroid Build Coastguard Worker 	if ((uint64_t)gbb->bmpfv_offset + gbb->bmpfv_size > len)
129*8617a60dSAndroid Build Coastguard Worker 		return 0;
130*8617a60dSAndroid Build Coastguard Worker 	if (gbb->recovery_key_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
131*8617a60dSAndroid Build Coastguard Worker 		return 0;
132*8617a60dSAndroid Build Coastguard Worker 	if ((uint64_t)gbb->recovery_key_offset + gbb->recovery_key_size > len)
133*8617a60dSAndroid Build Coastguard Worker 		return 0;
134*8617a60dSAndroid Build Coastguard Worker 
135*8617a60dSAndroid Build Coastguard Worker 	/* Seems legit... */
136*8617a60dSAndroid Build Coastguard Worker 	return 1;
137*8617a60dSAndroid Build Coastguard Worker }
138*8617a60dSAndroid Build Coastguard Worker 
139*8617a60dSAndroid Build Coastguard Worker /* For GBB v1.2 and later, print the stored digest of the HWID (and whether
140*8617a60dSAndroid Build Coastguard Worker  * it's correct). Return true if it is correct. */
print_hwid_digest(struct vb2_gbb_header * gbb,const char * banner)141*8617a60dSAndroid Build Coastguard Worker int print_hwid_digest(struct vb2_gbb_header *gbb, const char *banner)
142*8617a60dSAndroid Build Coastguard Worker {
143*8617a60dSAndroid Build Coastguard Worker 	FT_READABLE_PRINT("%s", banner);
144*8617a60dSAndroid Build Coastguard Worker 	FT_PARSEABLE_PRINT("hwid::digest::algorithm::2::SHA256\n");
145*8617a60dSAndroid Build Coastguard Worker 	FT_PARSEABLE_PRINT("hwid::digest::hex::");
146*8617a60dSAndroid Build Coastguard Worker 
147*8617a60dSAndroid Build Coastguard Worker 	/* There isn't one for v1.1 and earlier, so assume it's good. */
148*8617a60dSAndroid Build Coastguard Worker 	if (gbb->minor_version < 2) {
149*8617a60dSAndroid Build Coastguard Worker 		printf("<none>\n");
150*8617a60dSAndroid Build Coastguard Worker 		FT_PARSEABLE_PRINT("hwid::digest::ignored\n");
151*8617a60dSAndroid Build Coastguard Worker 		return 1;
152*8617a60dSAndroid Build Coastguard Worker 	}
153*8617a60dSAndroid Build Coastguard Worker 
154*8617a60dSAndroid Build Coastguard Worker 	uint8_t *buf = (uint8_t *)gbb;
155*8617a60dSAndroid Build Coastguard Worker 	char *hwid_str = (char *)(buf + gbb->hwid_offset);
156*8617a60dSAndroid Build Coastguard Worker 	int is_valid = 0;
157*8617a60dSAndroid Build Coastguard Worker 	struct vb2_hash hash;
158*8617a60dSAndroid Build Coastguard Worker 
159*8617a60dSAndroid Build Coastguard Worker 	if (VB2_SUCCESS == vb2_hash_calculate(false, buf + gbb->hwid_offset,
160*8617a60dSAndroid Build Coastguard Worker 					      strlen(hwid_str), VB2_HASH_SHA256,
161*8617a60dSAndroid Build Coastguard Worker 					      &hash)) {
162*8617a60dSAndroid Build Coastguard Worker 		int i;
163*8617a60dSAndroid Build Coastguard Worker 		is_valid = 1;
164*8617a60dSAndroid Build Coastguard Worker 		/* print it, comparing as we go */
165*8617a60dSAndroid Build Coastguard Worker 		for (i = 0; i < sizeof(hash.sha256); i++) {
166*8617a60dSAndroid Build Coastguard Worker 			printf("%02x", gbb->hwid_digest[i]);
167*8617a60dSAndroid Build Coastguard Worker 			if (gbb->hwid_digest[i] != hash.sha256[i])
168*8617a60dSAndroid Build Coastguard Worker 				is_valid = 0;
169*8617a60dSAndroid Build Coastguard Worker 		}
170*8617a60dSAndroid Build Coastguard Worker 	}
171*8617a60dSAndroid Build Coastguard Worker 
172*8617a60dSAndroid Build Coastguard Worker 	FT_PRINT_RAW("", "\n");
173*8617a60dSAndroid Build Coastguard Worker 	FT_PRINT("   %s\n", "hwid::digest::%s\n", is_valid ? "valid" : "invalid");
174*8617a60dSAndroid Build Coastguard Worker 	return is_valid;
175*8617a60dSAndroid Build Coastguard Worker }
176*8617a60dSAndroid Build Coastguard Worker 
177*8617a60dSAndroid Build Coastguard Worker /* Deprecated. Use futil_set_gbb_hwid in future. */
178*8617a60dSAndroid Build Coastguard Worker /* For GBB v1.2 and later, update the hwid_digest field. */
update_hwid_digest(struct vb2_gbb_header * gbb)179*8617a60dSAndroid Build Coastguard Worker void update_hwid_digest(struct vb2_gbb_header *gbb)
180*8617a60dSAndroid Build Coastguard Worker {
181*8617a60dSAndroid Build Coastguard Worker 	/* There isn't one for v1.1 and earlier */
182*8617a60dSAndroid Build Coastguard Worker 	if (gbb->minor_version < 2)
183*8617a60dSAndroid Build Coastguard Worker 		return;
184*8617a60dSAndroid Build Coastguard Worker 
185*8617a60dSAndroid Build Coastguard Worker 	uint8_t *buf = (uint8_t *)gbb;
186*8617a60dSAndroid Build Coastguard Worker 	char *hwid_str = (char *)(buf + gbb->hwid_offset);
187*8617a60dSAndroid Build Coastguard Worker 	struct vb2_hash hash;
188*8617a60dSAndroid Build Coastguard Worker 
189*8617a60dSAndroid Build Coastguard Worker 	vb2_hash_calculate(false, buf + gbb->hwid_offset, strlen(hwid_str),
190*8617a60dSAndroid Build Coastguard Worker 			   VB2_HASH_SHA256, &hash);
191*8617a60dSAndroid Build Coastguard Worker 	memcpy(gbb->hwid_digest, hash.raw, sizeof(gbb->hwid_digest));
192*8617a60dSAndroid Build Coastguard Worker }
193*8617a60dSAndroid Build Coastguard Worker 
194*8617a60dSAndroid Build Coastguard Worker /* Sets the HWID string field inside a GBB header. */
futil_set_gbb_hwid(struct vb2_gbb_header * gbb,const char * hwid)195*8617a60dSAndroid Build Coastguard Worker int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid)
196*8617a60dSAndroid Build Coastguard Worker {
197*8617a60dSAndroid Build Coastguard Worker 	uint8_t *to = (uint8_t *)gbb + gbb->hwid_offset;
198*8617a60dSAndroid Build Coastguard Worker 	struct vb2_hash hash;
199*8617a60dSAndroid Build Coastguard Worker 	size_t len;
200*8617a60dSAndroid Build Coastguard Worker 
201*8617a60dSAndroid Build Coastguard Worker 	assert(hwid);
202*8617a60dSAndroid Build Coastguard Worker 	len = strlen(hwid);
203*8617a60dSAndroid Build Coastguard Worker 	if (len >= gbb->hwid_size)
204*8617a60dSAndroid Build Coastguard Worker 		return -1;
205*8617a60dSAndroid Build Coastguard Worker 
206*8617a60dSAndroid Build Coastguard Worker 	/* Zero whole area so we won't have garbage after NUL. */
207*8617a60dSAndroid Build Coastguard Worker 	memset(to, 0, gbb->hwid_size);
208*8617a60dSAndroid Build Coastguard Worker 	memcpy(to, hwid, len);
209*8617a60dSAndroid Build Coastguard Worker 
210*8617a60dSAndroid Build Coastguard Worker 	/* major_version starts from 1 and digest must be updated since v1.2. */
211*8617a60dSAndroid Build Coastguard Worker 	if (gbb->major_version == 1 && gbb->minor_version < 2)
212*8617a60dSAndroid Build Coastguard Worker 		return 0;
213*8617a60dSAndroid Build Coastguard Worker 
214*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2_hash_calculate(false, to, len, VB2_HASH_SHA256, &hash));
215*8617a60dSAndroid Build Coastguard Worker 	memcpy(gbb->hwid_digest, hash.raw, sizeof(gbb->hwid_digest));
216*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
217*8617a60dSAndroid Build Coastguard Worker }
218*8617a60dSAndroid Build Coastguard Worker 
futil_copy_file(const char * infile,const char * outfile)219*8617a60dSAndroid Build Coastguard Worker int futil_copy_file(const char *infile, const char *outfile)
220*8617a60dSAndroid Build Coastguard Worker {
221*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("%s -> %s\n", infile, outfile);
222*8617a60dSAndroid Build Coastguard Worker 
223*8617a60dSAndroid Build Coastguard Worker 	int ifd, ofd;
224*8617a60dSAndroid Build Coastguard Worker 	if ((ifd = open(infile, O_RDONLY)) == -1) {
225*8617a60dSAndroid Build Coastguard Worker 		ERROR("Cannot open '%s', %s.\n", infile, strerror(errno));
226*8617a60dSAndroid Build Coastguard Worker 		return -1;
227*8617a60dSAndroid Build Coastguard Worker 	}
228*8617a60dSAndroid Build Coastguard Worker 	if ((ofd = creat(outfile, 0660)) == -1) {
229*8617a60dSAndroid Build Coastguard Worker 		ERROR("Cannot open '%s', %s.\n", outfile, strerror(errno));
230*8617a60dSAndroid Build Coastguard Worker 		close(ifd);
231*8617a60dSAndroid Build Coastguard Worker 		return -1;
232*8617a60dSAndroid Build Coastguard Worker 	}
233*8617a60dSAndroid Build Coastguard Worker 	struct stat finfo = {0};
234*8617a60dSAndroid Build Coastguard Worker 	if (fstat(ifd, &finfo) < 0) {
235*8617a60dSAndroid Build Coastguard Worker 		ERROR("Cannot fstat '%s' as %s.\n", infile, strerror(errno));
236*8617a60dSAndroid Build Coastguard Worker 		close (ifd);
237*8617a60dSAndroid Build Coastguard Worker 		close (ofd);
238*8617a60dSAndroid Build Coastguard Worker 		return -1;
239*8617a60dSAndroid Build Coastguard Worker 	}
240*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
241*8617a60dSAndroid Build Coastguard Worker 	ssize_t ret = sendfile(ofd, ifd, NULL, finfo.st_size);
242*8617a60dSAndroid Build Coastguard Worker #else
243*8617a60dSAndroid Build Coastguard Worker 	ssize_t ret = fcopyfile(ifd, ofd, 0, COPYFILE_ALL);
244*8617a60dSAndroid Build Coastguard Worker #endif
245*8617a60dSAndroid Build Coastguard Worker 	close(ifd);
246*8617a60dSAndroid Build Coastguard Worker 	close(ofd);
247*8617a60dSAndroid Build Coastguard Worker 	if (ret == -1) {
248*8617a60dSAndroid Build Coastguard Worker 		ERROR("Cannot copy '%s'->'%s', %s.\n", infile,
249*8617a60dSAndroid Build Coastguard Worker 		      outfile, strerror(errno));
250*8617a60dSAndroid Build Coastguard Worker 	}
251*8617a60dSAndroid Build Coastguard Worker 	return ret;
252*8617a60dSAndroid Build Coastguard Worker }
253*8617a60dSAndroid Build Coastguard Worker 
futil_open_file(const char * infile,int * fd,enum file_mode mode)254*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_open_file(const char *infile, int *fd,
255*8617a60dSAndroid Build Coastguard Worker 				    enum file_mode mode)
256*8617a60dSAndroid Build Coastguard Worker {
257*8617a60dSAndroid Build Coastguard Worker 	if (mode == FILE_RW) {
258*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("open RW %s\n", infile);
259*8617a60dSAndroid Build Coastguard Worker 		*fd = open(infile, O_RDWR);
260*8617a60dSAndroid Build Coastguard Worker 		if (*fd < 0) {
261*8617a60dSAndroid Build Coastguard Worker 			ERROR("Can't open %s for writing: %s\n", infile,
262*8617a60dSAndroid Build Coastguard Worker 			      strerror(errno));
263*8617a60dSAndroid Build Coastguard Worker 			return FILE_ERR_OPEN;
264*8617a60dSAndroid Build Coastguard Worker 		}
265*8617a60dSAndroid Build Coastguard Worker 	} else {
266*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("open RO %s\n", infile);
267*8617a60dSAndroid Build Coastguard Worker 		*fd = open(infile, O_RDONLY);
268*8617a60dSAndroid Build Coastguard Worker 		if (*fd < 0) {
269*8617a60dSAndroid Build Coastguard Worker 			ERROR("Can't open %s for reading: %s\n", infile,
270*8617a60dSAndroid Build Coastguard Worker 			      strerror(errno));
271*8617a60dSAndroid Build Coastguard Worker 			return FILE_ERR_OPEN;
272*8617a60dSAndroid Build Coastguard Worker 		}
273*8617a60dSAndroid Build Coastguard Worker 	}
274*8617a60dSAndroid Build Coastguard Worker 	return FILE_ERR_NONE;
275*8617a60dSAndroid Build Coastguard Worker }
276*8617a60dSAndroid Build Coastguard Worker 
futil_close_file(int fd)277*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_close_file(int fd)
278*8617a60dSAndroid Build Coastguard Worker {
279*8617a60dSAndroid Build Coastguard Worker 	if (fd >= 0 && close(fd)) {
280*8617a60dSAndroid Build Coastguard Worker 		ERROR("Closing ifd: %s\n", strerror(errno));
281*8617a60dSAndroid Build Coastguard Worker 		return FILE_ERR_CLOSE;
282*8617a60dSAndroid Build Coastguard Worker 	}
283*8617a60dSAndroid Build Coastguard Worker 	return FILE_ERR_NONE;
284*8617a60dSAndroid Build Coastguard Worker }
285*8617a60dSAndroid Build Coastguard Worker 
futil_map_file(int fd,enum file_mode mode,uint8_t ** buf,uint32_t * len)286*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_map_file(int fd, enum file_mode mode,
287*8617a60dSAndroid Build Coastguard Worker 				   uint8_t **buf, uint32_t *len)
288*8617a60dSAndroid Build Coastguard Worker {
289*8617a60dSAndroid Build Coastguard Worker 	struct stat sb;
290*8617a60dSAndroid Build Coastguard Worker 	void *mmap_ptr;
291*8617a60dSAndroid Build Coastguard Worker 	uint32_t reasonable_len;
292*8617a60dSAndroid Build Coastguard Worker 
293*8617a60dSAndroid Build Coastguard Worker 	if (0 != fstat(fd, &sb)) {
294*8617a60dSAndroid Build Coastguard Worker 		ERROR("Can't stat input file: %s\n", strerror(errno));
295*8617a60dSAndroid Build Coastguard Worker 		return FILE_ERR_STAT;
296*8617a60dSAndroid Build Coastguard Worker 	}
297*8617a60dSAndroid Build Coastguard Worker 
298*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
299*8617a60dSAndroid Build Coastguard Worker 	if (S_ISBLK(sb.st_mode))
300*8617a60dSAndroid Build Coastguard Worker 		ioctl(fd, BLKGETSIZE64, &sb.st_size);
301*8617a60dSAndroid Build Coastguard Worker #endif
302*8617a60dSAndroid Build Coastguard Worker 
303*8617a60dSAndroid Build Coastguard Worker 	/* If the image is larger than 2^32 bytes, it's wrong. */
304*8617a60dSAndroid Build Coastguard Worker 	if (sb.st_size < 0 || sb.st_size > UINT32_MAX) {
305*8617a60dSAndroid Build Coastguard Worker 		ERROR("Image size is unreasonable\n");
306*8617a60dSAndroid Build Coastguard Worker 		return FILE_ERR_SIZE;
307*8617a60dSAndroid Build Coastguard Worker 	}
308*8617a60dSAndroid Build Coastguard Worker 	reasonable_len = (uint32_t)sb.st_size;
309*8617a60dSAndroid Build Coastguard Worker 
310*8617a60dSAndroid Build Coastguard Worker 	if (mode == FILE_RW)
311*8617a60dSAndroid Build Coastguard Worker 		mmap_ptr = mmap(0, sb.st_size,
312*8617a60dSAndroid Build Coastguard Worker 				PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
313*8617a60dSAndroid Build Coastguard Worker 	else
314*8617a60dSAndroid Build Coastguard Worker 		mmap_ptr = mmap(0, sb.st_size,
315*8617a60dSAndroid Build Coastguard Worker 				PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
316*8617a60dSAndroid Build Coastguard Worker 
317*8617a60dSAndroid Build Coastguard Worker 	if (mmap_ptr == MAP_FAILED) {
318*8617a60dSAndroid Build Coastguard Worker 		ERROR("Can't mmap %s file: %s\n",
319*8617a60dSAndroid Build Coastguard Worker 		      mode == FILE_RW ? "output" : "input", strerror(errno));
320*8617a60dSAndroid Build Coastguard Worker 		return FILE_ERR_MMAP;
321*8617a60dSAndroid Build Coastguard Worker 	}
322*8617a60dSAndroid Build Coastguard Worker 
323*8617a60dSAndroid Build Coastguard Worker 	*buf = (uint8_t *)mmap_ptr;
324*8617a60dSAndroid Build Coastguard Worker 	*len = reasonable_len;
325*8617a60dSAndroid Build Coastguard Worker 	return FILE_ERR_NONE;
326*8617a60dSAndroid Build Coastguard Worker }
327*8617a60dSAndroid Build Coastguard Worker 
futil_unmap_file(int fd,enum file_mode mode,uint8_t * buf,uint32_t len)328*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_unmap_file(int fd, enum file_mode mode,
329*8617a60dSAndroid Build Coastguard Worker 				     uint8_t *buf, uint32_t len)
330*8617a60dSAndroid Build Coastguard Worker {
331*8617a60dSAndroid Build Coastguard Worker 	void *mmap_ptr = buf;
332*8617a60dSAndroid Build Coastguard Worker 	enum futil_file_err err = FILE_ERR_NONE;
333*8617a60dSAndroid Build Coastguard Worker 
334*8617a60dSAndroid Build Coastguard Worker 	if (mode == FILE_RW &&
335*8617a60dSAndroid Build Coastguard Worker 	    (0 != msync(mmap_ptr, len, MS_SYNC | MS_INVALIDATE))) {
336*8617a60dSAndroid Build Coastguard Worker 		ERROR("msync failed: %s\n", strerror(errno));
337*8617a60dSAndroid Build Coastguard Worker 		err = FILE_ERR_MSYNC;
338*8617a60dSAndroid Build Coastguard Worker 	}
339*8617a60dSAndroid Build Coastguard Worker 
340*8617a60dSAndroid Build Coastguard Worker 	if (0 != munmap(mmap_ptr, len)) {
341*8617a60dSAndroid Build Coastguard Worker 		ERROR("Can't munmap pointer: %s\n", strerror(errno));
342*8617a60dSAndroid Build Coastguard Worker 		if (err == FILE_ERR_NONE)
343*8617a60dSAndroid Build Coastguard Worker 			err = FILE_ERR_MUNMAP;
344*8617a60dSAndroid Build Coastguard Worker 	}
345*8617a60dSAndroid Build Coastguard Worker 
346*8617a60dSAndroid Build Coastguard Worker 	return err;
347*8617a60dSAndroid Build Coastguard Worker }
348*8617a60dSAndroid Build Coastguard Worker 
futil_open_and_map_file(const char * infile,int * fd,enum file_mode mode,uint8_t ** buf,uint32_t * len)349*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_open_and_map_file(const char *infile, int *fd,
350*8617a60dSAndroid Build Coastguard Worker 					    enum file_mode mode, uint8_t **buf,
351*8617a60dSAndroid Build Coastguard Worker 					    uint32_t *len)
352*8617a60dSAndroid Build Coastguard Worker {
353*8617a60dSAndroid Build Coastguard Worker 	enum futil_file_err rv = futil_open_file(infile, fd, mode);
354*8617a60dSAndroid Build Coastguard Worker 	if (rv != FILE_ERR_NONE)
355*8617a60dSAndroid Build Coastguard Worker 		return rv;
356*8617a60dSAndroid Build Coastguard Worker 
357*8617a60dSAndroid Build Coastguard Worker 	rv = futil_map_file(*fd, mode,  buf, len);
358*8617a60dSAndroid Build Coastguard Worker 	if (rv != FILE_ERR_NONE)
359*8617a60dSAndroid Build Coastguard Worker 		futil_close_file(*fd);
360*8617a60dSAndroid Build Coastguard Worker 
361*8617a60dSAndroid Build Coastguard Worker 	return rv;
362*8617a60dSAndroid Build Coastguard Worker }
363*8617a60dSAndroid Build Coastguard Worker 
futil_unmap_and_close_file(int fd,enum file_mode mode,uint8_t * buf,uint32_t len)364*8617a60dSAndroid Build Coastguard Worker enum futil_file_err futil_unmap_and_close_file(int fd, enum file_mode mode,
365*8617a60dSAndroid Build Coastguard Worker 					       uint8_t *buf, uint32_t len)
366*8617a60dSAndroid Build Coastguard Worker {
367*8617a60dSAndroid Build Coastguard Worker 	enum futil_file_err rv = FILE_ERR_NONE;
368*8617a60dSAndroid Build Coastguard Worker 
369*8617a60dSAndroid Build Coastguard Worker 	if (buf)
370*8617a60dSAndroid Build Coastguard Worker 		rv = futil_unmap_file(fd, mode, buf, len);
371*8617a60dSAndroid Build Coastguard Worker 	if (rv != FILE_ERR_NONE)
372*8617a60dSAndroid Build Coastguard Worker 		return rv;
373*8617a60dSAndroid Build Coastguard Worker 
374*8617a60dSAndroid Build Coastguard Worker 	if (fd != -1)
375*8617a60dSAndroid Build Coastguard Worker 		return futil_close_file(fd);
376*8617a60dSAndroid Build Coastguard Worker 	else
377*8617a60dSAndroid Build Coastguard Worker 		return FILE_ERR_NONE;
378*8617a60dSAndroid Build Coastguard Worker }
379*8617a60dSAndroid Build Coastguard Worker 
380*8617a60dSAndroid Build Coastguard Worker #define DISK_SECTOR_SIZE 512
ft_recognize_gpt(uint8_t * buf,uint32_t len)381*8617a60dSAndroid Build Coastguard Worker enum futil_file_type ft_recognize_gpt(uint8_t *buf, uint32_t len)
382*8617a60dSAndroid Build Coastguard Worker {
383*8617a60dSAndroid Build Coastguard Worker 	GptHeader *h;
384*8617a60dSAndroid Build Coastguard Worker 
385*8617a60dSAndroid Build Coastguard Worker 	/* GPT header starts at sector 1, is one sector long */
386*8617a60dSAndroid Build Coastguard Worker 	if (len < 2 * DISK_SECTOR_SIZE)
387*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
388*8617a60dSAndroid Build Coastguard Worker 
389*8617a60dSAndroid Build Coastguard Worker 	h = (GptHeader *)(buf + DISK_SECTOR_SIZE);
390*8617a60dSAndroid Build Coastguard Worker 
391*8617a60dSAndroid Build Coastguard Worker 	if (memcmp(h->signature, GPT_HEADER_SIGNATURE,
392*8617a60dSAndroid Build Coastguard Worker 		   GPT_HEADER_SIGNATURE_SIZE) &&
393*8617a60dSAndroid Build Coastguard Worker 	    memcmp(h->signature, GPT_HEADER_SIGNATURE2,
394*8617a60dSAndroid Build Coastguard Worker 		   GPT_HEADER_SIGNATURE_SIZE))
395*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
396*8617a60dSAndroid Build Coastguard Worker 	if (h->revision != GPT_HEADER_REVISION)
397*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
398*8617a60dSAndroid Build Coastguard Worker 	if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER)
399*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
400*8617a60dSAndroid Build Coastguard Worker 
401*8617a60dSAndroid Build Coastguard Worker 	if (HeaderCrc(h) != h->header_crc32)
402*8617a60dSAndroid Build Coastguard Worker 		return FILE_TYPE_UNKNOWN;
403*8617a60dSAndroid Build Coastguard Worker 
404*8617a60dSAndroid Build Coastguard Worker 	return FILE_TYPE_CHROMIUMOS_DISK;
405*8617a60dSAndroid Build Coastguard Worker }
406*8617a60dSAndroid Build Coastguard Worker 
parse_digest_or_die(uint8_t * buf,int len,const char * str)407*8617a60dSAndroid Build Coastguard Worker void parse_digest_or_die(uint8_t *buf, int len, const char *str)
408*8617a60dSAndroid Build Coastguard Worker {
409*8617a60dSAndroid Build Coastguard Worker 	if (!parse_hash(buf, len, str)) {
410*8617a60dSAndroid Build Coastguard Worker 		ERROR("Invalid DIGEST \"%s\"\n", str);
411*8617a60dSAndroid Build Coastguard Worker 		exit(1);
412*8617a60dSAndroid Build Coastguard Worker 	}
413*8617a60dSAndroid Build Coastguard Worker }
414*8617a60dSAndroid Build Coastguard Worker 
print_bytes(const void * ptr,size_t len)415*8617a60dSAndroid Build Coastguard Worker void print_bytes(const void *ptr, size_t len)
416*8617a60dSAndroid Build Coastguard Worker {
417*8617a60dSAndroid Build Coastguard Worker 	const uint8_t *buf = (const uint8_t *)ptr;
418*8617a60dSAndroid Build Coastguard Worker 
419*8617a60dSAndroid Build Coastguard Worker 	for (size_t i = 0; i < len; i++)
420*8617a60dSAndroid Build Coastguard Worker 		printf("%02x", *buf++);
421*8617a60dSAndroid Build Coastguard Worker }
422*8617a60dSAndroid Build Coastguard Worker 
write_to_file(const char * msg,const char * filename,uint8_t * start,size_t size)423*8617a60dSAndroid Build Coastguard Worker int write_to_file(const char *msg, const char *filename, uint8_t *start,
424*8617a60dSAndroid Build Coastguard Worker 		  size_t size)
425*8617a60dSAndroid Build Coastguard Worker {
426*8617a60dSAndroid Build Coastguard Worker 	FILE *fp;
427*8617a60dSAndroid Build Coastguard Worker 	int r = 0;
428*8617a60dSAndroid Build Coastguard Worker 
429*8617a60dSAndroid Build Coastguard Worker 	fp = fopen(filename, "wb");
430*8617a60dSAndroid Build Coastguard Worker 	if (!fp) {
431*8617a60dSAndroid Build Coastguard Worker 		r = errno;
432*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to open %s for writing: %s\n", filename,
433*8617a60dSAndroid Build Coastguard Worker 		      strerror(r));
434*8617a60dSAndroid Build Coastguard Worker 		return r;
435*8617a60dSAndroid Build Coastguard Worker 	}
436*8617a60dSAndroid Build Coastguard Worker 
437*8617a60dSAndroid Build Coastguard Worker 	/* Don't write zero bytes */
438*8617a60dSAndroid Build Coastguard Worker 	if (size && 1 != fwrite(start, size, 1, fp)) {
439*8617a60dSAndroid Build Coastguard Worker 		r = errno;
440*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to write to %s: %s\n", filename, strerror(r));
441*8617a60dSAndroid Build Coastguard Worker 	}
442*8617a60dSAndroid Build Coastguard Worker 
443*8617a60dSAndroid Build Coastguard Worker 	if (fclose(fp) != 0) {
444*8617a60dSAndroid Build Coastguard Worker 		int e = errno;
445*8617a60dSAndroid Build Coastguard Worker 		ERROR("Unable to close %s: %s\n", filename, strerror(e));
446*8617a60dSAndroid Build Coastguard Worker 		if (!r)
447*8617a60dSAndroid Build Coastguard Worker 			r = e;
448*8617a60dSAndroid Build Coastguard Worker 	}
449*8617a60dSAndroid Build Coastguard Worker 
450*8617a60dSAndroid Build Coastguard Worker 	if (!r && msg)
451*8617a60dSAndroid Build Coastguard Worker 		printf("%s %s\n", msg, filename);
452*8617a60dSAndroid Build Coastguard Worker 
453*8617a60dSAndroid Build Coastguard Worker 	return r;
454*8617a60dSAndroid Build Coastguard Worker }
455