summaryrefslogtreecommitdiff
path: root/futility/cmd_pcr.c
diff options
context:
space:
mode:
Diffstat (limited to 'futility/cmd_pcr.c')
-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);