blob: f3e7748e0418f32ea13b7f4dac58767626a6d743 [file] [log] [blame]
Joel Kitching9adf2aa2019-08-20 17:43:50 +08001/* Copyright 2014 The Chromium OS Authors. All rights reserved.
Bill Richardsoncf6e78d2014-08-27 15:50:25 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Hung-Te Lin859682a2019-01-15 18:07:23 +08006#include <assert.h>
Bill Richardson15dc6fc2014-09-02 14:45:44 -07007#include <errno.h>
Idwer Volleringb384db32021-05-10 21:15:45 +02008#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
Bill Richardsone192e7f2014-09-23 12:49:26 -07009#include <linux/fs.h> /* For BLKGETSIZE64 */
David Riley05987b12015-02-05 19:22:49 -080010#endif
Bill Richardsone192e7f2014-09-23 12:49:26 -070011#include <stdarg.h>
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070012#include <stdint.h>
Bill Richardson15dc6fc2014-09-02 14:45:44 -070013#include <stdio.h>
14#include <stdlib.h>
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070015#include <string.h>
Bill Richardsone192e7f2014-09-23 12:49:26 -070016#include <sys/ioctl.h>
Bill Richardson15dc6fc2014-09-02 14:45:44 -070017#include <sys/mman.h>
18#include <sys/stat.h>
19#include <sys/types.h>
20#include <sys/wait.h>
21#include <unistd.h>
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070022
Randall Spangler7c3ae422016-05-11 13:50:18 -070023#include "2common.h"
24#include "2sha.h"
Joel Kitchingffd42a82019-08-29 13:58:52 +080025#include "2sysincludes.h"
Bill Richardson25593382015-01-30 12:22:28 -080026#include "cgptlib_internal.h"
27#include "file_type.h"
Bill Richardsone192e7f2014-09-23 12:49:26 -070028#include "futility.h"
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070029
Bill Richardsonc8054ea2015-03-12 08:53:10 -070030/* Default is to support everything we can */
31enum vboot_version vboot_version = VBOOT_VERSION_ALL;
32
Bill Richardsone192e7f2014-09-23 12:49:26 -070033int debugging_enabled;
Julius Werner5160e692019-03-05 13:56:41 -080034void vb2ex_printf(const char *func, const char *format, ...)
Bill Richardsone192e7f2014-09-23 12:49:26 -070035{
36 if (!debugging_enabled)
37 return;
38
39 va_list ap;
40 va_start(ap, format);
Julius Werner88a47ff2019-05-08 13:33:20 -070041 fprintf(stderr, "DEBUG: %s: ", func);
42 vfprintf(stderr, format, ap);
Bill Richardsone192e7f2014-09-23 12:49:26 -070043 va_end(ap);
44}
45
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070046static int is_null_terminated(const char *s, int len)
47{
48 len--;
49 s += len;
50 while (len-- >= 0)
51 if (!*s--)
52 return 1;
53 return 0;
54}
55
56static inline uint32_t max(uint32_t a, uint32_t b)
57{
58 return a > b ? a : b;
59}
60
Bill Richardson35c69cc2015-03-26 15:31:54 -070061enum futil_file_type ft_recognize_gbb(uint8_t *buf, uint32_t len)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070062{
Joel Kitching27e3e9f2019-04-25 18:31:14 +080063 struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)buf;
Bill Richardson25593382015-01-30 12:22:28 -080064
Joel Kitching27e3e9f2019-04-25 18:31:14 +080065 if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE))
Bill Richardson25593382015-01-30 12:22:28 -080066 return FILE_TYPE_UNKNOWN;
Joel Kitching27e3e9f2019-04-25 18:31:14 +080067 if (gbb->major_version > VB2_GBB_MAJOR_VER)
Bill Richardson25593382015-01-30 12:22:28 -080068 return FILE_TYPE_UNKNOWN;
Joel Kitching27e3e9f2019-04-25 18:31:14 +080069 if (sizeof(struct vb2_gbb_header) > len)
Bill Richardson25593382015-01-30 12:22:28 -080070 return FILE_TYPE_UNKNOWN;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070071
72 /* close enough */
Bill Richardson25593382015-01-30 12:22:28 -080073 return FILE_TYPE_GBB;
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070074}
75
Joel Kitching27e3e9f2019-04-25 18:31:14 +080076int futil_valid_gbb_header(struct vb2_gbb_header *gbb, uint32_t len,
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070077 uint32_t *maxlen_ptr)
78{
Joel Kitching27e3e9f2019-04-25 18:31:14 +080079 if (len < sizeof(struct vb2_gbb_header))
Bill Richardson7ccd9ce2015-01-30 23:45:49 -080080 return 0;
81
Joel Kitching27e3e9f2019-04-25 18:31:14 +080082 if (memcmp(gbb->signature, VB2_GBB_SIGNATURE, VB2_GBB_SIGNATURE_SIZE))
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070083 return 0;
Joel Kitching27e3e9f2019-04-25 18:31:14 +080084 if (gbb->major_version != VB2_GBB_MAJOR_VER)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -070085 return 0;
86
87 /* Check limits first, to help identify problems */
88 if (maxlen_ptr) {
89 uint32_t maxlen = gbb->header_size;
90 maxlen = max(maxlen,
91 gbb->hwid_offset + gbb->hwid_size);
92 maxlen = max(maxlen,
93 gbb->rootkey_offset + gbb->rootkey_size);
94 maxlen = max(maxlen,
95 gbb->bmpfv_offset + gbb->bmpfv_size);
96 maxlen = max(maxlen,
97 gbb->recovery_key_offset + gbb->recovery_key_size);
98 *maxlen_ptr = maxlen;
99 }
100
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800101 if (gbb->header_size != EXPECTED_VB2_GBB_HEADER_SIZE ||
102 gbb->header_size > len)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700103 return 0;
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800104 if (gbb->hwid_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700105 return 0;
106 if (gbb->hwid_offset + gbb->hwid_size > len)
107 return 0;
108 if (gbb->hwid_size) {
109 const char *s = (const char *)
110 ((uint8_t *)gbb + gbb->hwid_offset);
111 if (!is_null_terminated(s, gbb->hwid_size))
112 return 0;
113 }
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800114 if (gbb->rootkey_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700115 return 0;
116 if (gbb->rootkey_offset + gbb->rootkey_size > len)
117 return 0;
118
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800119 if (gbb->bmpfv_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700120 return 0;
121 if (gbb->bmpfv_offset + gbb->bmpfv_size > len)
122 return 0;
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800123 if (gbb->recovery_key_offset < EXPECTED_VB2_GBB_HEADER_SIZE)
Bill Richardsoncf6e78d2014-08-27 15:50:25 -0700124 return 0;
125 if (gbb->recovery_key_offset + gbb->recovery_key_size > len)
126 return 0;
127
128 /* Seems legit... */
129 return 1;
130}
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700131
Bill Richardson6df3e332014-10-02 18:50:33 -0700132/* For GBB v1.2 and later, print the stored digest of the HWID (and whether
133 * it's correct). Return true if it is correct. */
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800134int print_hwid_digest(struct vb2_gbb_header *gbb,
Bill Richardson6df3e332014-10-02 18:50:33 -0700135 const char *banner, const char *footer)
136{
137 printf("%s", banner);
138
139 /* There isn't one for v1.1 and earlier, so assume it's good. */
140 if (gbb->minor_version < 2) {
141 printf("<none>%s", footer);
142 return 1;
143 }
144
145 uint8_t *buf = (uint8_t *)gbb;
146 char *hwid_str = (char *)(buf + gbb->hwid_offset);
147 int is_valid = 0;
Randall Spangler7c3ae422016-05-11 13:50:18 -0700148 uint8_t digest[VB2_SHA256_DIGEST_SIZE];
149
150 if (VB2_SUCCESS == vb2_digest_buffer(buf + gbb->hwid_offset,
151 strlen(hwid_str), VB2_HASH_SHA256,
152 digest, sizeof(digest))) {
Bill Richardson6df3e332014-10-02 18:50:33 -0700153 int i;
154 is_valid = 1;
155 /* print it, comparing as we go */
Randall Spangler7c3ae422016-05-11 13:50:18 -0700156 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++) {
Bill Richardson6df3e332014-10-02 18:50:33 -0700157 printf("%02x", gbb->hwid_digest[i]);
158 if (gbb->hwid_digest[i] != digest[i])
159 is_valid = 0;
160 }
Bill Richardson6df3e332014-10-02 18:50:33 -0700161 }
162
163 printf(" %s", is_valid ? "valid" : "<invalid>");
164 printf("%s", footer);
165 return is_valid;
166}
167
Hung-Te Lin859682a2019-01-15 18:07:23 +0800168/* Deprecated. Use futil_set_gbb_hwid in future. */
Bill Richardson6df3e332014-10-02 18:50:33 -0700169/* For GBB v1.2 and later, update the hwid_digest field. */
Joel Kitching27e3e9f2019-04-25 18:31:14 +0800170void update_hwid_digest(struct vb2_gbb_header *gbb)
Bill Richardson6df3e332014-10-02 18:50:33 -0700171{
172 /* There isn't one for v1.1 and earlier */
173 if (gbb->minor_version < 2)
174 return;
175
176 uint8_t *buf = (uint8_t *)gbb;
177 char *hwid_str = (char *)(buf + gbb->hwid_offset);
Randall Spangler7c3ae422016-05-11 13:50:18 -0700178
179 vb2_digest_buffer(buf + gbb->hwid_offset, strlen(hwid_str),
180 VB2_HASH_SHA256,
181 gbb->hwid_digest, sizeof(gbb->hwid_digest));
Bill Richardson6df3e332014-10-02 18:50:33 -0700182}
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700183
Hung-Te Lin859682a2019-01-15 18:07:23 +0800184/* Sets the HWID string field inside a GBB header. */
185int futil_set_gbb_hwid(struct vb2_gbb_header *gbb, const char *hwid)
186{
187 uint8_t *to = (uint8_t *)gbb + gbb->hwid_offset;
188 size_t len;
189
190 assert(hwid);
191 len = strlen(hwid);
192 if (len >= gbb->hwid_size)
193 return -1;
194
195 /* Zero whole area so we won't have garbage after NUL. */
196 memset(to, 0, gbb->hwid_size);
197 memcpy(to, hwid, len);
198
199 /* major_version starts from 1 and digest must be updated since v1.2. */
200 if (gbb->major_version == 1 && gbb->minor_version < 2)
201 return 0;
202
203 return vb2_digest_buffer(to, len, VB2_HASH_SHA256, gbb->hwid_digest,
204 sizeof(gbb->hwid_digest));
205}
206
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700207/*
208 * TODO: All sorts of race conditions likely here, and everywhere this is used.
209 * Do we care? If so, fix it.
210 */
Bill Richardsone192e7f2014-09-23 12:49:26 -0700211void futil_copy_file_or_die(const char *infile, const char *outfile)
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700212{
213 pid_t pid;
214 int status;
215
Julius Werner5160e692019-03-05 13:56:41 -0800216 VB2_DEBUG("%s -> %s\n", infile, outfile);
Bill Richardsonb406c102014-12-03 14:10:13 -0800217
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700218 pid = fork();
219
220 if (pid < 0) {
221 fprintf(stderr, "Couldn't fork /bin/cp process: %s\n",
222 strerror(errno));
223 exit(1);
224 }
225
226 /* child */
227 if (!pid) {
228 execl("/bin/cp", "/bin/cp", infile, outfile, NULL);
229 fprintf(stderr, "Child couldn't exec /bin/cp: %s\n",
230 strerror(errno));
231 exit(1);
232 }
233
234 /* parent - wait for child to finish */
235 if (wait(&status) == -1) {
236 fprintf(stderr,
237 "Couldn't wait for /bin/cp process to exit: %s\n",
238 strerror(errno));
239 exit(1);
240 }
241
242 if (WIFEXITED(status)) {
243 status = WEXITSTATUS(status);
244 /* zero is normal exit */
245 if (!status)
246 return;
247 fprintf(stderr, "/bin/cp exited with status %d\n", status);
248 exit(1);
249 }
250
Bill Richardson779796f2014-09-23 11:47:40 -0700251 if (WIFSIGNALED(status)) {
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700252 status = WTERMSIG(status);
253 fprintf(stderr, "/bin/cp was killed with signal %d\n", status);
254 exit(1);
255 }
256
257 fprintf(stderr, "I have no idea what just happened\n");
258 exit(1);
259}
260
261
Bill Richardson25593382015-01-30 12:22:28 -0800262enum futil_file_err futil_map_file(int fd, int writeable,
263 uint8_t **buf, uint32_t *len)
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700264{
265 struct stat sb;
266 void *mmap_ptr;
267 uint32_t reasonable_len;
268
269 if (0 != fstat(fd, &sb)) {
270 fprintf(stderr, "Can't stat input file: %s\n",
271 strerror(errno));
Bill Richardson25593382015-01-30 12:22:28 -0800272 return FILE_ERR_STAT;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700273 }
274
Idwer Volleringb384db32021-05-10 21:15:45 +0200275#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
Bill Richardsone192e7f2014-09-23 12:49:26 -0700276 if (S_ISBLK(sb.st_mode))
277 ioctl(fd, BLKGETSIZE64, &sb.st_size);
David Riley05987b12015-02-05 19:22:49 -0800278#endif
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700279
280 /* If the image is larger than 2^32 bytes, it's wrong. */
281 if (sb.st_size < 0 || sb.st_size > UINT32_MAX) {
282 fprintf(stderr, "Image size is unreasonable\n");
Bill Richardson25593382015-01-30 12:22:28 -0800283 return FILE_ERR_SIZE;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700284 }
285 reasonable_len = (uint32_t)sb.st_size;
286
287 if (writeable)
288 mmap_ptr = mmap(0, sb.st_size,
289 PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
290 else
291 mmap_ptr = mmap(0, sb.st_size,
Bill Richardsone192e7f2014-09-23 12:49:26 -0700292 PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700293
294 if (mmap_ptr == (void *)-1) {
295 fprintf(stderr, "Can't mmap %s file: %s\n",
296 writeable ? "output" : "input",
297 strerror(errno));
Bill Richardson25593382015-01-30 12:22:28 -0800298 return FILE_ERR_MMAP;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700299 }
300
Bill Richardsone192e7f2014-09-23 12:49:26 -0700301 *buf = (uint8_t *)mmap_ptr;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700302 *len = reasonable_len;
Bill Richardson25593382015-01-30 12:22:28 -0800303 return FILE_ERR_NONE;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700304}
305
Bill Richardson25593382015-01-30 12:22:28 -0800306enum futil_file_err futil_unmap_file(int fd, int writeable,
307 uint8_t *buf, uint32_t len)
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700308{
Bill Richardsone192e7f2014-09-23 12:49:26 -0700309 void *mmap_ptr = buf;
Bill Richardson25593382015-01-30 12:22:28 -0800310 enum futil_file_err err = FILE_ERR_NONE;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700311
312 if (writeable &&
Bill Richardsone192e7f2014-09-23 12:49:26 -0700313 (0 != msync(mmap_ptr, len, MS_SYNC|MS_INVALIDATE))) {
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700314 fprintf(stderr, "msync failed: %s\n", strerror(errno));
Bill Richardson25593382015-01-30 12:22:28 -0800315 err = FILE_ERR_MSYNC;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700316 }
317
Bill Richardsone192e7f2014-09-23 12:49:26 -0700318 if (0 != munmap(mmap_ptr, len)) {
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700319 fprintf(stderr, "Can't munmap pointer: %s\n",
320 strerror(errno));
Bill Richardson25593382015-01-30 12:22:28 -0800321 if (err == FILE_ERR_NONE)
322 err = FILE_ERR_MUNMAP;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700323 }
324
Bill Richardson25593382015-01-30 12:22:28 -0800325 return err;
326}
327
328
329#define DISK_SECTOR_SIZE 512
Bill Richardson35c69cc2015-03-26 15:31:54 -0700330enum futil_file_type ft_recognize_gpt(uint8_t *buf, uint32_t len)
Bill Richardson25593382015-01-30 12:22:28 -0800331{
332 GptHeader *h;
333
334 /* GPT header starts at sector 1, is one sector long */
335 if (len < 2 * DISK_SECTOR_SIZE)
336 return FILE_TYPE_UNKNOWN;
337
338 h = (GptHeader *)(buf + DISK_SECTOR_SIZE);
339
340 if (memcmp(h->signature, GPT_HEADER_SIGNATURE,
341 GPT_HEADER_SIGNATURE_SIZE) &&
342 memcmp(h->signature, GPT_HEADER_SIGNATURE2,
343 GPT_HEADER_SIGNATURE_SIZE))
344 return FILE_TYPE_UNKNOWN;
345 if (h->revision != GPT_HEADER_REVISION)
346 return FILE_TYPE_UNKNOWN;
347 if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER)
348 return FILE_TYPE_UNKNOWN;
349
350 if (HeaderCrc(h) != h->header_crc32)
351 return FILE_TYPE_UNKNOWN;
352
353 return FILE_TYPE_CHROMIUMOS_DISK;
Bill Richardson15dc6fc2014-09-02 14:45:44 -0700354}