tpmc: add PCR reading function

Add ability to report a single PCR value via the tpmc utility. Using
/sys/devices/platform/tpm_tis/pcrs is too slow, since it reads all
PCRs before returning. Anything wanting to read PCR0 on a time-critical
path needs maximum speed.

BUG=chromium-os:22172
TEST=install and test x86-alex.

Change-Id: I2d450961d33fa314d54b909135a74aa756279ec6
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/13891
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
diff --git a/utility/tpmc.c b/utility/tpmc.c
index 0b89677..d8fb07a 100644
--- a/utility/tpmc.c
+++ b/utility/tpmc.c
@@ -160,6 +160,29 @@
   return TlclWrite(index, value, size);
 }
 
+static uint32_t HandlerPCRRead(void) {
+  uint32_t index;
+  uint8_t value[TPM_PCR_DIGEST];
+  uint32_t result;
+  int i;
+  if (nargs != 3) {
+    fprintf(stderr, "usage: tpmc pcrread <index>\n");
+    exit(OTHER_ERROR);
+  }
+  if (HexStringToUint32(args[2], &index) != 0) {
+    fprintf(stderr, "<index> must be 32-bit hex (0x[0-9a-f]+)\n");
+    exit(OTHER_ERROR);
+  }
+  result = TlclPCRRead(index, value, sizeof(value));
+  if (result == 0) {
+    for (i = 0; i < TPM_PCR_DIGEST; i++) {
+      printf("%02x", value[i]);
+    }
+    printf("\n");
+  }
+  return result;
+}
+
 static uint32_t HandlerRead(void) {
   uint32_t index, size;
   uint8_t value[4096];
@@ -283,6 +306,8 @@
     HandlerWrite },
   { "read", "read", "read from a space (read <index> <size>)",
     HandlerRead },
+  { "pcrread", "pcr", "read from a PCR (pcrread <index>)",
+    HandlerPCRRead },
   { "getpermissions", "getp", "print space permissions (getp <index>)",
     HandlerGetPermissions },
   { "getpermanentflags", "getpf", "print all permanent flags",