diff options
author | Bill Richardson <wfrichar@chromium.org> | 2015-01-30 12:22:28 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-01-31 05:42:48 +0000 |
commit | 2559338dbdacbcbd3ae426337403196135bbc7e8 (patch) | |
tree | fb87c9b5b7058e14349f16cac2dc81966942ea87 /futility | |
parent | 65ce99b3e2c75bbb416b6edf78b5ea0d7f8c3a94 (diff) | |
download | vboot-2559338dbdacbcbd3ae426337403196135bbc7e8.tar.gz |
futility: refactor file type detection into new files
This moves the what-kind-of-file-is-this logic into a separate
file, and makes it work by calling distinct recognizers until one
hits. A new "-t" option to the show command prints what it's
doing.
BUG=chromium:228932
BRANCH=ToT
TEST=make runtests
Change-Id: Id8f60bdf3fe6a9adf41b4555b3448a261fa52fea
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/245122
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'futility')
-rw-r--r-- | futility/cmd_show.c | 44 | ||||
-rw-r--r-- | futility/cmd_sign.c | 13 | ||||
-rw-r--r-- | futility/cmd_vbutil_kernel.c | 3 | ||||
-rw-r--r-- | futility/file_type.c | 123 | ||||
-rw-r--r-- | futility/file_type.h | 50 | ||||
-rw-r--r-- | futility/futility.h | 24 | ||||
-rw-r--r-- | futility/misc.c | 65 | ||||
-rw-r--r-- | futility/traversal.c | 148 | ||||
-rw-r--r-- | futility/traversal.h | 33 | ||||
-rw-r--r-- | futility/vb1_helper.c | 36 |
10 files changed, 355 insertions, 184 deletions
diff --git a/futility/cmd_show.c b/futility/cmd_show.c index 7f0e488f..c6584259 100644 --- a/futility/cmd_show.c +++ b/futility/cmd_show.c @@ -17,6 +17,7 @@ #include <unistd.h> #include "bmpblk_header.h" +#include "file_type.h" #include "fmap.h" #include "futility.h" #include "gbb_header.h" @@ -38,6 +39,7 @@ static struct local_data_s { uint64_t fv_size; uint32_t padding; int strict; + int t_flag; } option = { .padding = 65536, }; @@ -505,7 +507,7 @@ enum no_short_opts { }; static const char usage[] = "\n" - "Usage: " MYNAME " %s [OPTIONS] FILE\n" + "Usage: " MYNAME " %s [OPTIONS] FILE [...]\n" "\n" "Where FILE could be a\n" "\n" @@ -516,6 +518,7 @@ static const char usage[] = "\n" " kernel partition (/dev/sda2, /dev/mmcblk0p2)\n" "\n" "Options:\n" + " -t Just show the type of each file\n" " -k|--publickey FILE" " Use this public key for validation\n" " -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n" @@ -544,7 +547,34 @@ static const struct option long_opts[] = { {"debug", 0, &debugging_enabled, 1}, {NULL, 0, NULL, 0}, }; -static char *short_opts = ":f:k:"; +static char *short_opts = ":f:k:t"; + + +static void show_type(char *filename) +{ + enum futil_file_err err; + enum futil_file_type type; + err = futil_file_type(filename, &type); + switch (err) { + case FILE_ERR_NONE: + printf("%s:\t%s\n", filename, futil_file_type_str(type)); + break; + case FILE_ERR_DIR: + printf("%s:\t%s\n", filename, "directory"); + break; + case FILE_ERR_CHR: + printf("%s:\t%s\n", filename, "character special"); + break; + case FILE_ERR_FIFO: + printf("%s:\t%s\n", filename, "FIFO"); + break; + case FILE_ERR_SOCK: + printf("%s:\t%s\n", filename, "socket"); + break; + default: + break; + } +} static int do_show(int argc, char *argv[]) { @@ -574,6 +604,9 @@ static int do_show(int argc, char *argv[]) errorcnt++; } break; + case 't': + option.t_flag = 1; + break; case OPT_PADDING: option.padding = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { @@ -613,6 +646,12 @@ static int do_show(int argc, char *argv[]) return 1; } + if (option.t_flag) { + for (i = optind; i < argc; i++) + show_type(argv[i]); + goto done; + } + for (i = optind; i < argc; i++) { infile = argv[i]; ifd = open(infile, O_RDONLY); @@ -646,6 +685,7 @@ boo: } } +done: if (option.k) free(option.k); if (option.fv) diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index f256b00e..a960abd6 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -18,6 +18,7 @@ #include <unistd.h> #include "bmpblk_header.h" +#include "file_type.h" #include "fmap.h" #include "futility.h" #include "gbb_header.h" @@ -889,7 +890,10 @@ static int do_sign(int argc, char *argv[]) } /* What are we looking at? */ - type = futil_what_file_type(infile); + if (futil_file_type(infile, &type)) { + errorcnt++; + goto done; + } /* We may be able to infer the type based on the other args */ if (type == FILE_TYPE_UNKNOWN) { @@ -900,7 +904,7 @@ static int do_sign(int argc, char *argv[]) type = FILE_TYPE_RAW_FIRMWARE; } - Debug("type=%s\n", futil_file_type_str[type]); + Debug("type=%s\n", futil_file_type_str(type)); /* Check the arguments for the type of thing we want to sign */ switch (type) { @@ -972,6 +976,11 @@ static int do_sign(int argc, char *argv[]) errorcnt += no_opt_if(!option.config_data, "config"); errorcnt += no_opt_if(option.arch == ARCH_UNSPECIFIED, "arch"); break; + case FILE_TYPE_CHROMIUMOS_DISK: + fprintf(stderr, "Signing a %s is not yet supported\n", + futil_file_type_str(type)); + errorcnt++; + break; default: DIE; } diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c index 40deba9e..65a9af39 100644 --- a/futility/cmd_vbutil_kernel.c +++ b/futility/cmd_vbutil_kernel.c @@ -18,6 +18,7 @@ #include <sys/stat.h> #include <unistd.h> +#include "file_type.h" #include "futility.h" #include "host_common.h" #include "kernel_blob.h" @@ -464,7 +465,7 @@ static int do_vbutil_kernel(int argc, char *argv[]) /* Make sure we have a kernel partition */ if (FILE_TYPE_KERN_PREAMBLE != - futil_what_file_type_buf(kpart_data, kpart_size)) + futil_file_type_buf(kpart_data, kpart_size)) Fatal("%s is not a kernel blob\n", oldfile); kblob_data = UnpackKPart(kpart_data, kpart_size, opt_pad, diff --git a/futility/file_type.c b/futility/file_type.c new file mode 100644 index 00000000..0c915865 --- /dev/null +++ b/futility/file_type.c @@ -0,0 +1,123 @@ +/* + * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "file_type.h" +#include "futility.h" +#include "gbb_header.h" + +/* Human-readable strings */ +static const char * const type_strings[] = { + "unknown", + "VbPublicKey", + "VbKeyBlock", + "VbFirmwarePreamble", + "GBB", + "Chrome OS BIOS image", + "Cr-48 Chrome OS BIOS image", + "VbKernelPreamble", + "raw firmware", + "raw kernel", + "chromiumos disk image", +}; +BUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES); + +const char * const futil_file_type_str(enum futil_file_type type) +{ + if (type < 0 || type >= NUM_FILE_TYPES) + type = FILE_TYPE_UNKNOWN; + + return type_strings[type]; +} + +/* Try these in order so we recognize the larger objects first */ +enum futil_file_type (*recognizers[])(uint8_t *buf, uint32_t len) = { + &recognize_gpt, + &recognize_bios_image, + &recognize_gbb, + &recognize_vblock1, +}; + +/* Try to figure out what we're looking at */ +enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len) +{ + enum futil_file_type type; + int i; + + for (i = 0; i < ARRAY_SIZE(recognizers); i++) { + type = recognizers[i](buf, len); + if (type != FILE_TYPE_UNKNOWN) + return type; + } + + return FILE_TYPE_UNKNOWN; +} + +enum futil_file_err futil_file_type(const char *filename, + enum futil_file_type *type) +{ + int ifd; + uint8_t *buf; + uint32_t buf_len; + struct stat sb; + enum futil_file_err err = FILE_ERR_NONE; + + *type = FILE_TYPE_UNKNOWN; + + ifd = open(filename, O_RDONLY); + if (ifd < 0) { + fprintf(stderr, "Can't open %s: %s\n", + filename, strerror(errno)); + return FILE_ERR_OPEN; + } + + if (0 != fstat(ifd, &sb)) { + fprintf(stderr, "Can't stat input file: %s\n", + strerror(errno)); + return FILE_ERR_STAT; + } + + if (S_ISREG(sb.st_mode) || S_ISBLK(sb.st_mode)) { + err = futil_map_file(ifd, MAP_RO, &buf, &buf_len); + if (err) { + close(ifd); + return err; + } + + *type = futil_file_type_buf(buf, buf_len); + + err = futil_unmap_file(ifd, MAP_RO, buf, buf_len); + if (err) { + close(ifd); + return err; + } + } else if (S_ISDIR(sb.st_mode)) { + err = FILE_ERR_DIR; + } else if (S_ISCHR(sb.st_mode)) { + err = FILE_ERR_CHR; + } else if (S_ISFIFO(sb.st_mode)) { + err = FILE_ERR_FIFO; + } else if (S_ISSOCK(sb.st_mode)) { + err = FILE_ERR_SOCK; + } + + if (close(ifd)) { + fprintf(stderr, "Error when closing %s: %s\n", + filename, strerror(errno)); + return FILE_ERR_CLOSE; + } + + return err; +} diff --git a/futility/file_type.h b/futility/file_type.h new file mode 100644 index 00000000..f8aa97e7 --- /dev/null +++ b/futility/file_type.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_ +#define VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_ + +/* What type of things do I know how to handle? */ +enum futil_file_type { + FILE_TYPE_UNKNOWN, + FILE_TYPE_PUBKEY, /* VbPublicKey */ + FILE_TYPE_KEYBLOCK, /* VbKeyBlockHeader */ + FILE_TYPE_FW_PREAMBLE, /* VbFirmwarePreambleHeader */ + FILE_TYPE_GBB, /* GoogleBinaryBlockHeader */ + FILE_TYPE_BIOS_IMAGE, /* Chrome OS BIOS image */ + FILE_TYPE_OLD_BIOS_IMAGE, /* Old Chrome OS BIOS image */ + FILE_TYPE_KERN_PREAMBLE, /* VbKernelPreambleHeader */ + + /* These are FILE_TYPE_UNKNOWN, but we've been told more about them */ + FILE_TYPE_RAW_FIRMWARE, /* FW_MAIN_A, etc. */ + FILE_TYPE_RAW_KERNEL, /* vmlinuz, *.uimg, etc. */ + + FILE_TYPE_CHROMIUMOS_DISK, /* At least it has a GPT */ + + NUM_FILE_TYPES +}; + +/* Names for them */ +const char * const futil_file_type_str(enum futil_file_type type); + +/* + * This tries to match the buffer content to one of the known file types. + */ +enum futil_file_type futil_file_type_buf(uint8_t *buf, uint32_t len); + +/* + * This opens a file and tries to match it to one of the known file types. + * It's not an error if it returns FILE_TYPE_UKNOWN. + */ +enum futil_file_err futil_file_type(const char *filename, + enum futil_file_type *type); + +/* Routines to identify particular file types. */ +enum futil_file_type recognize_bios_image(uint8_t *buf, uint32_t len); +enum futil_file_type recognize_gbb(uint8_t *buf, uint32_t len); +enum futil_file_type recognize_vblock1(uint8_t *buf, uint32_t len); +enum futil_file_type recognize_gpt(uint8_t *buf, uint32_t len); + +#endif /* VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_ */ diff --git a/futility/futility.h b/futility/futility.h index 652b5fbc..5f9a5b78 100644 --- a/futility/futility.h +++ b/futility/futility.h @@ -85,11 +85,29 @@ int print_hwid_digest(GoogleBinaryBlockHeader *gbb, /* Copies a file or dies with an error message */ void futil_copy_file_or_die(const char *infile, const char *outfile); -/* Wrapper for mmap/munmap. Returns 0 on success. Skips stupidly large files. */ +/* Possible file operation errors */ +enum futil_file_err { + FILE_ERR_NONE, + FILE_ERR_STAT, + FILE_ERR_SIZE, + FILE_ERR_MMAP, + FILE_ERR_MSYNC, + FILE_ERR_MUNMAP, + FILE_ERR_OPEN, + FILE_ERR_CLOSE, + FILE_ERR_DIR, + FILE_ERR_CHR, + FILE_ERR_FIFO, + FILE_ERR_SOCK, +}; + +/* Wrapper for mmap/munmap. Skips stupidly large files. */ #define MAP_RO 0 #define MAP_RW 1 -int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len); -int futil_unmap_file(int fd, int writeable, uint8_t *buf, uint32_t len); +enum futil_file_err futil_map_file(int fd, int writeable, + uint8_t **buf, uint32_t *len); +enum futil_file_err futil_unmap_file(int fd, int writeable, + uint8_t *buf, uint32_t len); /* The CPU architecture is occasionally important */ enum arch_t { diff --git a/futility/misc.c b/futility/misc.c index 4d8d762e..183edcc2 100644 --- a/futility/misc.c +++ b/futility/misc.c @@ -18,6 +18,8 @@ #include <sys/wait.h> #include <unistd.h> +#include "cgptlib_internal.h" +#include "file_type.h" #include "futility.h" #include "gbb_header.h" @@ -49,17 +51,19 @@ static inline uint32_t max(uint32_t a, uint32_t b) return a > b ? a : b; } -int futil_looks_like_gbb(GoogleBinaryBlockHeader *gbb, uint32_t len) +enum futil_file_type recognize_gbb(uint8_t *buf, uint32_t len) { + GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf; + if (memcmp(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE)) - return 0; + return FILE_TYPE_UNKNOWN; if (gbb->major_version > GBB_MAJOR_VER) - return 0; + return FILE_TYPE_UNKNOWN; if (sizeof(GoogleBinaryBlockHeader) > len) - return 0; + return FILE_TYPE_UNKNOWN; /* close enough */ - return 1; + return FILE_TYPE_GBB; } int futil_valid_gbb_header(GoogleBinaryBlockHeader *gbb, uint32_t len, @@ -221,7 +225,8 @@ void futil_copy_file_or_die(const char *infile, const char *outfile) } -int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len) +enum futil_file_err futil_map_file(int fd, int writeable, + uint8_t **buf, uint32_t *len) { struct stat sb; void *mmap_ptr; @@ -230,7 +235,7 @@ int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len) if (0 != fstat(fd, &sb)) { fprintf(stderr, "Can't stat input file: %s\n", strerror(errno)); - return 1; + return FILE_ERR_STAT; } if (S_ISBLK(sb.st_mode)) @@ -239,7 +244,7 @@ int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len) /* If the image is larger than 2^32 bytes, it's wrong. */ if (sb.st_size < 0 || sb.st_size > UINT32_MAX) { fprintf(stderr, "Image size is unreasonable\n"); - return 1; + return FILE_ERR_SIZE; } reasonable_len = (uint32_t)sb.st_size; @@ -254,30 +259,60 @@ int futil_map_file(int fd, int writeable, uint8_t **buf, uint32_t *len) fprintf(stderr, "Can't mmap %s file: %s\n", writeable ? "output" : "input", strerror(errno)); - return 1; + return FILE_ERR_MMAP; } *buf = (uint8_t *)mmap_ptr; *len = reasonable_len; - return 0; + return FILE_ERR_NONE; } -int futil_unmap_file(int fd, int writeable, uint8_t *buf, uint32_t len) +enum futil_file_err futil_unmap_file(int fd, int writeable, + uint8_t *buf, uint32_t len) { void *mmap_ptr = buf; - int errorcnt = 0; + enum futil_file_err err = FILE_ERR_NONE; if (writeable && (0 != msync(mmap_ptr, len, MS_SYNC|MS_INVALIDATE))) { fprintf(stderr, "msync failed: %s\n", strerror(errno)); - errorcnt++; + err = FILE_ERR_MSYNC; } if (0 != munmap(mmap_ptr, len)) { fprintf(stderr, "Can't munmap pointer: %s\n", strerror(errno)); - errorcnt++; + if (err == FILE_ERR_NONE) + err = FILE_ERR_MUNMAP; } - return errorcnt; + return err; +} + + +#define DISK_SECTOR_SIZE 512 +enum futil_file_type recognize_gpt(uint8_t *buf, uint32_t len) +{ + GptHeader *h; + + /* GPT header starts at sector 1, is one sector long */ + if (len < 2 * DISK_SECTOR_SIZE) + return FILE_TYPE_UNKNOWN; + + h = (GptHeader *)(buf + DISK_SECTOR_SIZE); + + if (memcmp(h->signature, GPT_HEADER_SIGNATURE, + GPT_HEADER_SIGNATURE_SIZE) && + memcmp(h->signature, GPT_HEADER_SIGNATURE2, + GPT_HEADER_SIGNATURE_SIZE)) + return FILE_TYPE_UNKNOWN; + if (h->revision != GPT_HEADER_REVISION) + return FILE_TYPE_UNKNOWN; + if (h->size < MIN_SIZE_OF_HEADER || h->size > MAX_SIZE_OF_HEADER) + return FILE_TYPE_UNKNOWN; + + if (HeaderCrc(h) != h->header_crc32) + return FILE_TYPE_UNKNOWN; + + return FILE_TYPE_CHROMIUMOS_DISK; } diff --git a/futility/traversal.c b/futility/traversal.c index ef60fde2..aa9988a7 100644 --- a/futility/traversal.c +++ b/futility/traversal.c @@ -4,20 +4,12 @@ * found in the LICENSE file. */ -#include <errno.h> -#include <fcntl.h> #include <stdint.h> #include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> +#include "file_type.h" #include "fmap.h" #include "futility.h" -#include "gbb_header.h" -#include "host_common.h" -#include "host_key.h" #include "traversal.h" /* What functions do we invoke for a particular operation and component? */ @@ -84,6 +76,7 @@ static const struct { {CB_KERN_PREAMBLE, "Kernel Preamble"}, /* FILE_TYPE_KERN_PREAMBLE */ {CB_RAW_FIRMWARE, "raw firmware"}, /* FILE_TYPE_RAW_FIRMWARE */ {CB_RAW_KERNEL, "raw kernel"}, /* FILE_TYPE_RAW_KERNEL */ + {0, "chromiumos disk"}, /* FILE_TYPE_CHROMIUMOS_DISK */ }; BUILD_ASSERT(ARRAY_SIZE(direct_callback) == NUM_FILE_TYPES); @@ -116,7 +109,6 @@ static const struct bios_area_s old_bios_area[] = { {0, 0} }; - static int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap, const struct bios_area_s *area) { @@ -129,19 +121,17 @@ static int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap, return 1; } -const char * const futil_file_type_str[] = { - "FILE_TYPE_UNKNOWN", - "FILE_TYPE_PUBKEY", - "FILE_TYPE_KEYBLOCK", - "FILE_TYPE_FW_PREAMBLE", - "FILE_TYPE_GBB", - "FILE_TYPE_BIOS_IMAGE", - "FILE_TYPE_OLD_BIOS_IMAGE", - "FILE_TYPE_KERN_PREAMBLE", - "FILE_TYPE_RAW_FIRMWARE", - "FILE_TYPE_RAW_KERNEL", -}; -BUILD_ASSERT(ARRAY_SIZE(futil_file_type_str) == NUM_FILE_TYPES); +enum futil_file_type recognize_bios_image(uint8_t *buf, uint32_t len) +{ + FmapHeader *fmap = fmap_find(buf, len); + if (fmap) { + if (has_all_areas(buf, len, fmap, bios_area)) + return FILE_TYPE_BIOS_IMAGE; + if (has_all_areas(buf, len, fmap, old_bios_area)) + return FILE_TYPE_OLD_BIOS_IMAGE; + } + return FILE_TYPE_UNKNOWN; +} const char * const futil_cb_component_str[] = { "CB_BEGIN_TRAVERSAL", @@ -191,93 +181,6 @@ static int invoke_callback(struct futil_traverse_state_s *state, return 0; } -enum futil_file_type futil_what_file_type_buf(uint8_t *buf, uint32_t len) -{ - VbPublicKey *pubkey = (VbPublicKey *)buf; - VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; - GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf; - VbFirmwarePreambleHeader *fw_preamble; - VbKernelPreambleHeader *kern_preamble; - RSAPublicKey *rsa; - FmapHeader *fmap; - - /* - * Complex structs may begin with simpler structs first, so try them - * in reverse order. - */ - - fmap = fmap_find(buf, len); - if (fmap) { - if (has_all_areas(buf, len, fmap, bios_area)) - return FILE_TYPE_BIOS_IMAGE; - if (has_all_areas(buf, len, fmap, old_bios_area)) - return FILE_TYPE_OLD_BIOS_IMAGE; - } - - if (futil_looks_like_gbb(gbb, len)) - return FILE_TYPE_GBB; - - if (VBOOT_SUCCESS == KeyBlockVerify(key_block, len, NULL, 1)) { - rsa = PublicKeyToRSA(&key_block->data_key); - uint32_t more = key_block->key_block_size; - - /* and firmware preamble too? */ - fw_preamble = (VbFirmwarePreambleHeader *)(buf + more); - if (VBOOT_SUCCESS == - VerifyFirmwarePreamble(fw_preamble, len - more, rsa)) - return FILE_TYPE_FW_PREAMBLE; - - /* or maybe kernel preamble? */ - kern_preamble = (VbKernelPreambleHeader *)(buf + more); - if (VBOOT_SUCCESS == - VerifyKernelPreamble(kern_preamble, len - more, rsa)) - return FILE_TYPE_KERN_PREAMBLE; - - /* no, just keyblock */ - return FILE_TYPE_KEYBLOCK; - } - - if (PublicKeyLooksOkay(pubkey, len)) - return FILE_TYPE_PUBKEY; - - return FILE_TYPE_UNKNOWN; -} - -enum futil_file_type futil_what_file_type(const char *filename) -{ - enum futil_file_type type; - int ifd; - uint8_t *buf; - uint32_t buf_len; - - ifd = open(filename, O_RDONLY); - if (ifd < 0) { - fprintf(stderr, "Can't open %s: %s\n", - filename, strerror(errno)); - exit(1); - } - - if (0 != futil_map_file(ifd, MAP_RO, &buf, &buf_len)) { - close(ifd); - exit(1); - } - - type = futil_what_file_type_buf(buf, buf_len); - - if (0 != futil_unmap_file(ifd, MAP_RO, buf, buf_len)) { - close(ifd); - exit(1); - } - - if (close(ifd)) { - fprintf(stderr, "Error when closing %s: %s\n", - filename, strerror(errno)); - exit(1); - } - - return type; -} - int futil_traverse(uint8_t *buf, uint32_t len, struct futil_traverse_state_s *state, enum futil_file_type type) @@ -293,7 +196,7 @@ int futil_traverse(uint8_t *buf, uint32_t len, } if (type == FILE_TYPE_UNKNOWN) - type = futil_what_file_type_buf(buf, len); + type = futil_file_type_buf(buf, len); state->in_type = type; state->errors = retval; @@ -302,20 +205,6 @@ int futil_traverse(uint8_t *buf, uint32_t len, state->errors = retval; switch (type) { - case FILE_TYPE_PUBKEY: - case FILE_TYPE_KEYBLOCK: - case FILE_TYPE_FW_PREAMBLE: - case FILE_TYPE_GBB: - case FILE_TYPE_KERN_PREAMBLE: - case FILE_TYPE_RAW_FIRMWARE: - case FILE_TYPE_RAW_KERNEL: - retval |= invoke_callback(state, - direct_callback[type].component, - direct_callback[type].name, - 0, buf, len); - state->errors = retval; - break; - case FILE_TYPE_BIOS_IMAGE: /* We've already checked, so we know this will work. */ fmap = fmap_find(buf, len); @@ -349,9 +238,12 @@ int futil_traverse(uint8_t *buf, uint32_t len, break; default: - Debug("%s:%d unhandled type %s\n", __FILE__, __LINE__, - futil_file_type_str[type]); - retval = 1; + retval |= invoke_callback(state, + direct_callback[type].component, + direct_callback[type].name, + 0, buf, len); + state->errors = retval; + break; } retval |= invoke_callback(state, CB_END_TRAVERSAL, "<end>", diff --git a/futility/traversal.h b/futility/traversal.h index faf8d27c..e22b231e 100644 --- a/futility/traversal.h +++ b/futility/traversal.h @@ -8,27 +8,6 @@ #include <stdint.h> -/* What type of things do I know how to handle? */ -enum futil_file_type { - FILE_TYPE_UNKNOWN, - FILE_TYPE_PUBKEY, /* 1 VbPublicKey */ - FILE_TYPE_KEYBLOCK, /* 2 VbKeyBlockHeader */ - FILE_TYPE_FW_PREAMBLE, /* 3 VbFirmwarePreambleHeader */ - FILE_TYPE_GBB, /* 4 GoogleBinaryBlockHeader */ - FILE_TYPE_BIOS_IMAGE, /* 5 Chrome OS BIOS image */ - FILE_TYPE_OLD_BIOS_IMAGE, /* 6 Old Chrome OS BIOS image */ - FILE_TYPE_KERN_PREAMBLE, /* 7 VbKernelPreambleHeader */ - - /* These are FILE_TYPE_UNKNOWN, but we've been told more about them */ - FILE_TYPE_RAW_FIRMWARE, /* 8 FW_MAIN_A, etc. */ - FILE_TYPE_RAW_KERNEL, /* 9 vmlinuz, *.uimg, etc. */ - - NUM_FILE_TYPES -}; - -/* Names for them */ -extern const char * const futil_file_type_str[]; - /* What are we trying to accomplish? */ enum futil_op_type { FUTIL_OP_SHOW, @@ -91,18 +70,6 @@ struct futil_traverse_state_s { /* - * This tries to match the buffer content to one of the known file types. - */ -enum futil_file_type futil_what_file_type_buf(uint8_t *buf, uint32_t len); - -/* - * This opens a file and tries to match it to one of the known file types. It - * fails only if it can't open and scan the file. It's not an error if it - * returns FILE_TYPE_UKNOWN. - */ -enum futil_file_type futil_what_file_type(const char *filename); - -/* * Traverse the buffer using the provided state, which should be initialized * before calling. Returns nonzero (but no details) if there were any errors. */ diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c index dd219ef8..292a0f24 100644 --- a/futility/vb1_helper.c +++ b/futility/vb1_helper.c @@ -10,6 +10,7 @@ #include <string.h> #include <unistd.h> +#include "file_type.h" #include "futility.h" #include "host_common.h" #include "kernel_blob.h" @@ -701,3 +702,38 @@ uint8_t *CreateKernelBlob(uint8_t *vmlinuz_buf, uint64_t vmlinuz_size, *blob_size_ptr = g_kernel_blob_size; return g_kernel_blob_data; } + +enum futil_file_type recognize_vblock1(uint8_t *buf, uint32_t len) +{ + VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; + VbPublicKey *pubkey = (VbPublicKey *)buf; + VbFirmwarePreambleHeader *fw_preamble; + VbKernelPreambleHeader *kern_preamble; + RSAPublicKey *rsa; + + if (VBOOT_SUCCESS == KeyBlockVerify(key_block, len, NULL, 1)) { + rsa = PublicKeyToRSA(&key_block->data_key); + uint32_t more = key_block->key_block_size; + + /* and firmware preamble too? */ + fw_preamble = (VbFirmwarePreambleHeader *)(buf + more); + if (VBOOT_SUCCESS == + VerifyFirmwarePreamble(fw_preamble, len - more, rsa)) + return FILE_TYPE_FW_PREAMBLE; + + /* or maybe kernel preamble? */ + kern_preamble = (VbKernelPreambleHeader *)(buf + more); + if (VBOOT_SUCCESS == + VerifyKernelPreamble(kern_preamble, len - more, rsa)) + return FILE_TYPE_KERN_PREAMBLE; + + /* no, just keyblock */ + return FILE_TYPE_KEYBLOCK; + } + + /* Maybe just a VbPublicKey? */ + if (PublicKeyLooksOkay(pubkey, len)) + return FILE_TYPE_PUBKEY; + + return FILE_TYPE_UNKNOWN; +} |