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