summaryrefslogtreecommitdiff
path: root/futility
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2014-10-22 17:42:20 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-31 20:55:28 +0000
commitf4f395e1ca724ef8795cfe86a9edbf15f14eacd1 (patch)
treef76bbb265c340603f18fa74e1b4e3934006a94e1 /futility
parente1486c3234b7dc6fc5b58681b271a65a09141e20 (diff)
downloadvboot-f4f395e1ca724ef8795cfe86a9edbf15f14eacd1.tar.gz
Extend HWID digest into PCR1 (GBB v1.2 only)
GBB header v1.2 adds a digest of the HWID string to the blob (and maintains it when updated with the current futility/gbb_utility). This CL causes VbSelectFirmware() to extend PCR1 with that HWID digest (only for GBB header v1.2 and later, of course). Tests are updated. This also adds a "pcr" command to futility to help determine that the change is working on the hardware (adds 4K bytes or fewer to the size of the executable). BUG=chromium:415714 BRANCH=ToT (and maybe others?) TEST=make runtests, manual install on HW To test on hardware, build and update a system with this change (both the disk image and the RO firmware). NOTE: The BIOS image must be built in a chroot that is using the current version of futility. You may need to update your chroot if your BIOS image still produces v1.1 GBB headers. Check with: futility show <firmware_image.bin> | grep -B1 'digest:' Boot the new system with a new test image, then follow these steps: Read the BIOS: # flashrom -r /tmp/bios.bin Make sure the GBB has a valid digest for the HWID. # futility show /tmp/bios.bin | grep -B1 'digest:' HWID: SAMUS TEST 8028 digest: 4172d24f40bf72cc0ab8... <valid> # Extract only the sha1sum-sized part of the HWID digest: # futility show /tmp/bios.bin | awk '/digest:/ {print $2}' | colrm 41 4172d24f40bf72cc0ab878b4c589b8fe9cf4405e # Simulate extending that value in a PCR using the futility "pcr" command: # futility pcr 4172d24f40bf72cc0ab878b4c589b8fe9cf4405e PCR: 0000000000000000000000000000000000000000 + 4172d24f40bf72cc0ab878b4c589b8fe9cf4405e PCR: b6e5ffd2d898a7b15236ad22ca25f53ac1f40776 # Finally, look at the value of PCR1. It should match the last line of the futility pcr output: # head /sys/class/misc/tpm0/device/pcrs | grep PCR-01 PCR-01: B6 E5 FF D2 D8 98 A7 B1 52 36 AD 22 CA 25 F5 3A C1 F4 07 76 # Change-Id: I09cf855f1a24616cc1a9ddb676670edbc76827d2 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/226408 Reviewed-by: Darren Krahn <dkrahn@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'futility')
-rw-r--r--futility/cmd_pcr.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/futility/cmd_pcr.c b/futility/cmd_pcr.c
new file mode 100644
index 00000000..9149ccfe
--- /dev/null
+++ b/futility/cmd_pcr.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2014 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 <ctype.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "futility.h"
+
+static const char usage[] = "\n"
+ "Usage: " MYNAME " %s [OPTIONS] DIGEST [...]\n"
+ "\n"
+ "This simulates a TPM PCR extension, to determine the expected output\n"
+ "\n"
+ "Each DIGEST arg should be a hex string (spaces optional) of the\n"
+ "appropriate length. The PCR is extended with each digest in turn\n"
+ "and the new value displayed.\n"
+ "\n"
+ "Options:\n"
+ " -i Initialize the PCR with the first DIGEST argument\n"
+ " (the default is to start with all zeros)\n"
+ " -2 Use sha256 DIGESTS (the default is sha1)\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ " " MYNAME " %s b52791126f96a21a8ba4d511c6f25a1c1eb6dc9e\n"
+ " " MYNAME " %s "
+ "'b5 27 91 12 6f 96 a2 1a 8b a4 d5 11 c6 f2 5a 1c 1e b6 dc 9e'\n"
+ "\n";
+
+static void help_and_quit(const char *prog)
+{
+ printf(usage, prog, prog, prog);
+}
+
+static int parse_hex(uint8_t *val, const char *str)
+{
+ uint8_t v = 0;
+ char c;
+ int digit;
+
+ for (digit = 0; digit < 2; digit++) {
+ c = *str;
+ if (!c)
+ return 0;
+ if (!isxdigit(c))
+ return 0;
+ c = tolower(c);
+ if (c >= '0' && c <= '9')
+ v += c - '0';
+ else
+ v += 10 + c - 'a';
+ if (!digit)
+ v <<= 4;
+ str++;
+ }
+
+ *val = v;
+ return 1;
+}
+
+static void parse_digest_or_die(uint8_t *buf, int len, const char *str)
+{
+ const char *s = str;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ /* skip whitespace */
+ while (*s && isspace(*s))
+ s++;
+ if (!*s)
+ break;
+ if (!parse_hex(buf, s))
+ break;
+
+ /* on to the next byte */
+ s += 2;
+ buf++;
+ }
+
+ if (i != len) {
+ fprintf(stderr, "Invalid DIGEST \"%s\"\n", str);
+ exit(1);
+ }
+}
+
+static void print_digest(const uint8_t *buf, int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ printf("%02x", buf[i]);
+}
+
+
+static int do_pcr(int argc, char *argv[])
+{
+ uint8_t accum[SHA256_DIGEST_SIZE * 2];
+ uint8_t pcr[SHA256_DIGEST_SIZE];
+ int digest_alg = SHA1_DIGEST_ALGORITHM;
+ int digest_size = SHA1_DIGEST_SIZE;
+ int opt_init = 0;
+ int errorcnt = 0;
+ uint8_t *digest;
+ int i;
+
+ opterr = 0; /* quiet, you */
+ while ((i = getopt(argc, argv, ":i2")) != -1) {
+ switch (i) {
+ case 'i':
+ opt_init = 1;
+ break;
+ case '2':
+ digest_alg = SHA256_DIGEST_ALGORITHM;
+ digest_size = SHA256_DIGEST_SIZE;
+ break;
+ case '?':
+ if (optopt)
+ fprintf(stderr, "Unrecognized option: -%c\n",
+ optopt);
+ else
+ fprintf(stderr, "Unrecognized option\n");
+ errorcnt++;
+ break;
+ case ':':
+ fprintf(stderr, "Missing argument to -%c\n", optopt);
+ errorcnt++;
+ break;
+ default:
+ DIE;
+ }
+ }
+
+ if (errorcnt) {
+ help_and_quit(argv[0]);
+ return 1;
+ }
+
+ if (argc - optind < 1 + opt_init) {
+ fprintf(stderr, "You must extend at least one DIGEST\n");
+ help_and_quit(argv[0]);
+ return 1;
+ }
+
+ memset(pcr, 0, sizeof(pcr));
+
+ if (opt_init) {
+ parse_digest_or_die(pcr, digest_size, argv[optind]);
+ optind++;
+ }
+
+ printf("PCR: ");
+ print_digest(pcr, digest_size);
+ printf("\n");
+
+ for (i = optind; i < argc; i++) {
+ memcpy(accum, pcr, sizeof(pcr));
+ parse_digest_or_die(accum + digest_size, digest_size, argv[i]);
+
+ printf(" + ");
+ print_digest(accum + digest_size, digest_size);
+ printf("\n");
+
+ digest = DigestBuf(accum, digest_size * 2, digest_alg);
+ if (!digest) {
+ fprintf(stderr, "Error computing digest!\n");
+ return 1;
+ }
+ memcpy(pcr, digest, digest_size);
+ free(digest);
+
+ printf("PCR: ");
+ print_digest(pcr, digest_size);
+ printf("\n");
+ }
+
+ return 0;
+}
+
+DECLARE_FUTIL_COMMAND(pcr, do_pcr,
+ "Simulate a TPM PCR extension operation",
+ help_and_quit);