You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
3.7 KiB
187 lines
3.7 KiB
/* |
|
* 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);
|
|
|