diff options
-rw-r--r-- | host/include/host_misc.h | 2 | ||||
-rw-r--r-- | host/lib/host_misc.c | 10 | ||||
-rw-r--r-- | utility/Makefile | 12 | ||||
-rwxr-xr-x | utility/dev_debug_vboot | 67 | ||||
-rw-r--r-- | utility/dump_fmap.c | 192 | ||||
-rw-r--r-- | utility/vbutil_firmware.c | 36 | ||||
-rw-r--r-- | utility/vbutil_kernel.c | 14 | ||||
-rw-r--r-- | utility/vbutil_key.c | 13 | ||||
-rw-r--r-- | utility/vbutil_keyblock.c | 12 |
9 files changed, 337 insertions, 21 deletions
diff --git a/host/include/host_misc.h b/host/include/host_misc.h index abbfc0f6..cbf9eaff 100644 --- a/host/include/host_misc.h +++ b/host/include/host_misc.h @@ -24,5 +24,7 @@ uint8_t* ReadFile(const char* filename, uint64_t* size); * Returns 0 if success, 1 if error. */ int WriteFile(const char* filename, const void *data, uint64_t size); +/* Prints the sha1sum of the given VbPublicKey to stdout. */ +void PrintPubKeySha1Sum(VbPublicKey* key); #endif /* VBOOT_REFERENCE_HOST_MISC_H_ */ diff --git a/host/lib/host_misc.c b/host/lib/host_misc.c index d8f52970..91eaea25 100644 --- a/host/lib/host_misc.c +++ b/host/lib/host_misc.c @@ -66,3 +66,13 @@ int WriteFile(const char* filename, const void *data, uint64_t size) { fclose(f); return 0; } + +void PrintPubKeySha1Sum(VbPublicKey* key) { + uint8_t* buf = ((uint8_t *)key) + key->key_offset; + uint64_t buflen = key->key_size; + uint8_t* digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM); + int i; + for (i=0; i<SHA1_DIGEST_SIZE; i++) + printf("%02x", digest[i]); + Free(digest); +} diff --git a/utility/Makefile b/utility/Makefile index 745cc9c9..516e91a4 100644 --- a/utility/Makefile +++ b/utility/Makefile @@ -31,7 +31,9 @@ TARGET_NAMES = dumpRSAPublicKey \ vbutil_keyblock \ verify_data \ dev_make_keypair \ - dev_sign_file + dev_sign_file \ + dump_fmap \ + dev_debug_vboot TARGET_BINS = $(addprefix ${BUILD_ROOT}/,$(TARGET_NAMES)) ALL_DEPS = $(addsuffix .d,${TARGET_BINS}) @@ -79,6 +81,11 @@ ${BUILD_ROOT}/tpm_init_temp_fix: tpm_init_temp_fix.c $(LIBS) ${BUILD_ROOT}/dev_make_keypair: dev_make_keypair cp -f $< $@ + chmod +x $@ + +${BUILD_ROOT}/dev_debug_vboot: dev_debug_vboot + cp -f $< $@ + chmod +x $@ ${BUILD_ROOT}/tpmc: tpmc.c $(LIBS) $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) @@ -86,6 +93,9 @@ ${BUILD_ROOT}/tpmc: tpmc.c $(LIBS) ${BUILD_ROOT}/dev_sign_file: dev_sign_file.c $(LIBS) $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ $(LIBS) -lcrypto +${BUILD_ROOT}/dump_fmap: dump_fmap.c + $(CC) $(CFLAGS) $< -o $@ + install: $(TARGET_BINS) mkdir -p $(DESTDIR) cp -f $(TARGET_BINS) $(DESTDIR) diff --git a/utility/dev_debug_vboot b/utility/dev_debug_vboot new file mode 100755 index 00000000..424e9e41 --- /dev/null +++ b/utility/dev_debug_vboot @@ -0,0 +1,67 @@ +#!/bin/sh +# Copyright (c) 2010 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. +# + +TMPDIR=/tmp/debug_vboot +BIOS=bios.rom +# FIXME: support ARM +HD_KERN_A=/dev/sda2 +HD_KERN_B=/dev/sda4 +tmp=$(rootdev -s -d)2 +if [ "$tmp" != "$HD_KERN_A" ]; then + USB_KERN_A="$tmp" +fi + + +[ -d ${TMPDIR} ] || mkdir -p ${TMPDIR} +cd ${TMPDIR} + +echo "INFO: extracting BIOS image from flash" +flashrom -r ${BIOS} + +echo "INFO: extracting kernel images from drives" +dd if=${HD_KERN_A} of=hd_kern_a.blob +dd if=${HD_KERN_B} of=hd_kern_b.blob +if [ -n "$USB_KERN_A" ]; then + dd if=${USB_KERN_A} of=usb_kern_a.blob +fi + +echo "INFO: extracting BIOS components" +dump_fmap -x ${BIOS} || echo "FAILED" + +echo "INFO: pulling root and recovery keys from GBB" +gbb_utility -g --rootkey rootkey.vbpubk --recoverykey recoverykey.vbpubk \ + GBB_Area || echo "FAILED" +echo "INFO: display root key" +vbutil_key --unpack rootkey.vbpubk +echo "INFO: display recovery key" +vbutil_key --unpack recoverykey.vbpubk + +echo "TEST: verify firmware A with root key" +vbutil_firmware --verify Firmware_A_Key --signpubkey rootkey.vbpubk \ + --fv Firmware_A_Data --kernelkey kernel_subkey_a.vbpubk || echo "FAILED" +echo "TEST: verify firmware B with root key" +vbutil_firmware --verify Firmware_B_Key --signpubkey rootkey.vbpubk \ + --fv Firmware_B_Data --kernelkey kernel_subkey_b.vbpubk || echo "FAILED" + +echo "TEST: verify HD kernel A with firmware A key" +vbutil_kernel --verify hd_kern_a.blob --signpubkey kernel_subkey_a.vbpubk \ + || echo "FAILED" +echo "TEST: verify HD kernel B with firmware A key" +vbutil_kernel --verify hd_kern_b.blob --signpubkey kernel_subkey_a.vbpubk \ + || echo "FAILED" + +echo "TEST: verify HD kernel A with firmware B key" +vbutil_kernel --verify hd_kern_a.blob --signpubkey kernel_subkey_b.vbpubk \ + || echo "FAILED" +echo "TEST: verify HD kernel B with firmware B key" +vbutil_kernel --verify hd_kern_b.blob --signpubkey kernel_subkey_b.vbpubk \ + || echo "FAILED" + +if [ -n "$USB_KERN_A" ]; then + echo "TEST: verify USB kernel A with recovery key" + vbutil_kernel --verify usb_kern_a.blob --signpubkey recoverykey.vbpubk \ + || echo "FAILED" +fi diff --git a/utility/dump_fmap.c b/utility/dump_fmap.c new file mode 100644 index 00000000..a0d24de4 --- /dev/null +++ b/utility/dump_fmap.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2010 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 <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +/* global variables */ +static int opt_extract = 0; +static char *progname; +static void *base_of_rom; + +/* FMAP structs. See http://code.google.com/p/flashmap/wiki/FmapSpec */ +#define FMAP_SIGLEN 8 +#define FMAP_NAMELEN 32 +#define FMAP_SEARCH_STRIDE 4 +typedef struct _FmapHeader { + char fmap_signature[FMAP_SIGLEN]; /* avoiding endian issues */ + uint8_t fmap_ver_major; + uint8_t fmap_ver_minor; + uint64_t fmap_base; + uint32_t fmap_size; + char fmap_name[FMAP_NAMELEN]; + uint16_t fmap_nareas; +} __attribute__((packed)) FmapHeader; + +typedef struct _AreaHeader { + uint32_t area_offset; + uint32_t area_size; + char area_name[FMAP_NAMELEN]; + uint16_t area_flags; +} __attribute__((packed)) AreaHeader; + + +/* Return 0 if successful */ +static int dump_fmap(void *ptr) { + int i,retval = 0; + char buf[80]; // DWR: magic number + FmapHeader *fmh = (FmapHeader *)ptr; + AreaHeader *ah = (AreaHeader *)(ptr + sizeof(FmapHeader)); + + snprintf(buf, FMAP_SIGLEN+1, "%s", fmh->fmap_signature); + printf("fmap_signature %s\n", buf); + printf("fmap_version: %d.%d\n", fmh->fmap_ver_major, fmh->fmap_ver_minor); + printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base); + printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size, fmh->fmap_size); + snprintf(buf, FMAP_NAMELEN+1, "%s", fmh->fmap_name); + printf("fmap_name: %s\n", buf); + printf("fmap_nareas: %d\n", fmh->fmap_nareas); + + for (i=0; i<fmh->fmap_nareas; i++) { + printf("area: %d\n", i+1); + printf("area_offset: 0x%08x\n", ah->area_offset); + printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size); + snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name); + printf("area_name: %s\n", buf); + + if (opt_extract) { + char *s; + for (s=buf; *s; s++) + if (*s == ' ') + *s = '_'; + FILE *fp = fopen(buf,"wb"); + if (!fp) { + fprintf(stderr, "%s: can't open %s: %s\n", + progname, buf, strerror(errno)); + retval = 1; + } else { + if (1 != fwrite(base_of_rom + ah->area_offset, ah->area_size, 1, fp)) { + fprintf(stderr, "%s: can't write %s: %s\n", + progname, buf, strerror(errno)); + retval = 1; + } else { + printf("saved as \"%s\"\n", buf); + } + fclose(fp); + } + } + + ah++; + } + + return retval; +} + + +int main(int argc, char *argv[]) { + int c; + int errorcnt = 0; + struct stat sb; + int fd; + char *s; + size_t i; + int retval = 1; + + progname = strrchr(argv[0], '/'); + if (progname) + progname++; + else + progname = argv[0]; + + opterr = 0; /* quiet, you */ + while ((c=getopt(argc, argv, ":x")) != -1) { + switch (c) + { + case 'x': + opt_extract = 1; + break; + case '?': + fprintf(stderr, "%s: unrecognized switch: -%c\n", + progname, optopt); + errorcnt++; + break; + case ':': + fprintf(stderr, "%s: missing argument to -%c\n", + progname, optopt); + errorcnt++; + break; + default: + errorcnt++; + break; + } + } + + if (errorcnt || optind >= argc) { + fprintf(stderr, + "\nUsage: %s [-x] FLASHIMAGE\n\n" + "Display (and extract with -x) the FMAP components from a BIOS image" + "\n\n", + progname); + return 1; + } + + if (0 != stat(argv[optind], &sb)) { + fprintf(stderr, "%s: can't stat %s: %s\n", + progname, + argv[optind], + strerror(errno)); + return 1; + } + + fd = open(argv[optind], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "%s: can't open %s: %s\n", + progname, + argv[optind], + strerror(errno)); + return 1; + } + printf("opened %s\n", argv[optind]); + + base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (base_of_rom == (char *)-1) { + fprintf(stderr, "%s: can't mmap %s: %s\n", + progname, + argv[optind], + strerror(errno)); + close(fd); + return 1; + } + close(fd); /* done with this now */ + + s = (char *)base_of_rom; + for (i=0; i<sb.st_size; i += FMAP_SEARCH_STRIDE) { + if (0 == strncmp(s, "__FMAP__", 8)) { + printf("hit at 0x%08x\n", (uint32_t)i); + retval = dump_fmap(s); + break; + } + s++; + } + + if (0 != munmap(base_of_rom, sb.st_size)) { + fprintf(stderr, "%s: can't munmap %s: %s\n", + progname, + argv[optind], + strerror(errno)); + return 1; + } + + return retval; +} diff --git a/utility/vbutil_firmware.c b/utility/vbutil_firmware.c index d58e2a3a..9cff2729 100644 --- a/utility/vbutil_firmware.c +++ b/utility/vbutil_firmware.c @@ -60,6 +60,9 @@ static int PrintHelp(void) { "For '--verify <file>', required OPTIONS are:\n" " --signpubkey <file> Signing public key in .vbpubk format\n" " --fv <file> Firmware volume to verify\n" + "\n" + "For '--verify <file>', optional OPTIONS are:\n" + " --kernelkey <file> Write the kernel subkey to this file\n" ""); return 1; } @@ -157,14 +160,14 @@ static int Vblock(const char* outfile, const char* keyblock_file, return 0; } - static int Verify(const char* infile, const char* signpubkey, - const char* fv_file) { + const char* fv_file, const char* kernelkey_file) { VbKeyBlockHeader* key_block; VbFirmwarePreambleHeader* preamble; VbPublicKey* data_key; VbPublicKey* sign_key; + VbPublicKey* kernel_subkey; RSAPublicKey* rsa; uint8_t* blob; uint64_t blob_size; @@ -210,11 +213,15 @@ static int Verify(const char* infile, const char* signpubkey, printf("Key block:\n"); data_key = &key_block->data_key; printf(" Size: %" PRIu64 "\n", key_block->key_block_size); + printf(" Flags: %" PRIu64 " (ignored)\n", + key_block->key_block_flags); printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, (data_key->algorithm < kNumAlgorithms ? algo_strings[data_key->algorithm] : "(invalid)")); printf(" Data key version: %" PRIu64 "\n", data_key->key_version); - printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags); + printf(" Data key sha1sum: "); + PrintPubKeySha1Sum(data_key); + printf("\n"); rsa = PublicKeyToRSA(&key_block->data_key); if (!rsa) { @@ -235,12 +242,16 @@ static int Verify(const char* infile, const char* signpubkey, printf(" Header version: %" PRIu32 ".%" PRIu32"\n", preamble->header_version_major, preamble->header_version_minor); printf(" Firmware version: %" PRIu64 "\n", preamble->firmware_version); + kernel_subkey = &preamble->kernel_subkey; printf(" Kernel key algorithm: %" PRIu64 " %s\n", - preamble->kernel_subkey.algorithm, - (preamble->kernel_subkey.algorithm < kNumAlgorithms ? - algo_strings[preamble->kernel_subkey.algorithm] : "(invalid)")); + kernel_subkey->algorithm, + (kernel_subkey->algorithm < kNumAlgorithms ? + algo_strings[kernel_subkey->algorithm] : "(invalid)")); printf(" Kernel key version: %" PRIu64 "\n", - preamble->kernel_subkey.key_version); + kernel_subkey->key_version); + printf(" Kernel key sha1sum: "); + PrintPubKeySha1Sum(kernel_subkey); + printf("\n"); printf(" Firmware body size: %" PRIu64 "\n", preamble->body_signature.data_size); @@ -252,6 +263,15 @@ static int Verify(const char* infile, const char* signpubkey, return 1; } printf("Body verification succeeded.\n"); + + if (kernelkey_file) { + if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) { + fprintf(stderr, + "vbutil_firmware: unable to write kernel subkey\n"); + return 1; + } + } + return 0; } @@ -322,7 +342,7 @@ int main(int argc, char* argv[]) { return Vblock(filename, key_block_file, signprivate, version, fv_file, kernelkey_file); case OPT_MODE_VERIFY: - return Verify(filename, signpubkey, fv_file); + return Verify(filename, signpubkey, fv_file, kernelkey_file); default: printf("Must specify a mode.\n"); return PrintHelp(); diff --git a/utility/vbutil_kernel.c b/utility/vbutil_kernel.c index 80197194..acf156f7 100644 --- a/utility/vbutil_kernel.c +++ b/utility/vbutil_kernel.c @@ -661,11 +661,23 @@ static int Verify(const char* infile, const char* signpubkey, int verbose) { if (verbose) printf(" Signature: %s\n", sign_key ? "valid" : "ignored"); printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size); + printf(" Flags: %" PRIu64 " ", key_block->key_block_flags); + if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) + printf(" !DEV"); + if (key_block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) + printf(" DEV"); + if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) + printf(" !REC"); + if (key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) + printf(" REC"); + printf("\n"); printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, (data_key->algorithm < kNumAlgorithms ? algo_strings[data_key->algorithm] : "(invalid)")); printf(" Data key version: %" PRIu64 "\n", data_key->key_version); - printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags); + printf(" Data key sha1sum: "); + PrintPubKeySha1Sum(data_key); + printf("\n"); rsa = PublicKeyToRSA(&key_block->data_key); if (!rsa) { diff --git a/utility/vbutil_key.c b/utility/vbutil_key.c index c076bfff..38d90003 100644 --- a/utility/vbutil_key.c +++ b/utility/vbutil_key.c @@ -108,15 +108,6 @@ static int Pack(const char *infile, const char *outfile, uint64_t algorithm, } -static void PrintDigest(const uint8_t* buf, uint64_t buflen) { - uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM); - int i; - for (i=0; i<SHA1_DIGEST_SIZE; i++) - printf("%02x", digest[i]); - printf("\n"); - Free(digest); -} - /* Unpack a .vbpubk or .vbprivk */ static int Unpack(const char *infile, const char *outfile) { VbPublicKey* pubkey; @@ -134,7 +125,8 @@ static int Unpack(const char *infile, const char *outfile) { algo_strings[pubkey->algorithm] : "(invalid)")); printf("Key Version: %" PRIu64 "\n", pubkey->key_version); printf("Key sha1sum: "); - PrintDigest(((uint8_t *)pubkey) + pubkey->key_offset, pubkey->key_size); + PrintPubKeySha1Sum(pubkey); + printf("\n"); if (outfile) { if (0 != PublicKeyWrite(outfile, pubkey)) { fprintf(stderr, "vbutil_key: Error writing key copy.\n"); @@ -146,7 +138,6 @@ static int Unpack(const char *infile, const char *outfile) { return 0; } - if ((privkey = PrivateKeyRead(infile))) { printf("Private Key file: %s\n", infile); printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm, diff --git a/utility/vbutil_keyblock.c b/utility/vbutil_keyblock.c index 7d5b7c13..ff1b44be 100644 --- a/utility/vbutil_keyblock.c +++ b/utility/vbutil_keyblock.c @@ -152,12 +152,24 @@ static int Unpack(const char* infile, const char* datapubkey, printf("Key block file: %s\n", infile); printf("Flags: %" PRIu64 "\n", block->key_block_flags); + if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0) + printf(" !DEV"); + if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1) + printf(" DEV"); + if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0) + printf(" !REC"); + if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1) + printf(" REC"); + printf("\n"); data_key = &block->data_key; printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm, (data_key->algorithm < kNumAlgorithms ? algo_strings[data_key->algorithm] : "(invalid)")); printf("Data key version: %" PRIu64 "\n", data_key->key_version); + printf("Data key sha1sum: "); + PrintPubKeySha1Sum(data_key); + printf("\n"); if (datapubkey) { if (0 != PublicKeyWrite(datapubkey, data_key)) { |