Files
OpenCellular/futility/cmd_pcr.c
Bill Richardson 1eae873b61 futility: Add global args to specify vboot API and format
The host-side futility tool will need to support all extant vboot
implementations. Some legacy futility commands only support the
original vb1 format, but others ("show" or "sign", for example)
may need to be instructed which formats to expect or emit.

This change adds some global args to specify the preferred
formats. It also cleans up a few [unused AFAICT] one-letter args
to avoid conflicts.

BUG=chromium:231574
BRANCH=none
TEST=make runtests

Nothing makes use of this yet, except the "help" command.

Change-Id: Ib79fa12af72b8860b9494e5d9e90b9572c006107
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/246765
Reviewed-by: Randall Spangler <rspangler@chromium.org>
2015-02-28 00:56:13 +00:00

188 lines
3.7 KiB
C

/*
* 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,
VBOOT_VERSION_ALL,
"Simulate a TPM PCR extension operation",
help_and_quit);