cmd_pcr.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright 2014 The Chromium OS Authors. All rights reserved.
  3. * Use of this source code is governed by a BSD-style license that can be
  4. * found in the LICENSE file.
  5. */
  6. #include <ctype.h>
  7. #include <getopt.h>
  8. #include <stdint.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include "2sysincludes.h"
  12. #include "2common.h"
  13. #include "2sha.h"
  14. #include "futility.h"
  15. static const char usage[] = "\n"
  16. "Usage: " MYNAME " %s [OPTIONS] DIGEST [...]\n"
  17. "\n"
  18. "This simulates a TPM PCR extension, to determine the expected output\n"
  19. "\n"
  20. "Each DIGEST arg should be a hex string (spaces optional) of the\n"
  21. "appropriate length. The PCR is extended with each digest in turn\n"
  22. "and the new value displayed.\n"
  23. "\n"
  24. "Options:\n"
  25. " -i Initialize the PCR with the first DIGEST argument\n"
  26. " (the default is to start with all zeros)\n"
  27. " -2 Use sha256 DIGESTS (the default is sha1)\n"
  28. "\n"
  29. "Examples:\n"
  30. "\n"
  31. " " MYNAME " %s b52791126f96a21a8ba4d511c6f25a1c1eb6dc9e\n"
  32. " " MYNAME " %s "
  33. "'b5 27 91 12 6f 96 a2 1a 8b a4 d5 11 c6 f2 5a 1c 1e b6 dc 9e'\n"
  34. "\n";
  35. static void print_help(int argc, char *argv[])
  36. {
  37. printf(usage, argv[0], argv[0], argv[0]);
  38. }
  39. static int parse_hex(uint8_t *val, const char *str)
  40. {
  41. uint8_t v = 0;
  42. char c;
  43. int digit;
  44. for (digit = 0; digit < 2; digit++) {
  45. c = *str;
  46. if (!c)
  47. return 0;
  48. if (!isxdigit(c))
  49. return 0;
  50. c = tolower(c);
  51. if (c >= '0' && c <= '9')
  52. v += c - '0';
  53. else
  54. v += 10 + c - 'a';
  55. if (!digit)
  56. v <<= 4;
  57. str++;
  58. }
  59. *val = v;
  60. return 1;
  61. }
  62. static void parse_digest_or_die(uint8_t *buf, int len, const char *str)
  63. {
  64. const char *s = str;
  65. int i;
  66. for (i = 0; i < len; i++) {
  67. /* skip whitespace */
  68. while (*s && isspace(*s))
  69. s++;
  70. if (!*s)
  71. break;
  72. if (!parse_hex(buf, s))
  73. break;
  74. /* on to the next byte */
  75. s += 2;
  76. buf++;
  77. }
  78. if (i != len) {
  79. fprintf(stderr, "Invalid DIGEST \"%s\"\n", str);
  80. exit(1);
  81. }
  82. }
  83. static void print_digest(const uint8_t *buf, int len)
  84. {
  85. int i;
  86. for (i = 0; i < len; i++)
  87. printf("%02x", buf[i]);
  88. }
  89. enum {
  90. OPT_HELP = 1000,
  91. };
  92. static const struct option long_opts[] = {
  93. {"help", 0, 0, OPT_HELP},
  94. {NULL, 0, 0, 0}
  95. };
  96. static int do_pcr(int argc, char *argv[])
  97. {
  98. uint8_t accum[VB2_MAX_DIGEST_SIZE * 2];
  99. uint8_t pcr[VB2_MAX_DIGEST_SIZE];
  100. int digest_alg = VB2_HASH_SHA1;
  101. int digest_size;
  102. int opt_init = 0;
  103. int errorcnt = 0;
  104. int i;
  105. opterr = 0; /* quiet, you */
  106. while ((i = getopt_long(argc, argv, ":i2", long_opts, NULL)) != -1) {
  107. switch (i) {
  108. case 'i':
  109. opt_init = 1;
  110. break;
  111. case '2':
  112. digest_alg = VB2_HASH_SHA256;
  113. break;
  114. case OPT_HELP:
  115. print_help(argc, argv);
  116. return !!errorcnt;
  117. case '?':
  118. if (optopt)
  119. fprintf(stderr, "Unrecognized option: -%c\n",
  120. optopt);
  121. else
  122. fprintf(stderr, "Unrecognized option\n");
  123. errorcnt++;
  124. break;
  125. case ':':
  126. fprintf(stderr, "Missing argument to -%c\n", optopt);
  127. errorcnt++;
  128. break;
  129. default:
  130. DIE;
  131. }
  132. }
  133. if (errorcnt) {
  134. print_help(argc, argv);
  135. return 1;
  136. }
  137. if (argc - optind < 1 + opt_init) {
  138. fprintf(stderr, "You must extend at least one DIGEST\n");
  139. print_help(argc, argv);
  140. return 1;
  141. }
  142. memset(pcr, 0, sizeof(pcr));
  143. digest_size = vb2_digest_size(digest_alg);
  144. if (!digest_size) {
  145. fprintf(stderr, "Error determining digest size!\n");
  146. return 1;
  147. }
  148. if (opt_init) {
  149. parse_digest_or_die(pcr, digest_size, argv[optind]);
  150. optind++;
  151. }
  152. printf("PCR: ");
  153. print_digest(pcr, digest_size);
  154. printf("\n");
  155. for (i = optind; i < argc; i++) {
  156. memcpy(accum, pcr, sizeof(pcr));
  157. parse_digest_or_die(accum + digest_size, digest_size, argv[i]);
  158. printf(" + ");
  159. print_digest(accum + digest_size, digest_size);
  160. printf("\n");
  161. if (VB2_SUCCESS != vb2_digest_buffer(accum, digest_size * 2,
  162. digest_alg,
  163. pcr, digest_size)) {
  164. fprintf(stderr, "Error computing digest!\n");
  165. return 1;
  166. }
  167. printf("PCR: ");
  168. print_digest(pcr, digest_size);
  169. printf("\n");
  170. }
  171. return 0;
  172. }
  173. DECLARE_FUTIL_COMMAND(pcr, do_pcr, VBOOT_VERSION_ALL,
  174. "Simulate a TPM PCR extension operation");