OLD | NEW |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 * | 4 * |
5 * TPM command utility. Runs simple TPM commands. Mostly useful when physical | 5 * TPM command utility. Runs simple TPM commands. Mostly useful when physical |
6 * presence has not been locked. | 6 * presence has not been locked. |
7 */ | 7 */ |
8 | 8 |
9 #include <stdio.h> | 9 #include <stdio.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <syslog.h> | 11 #include <syslog.h> |
12 | 12 |
13 #include "tlcl.h" | 13 #include "tlcl.h" |
14 #include "tpm_error_messages.h" | 14 #include "tpm_error_messages.h" |
| 15 #include "tss_constants.h" |
15 | 16 |
16 typedef struct command_record { | 17 typedef struct command_record { |
17 const char* name; | 18 const char* name; |
18 const char* abbr; | 19 const char* abbr; |
19 const char* description; | 20 const char* description; |
20 uint32_t (*handler)(void); | 21 uint32_t (*handler)(void); |
21 } command_record; | 22 } command_record; |
22 | 23 |
| 24 /* Set in main, consumed by handler functions below. We use global variables |
| 25 * so we can also choose to call Tlcl*() functions directly; they don't take |
| 26 * argv/argc. |
| 27 */ |
| 28 int nargs; |
| 29 char** args; |
| 30 |
| 31 /* Converts a string in the form 0x[0-9a-f]+ to a 32-bit value. Returns 0 for |
| 32 * success, non-zero for failure. |
| 33 */ |
| 34 int HexStringToUint32(const char* string, uint32_t* value) { |
| 35 char tail[1]; |
| 36 /* strtoul is not as good because it overflows silently */ |
| 37 char* format = strncmp(string, "0x", 2) ? "%8x%s" : "0x%8x%s"; |
| 38 int n = sscanf(string, format, value, tail); |
| 39 return n != 1; |
| 40 } |
| 41 |
| 42 /* Converts a string in the form [0-9a-f]+ to an 8-bit value. Returns 0 for |
| 43 * success, non-zero for failure. |
| 44 */ |
| 45 int HexStringToUint8(const char* string, uint8_t* value) { |
| 46 char* end; |
| 47 uint32_t large_value = strtoul(string, &end, 16); |
| 48 if (*end != '\0' || large_value > 0xff) { |
| 49 return 1; |
| 50 } |
| 51 *value = large_value; |
| 52 return 0; |
| 53 } |
| 54 |
| 55 /* TPM error check and reporting. Returns 0 if |result| is 0 (TPM_SUCCESS). |
| 56 * Otherwise looks up a TPM error in the error table and prints the error if |
| 57 * found. |
| 58 */ |
| 59 uint32_t ErrorCheck(uint32_t result, const char* cmd) { |
| 60 if (result == 0) { |
| 61 return 0; |
| 62 } else { |
| 63 int i; |
| 64 int n = sizeof(tpm_error_table) / sizeof(tpm_error_table[0]); |
| 65 fprintf(stderr, "command \"%s\" failed with code 0x%x\n", cmd, result); |
| 66 for (i = 0; i < n; i++) { |
| 67 if (tpm_error_table[i].code == result) { |
| 68 fprintf(stderr, "%s\n%s\n", tpm_error_table[i].name, |
| 69 tpm_error_table[i].description); |
| 70 return 1; |
| 71 } |
| 72 } |
| 73 fprintf(stderr, "the TPM error code is unknown to this program\n"); |
| 74 return 1; |
| 75 } |
| 76 } |
| 77 |
23 /* Handler functions. These wouldn't exist if C had closures. | 78 /* Handler functions. These wouldn't exist if C had closures. |
24 */ | 79 */ |
25 | |
26 static uint32_t HandlerGetFlags(void) { | 80 static uint32_t HandlerGetFlags(void) { |
27 uint8_t disabled; | 81 uint8_t disabled; |
28 uint8_t deactivated; | 82 uint8_t deactivated; |
29 uint8_t nvlocked; | 83 uint8_t nvlocked; |
30 uint32_t result = TlclGetFlags(&disabled, &deactivated, &nvlocked); | 84 uint32_t result = TlclGetFlags(&disabled, &deactivated, &nvlocked); |
31 if (result == 0) { | 85 if (result == 0) { |
32 printf("disabled: %d\ndeactivated: %d\nnvlocked: %d\n", | 86 printf("disabled: %d\ndeactivated: %d\nnvlocked: %d\n", |
33 disabled, deactivated, nvlocked); | 87 disabled, deactivated, nvlocked); |
34 } | 88 } |
35 return result; | 89 return result; |
36 } | 90 } |
37 | 91 |
38 static uint32_t HandlerActivate(void) { | 92 static uint32_t HandlerActivate(void) { |
39 return TlclSetDeactivated(0); | 93 return TlclSetDeactivated(0); |
40 } | 94 } |
41 | 95 |
42 static uint32_t HandlerDeactivate(void) { | 96 static uint32_t HandlerDeactivate(void) { |
43 return TlclSetDeactivated(1); | 97 return TlclSetDeactivated(1); |
44 } | 98 } |
45 | 99 |
| 100 static uint32_t HandlerDefineSpace(void) { |
| 101 uint32_t index, size, perm; |
| 102 if (nargs != 5) { |
| 103 fprintf(stderr, "usage: tpmc def <index> <size> <perm>\n"); |
| 104 exit(1); |
| 105 } |
| 106 if (HexStringToUint32(args[2], &index) != 0 || |
| 107 HexStringToUint32(args[3], &size) != 0 || |
| 108 HexStringToUint32(args[4], &perm) != 0) { |
| 109 fprintf(stderr, "<index>, <size>, and <perm> must be " |
| 110 "32-bit hex (0x[0-9a-f]+)\n"); |
| 111 exit(1); |
| 112 } |
| 113 return TlclDefineSpace(index, perm, size); |
| 114 } |
| 115 |
| 116 static uint32_t HandlerWrite(void) { |
| 117 uint32_t index, size; |
| 118 uint8_t value[TPM_MAX_COMMAND_SIZE]; |
| 119 char** byteargs; |
| 120 int i; |
| 121 if (nargs < 3) { |
| 122 fprintf(stderr, "usage: tpmc write <index> [<byte0> <byte1> ...]\n"); |
| 123 exit(1); |
| 124 } |
| 125 if (HexStringToUint32(args[2], &index) != 0) { |
| 126 fprintf(stderr, "<index> must be 32-bit hex (0x[0-9a-f]+)\n"); |
| 127 exit(1); |
| 128 } |
| 129 size = nargs - 3; |
| 130 if (size > sizeof(value)) { |
| 131 fprintf(stderr, "byte array too large\n"); |
| 132 exit(1); |
| 133 } |
| 134 |
| 135 byteargs = args + 3; |
| 136 for (i = 0; i < size; i++) { |
| 137 if (HexStringToUint8(byteargs[i], &value[i]) != 0) { |
| 138 fprintf(stderr, "invalid byte %s, should be [0-9a-f][0-9a-f]?\n", |
| 139 byteargs[i]); |
| 140 exit(1); |
| 141 } |
| 142 } |
| 143 |
| 144 if (size == 0) { |
| 145 if (index == TPM_NV_INDEX_LOCK) { |
| 146 fprintf(stderr, "This would set the nvLocked bit. " |
| 147 "Use \"tpmc setnv\" instead.\n"); |
| 148 exit(1); |
| 149 } |
| 150 printf("warning: zero-length write\n"); |
| 151 } else { |
| 152 printf("writing %d byte%s\n", size, size > 1 ? "s" : ""); |
| 153 } |
| 154 |
| 155 return TlclWrite(index, value, size); |
| 156 } |
| 157 |
| 158 static uint32_t HandlerRead(void) { |
| 159 uint32_t index, size; |
| 160 uint8_t value[4096]; |
| 161 uint32_t result; |
| 162 int i; |
| 163 if (nargs != 4) { |
| 164 fprintf(stderr, "usage: tpmc read <index> <size>\n"); |
| 165 exit(1); |
| 166 } |
| 167 if (HexStringToUint32(args[2], &index) != 0 || |
| 168 HexStringToUint32(args[3], &size) != 0) { |
| 169 fprintf(stderr, "<index> and <size> must be 32-bit hex (0x[0-9a-f]+)\n"); |
| 170 exit(1); |
| 171 } |
| 172 if (size > sizeof(value)) { |
| 173 fprintf(stderr, "size of read (0x%x) is too big\n", size); |
| 174 exit(1); |
| 175 } |
| 176 result = TlclRead(index, value, size); |
| 177 if (result == 0 && size > 0) { |
| 178 for (i = 0; i < size - 1; i++) { |
| 179 printf("%x ", value[i]); |
| 180 } |
| 181 printf("%x\n", value[i]); |
| 182 } |
| 183 return result; |
| 184 } |
| 185 |
| 186 static uint32_t HandlerGetPermissions(void) { |
| 187 uint32_t index, permissions, result; |
| 188 if (nargs != 3) { |
| 189 fprintf(stderr, "usage: tpmc getp <index>\n"); |
| 190 exit(1); |
| 191 } |
| 192 if (HexStringToUint32(args[2], &index) != 0) { |
| 193 fprintf(stderr, "<index> must be 32-bit hex (0x[0-9a-f]+)\n"); |
| 194 exit(1); |
| 195 } |
| 196 result = TlclGetPermissions(index, &permissions); |
| 197 if (result == 0) { |
| 198 printf("space 0x%x has permissions 0x%x\n", index, permissions); |
| 199 } |
| 200 return result; |
| 201 } |
| 202 |
46 /* Table of TPM commands. | 203 /* Table of TPM commands. |
47 */ | 204 */ |
48 command_record command_table[] = { | 205 command_record command_table[] = { |
49 { "getflags", "getf", "read and print the value of selected flags", | 206 { "getflags", "getf", "read and print the value of selected flags", |
50 HandlerGetFlags }, | 207 HandlerGetFlags }, |
51 { "startup", "sta", "issue a Startup command", TlclStartup }, | 208 { "startup", "sta", "issue a Startup command", TlclStartup }, |
52 { "selftestfull", "test", "issue a SelfTestFull command", TlclSelfTestFull }, | 209 { "selftestfull", "test", "issue a SelfTestFull command", TlclSelfTestFull }, |
53 { "continueselftest", "ctest", "issue a ContinueSelfTest command", | 210 { "continueselftest", "ctest", "issue a ContinueSelfTest command", |
54 TlclContinueSelfTest }, | 211 TlclContinueSelfTest }, |
55 { "assertphysicalpresence", "ppon", "assert Physical Presence", | 212 { "assertphysicalpresence", "ppon", "assert Physical Presence", |
56 TlclAssertPhysicalPresence }, | 213 TlclAssertPhysicalPresence }, |
57 { "enable", "ena", "enable the TPM (needs PP)", TlclSetEnable }, | 214 { "enable", "ena", "enable the TPM (needs PP)", TlclSetEnable }, |
58 { "disable", "dis", "disable the TPM (needs PP)", TlclClearEnable }, | 215 { "disable", "dis", "disable the TPM (needs PP)", TlclClearEnable }, |
59 { "activate", "act", "activate the TPM (needs PP, maybe reboot)", | 216 { "activate", "act", "activate the TPM (needs PP, maybe reboot)", |
60 HandlerActivate }, | 217 HandlerActivate }, |
61 { "deactivate", "deact", "deactivate the TPM (needs PP, maybe reboot)", | 218 { "deactivate", "deact", "deactivate the TPM (needs PP, maybe reboot)", |
62 HandlerDeactivate }, | 219 HandlerDeactivate }, |
63 { "clear", "clr", "clear the TPM owner (needs PP)", TlclForceClear }, | 220 { "clear", "clr", "clear the TPM owner (needs PP)", TlclForceClear }, |
| 221 { "setnvlocked", "setnv", "set the nvLocked flag permanently (IRREVERSIBLE!)", |
| 222 TlclSetNvLocked }, |
| 223 { "lockphysicalpresence", "pplock", "lock PP to current value until reboot", |
| 224 TlclLockPhysicalPresence }, |
| 225 { "setbgloballock", "block", "set the bGlobalLock until reboot", |
| 226 TlclSetGlobalLock }, |
| 227 { "definespace", "def", "define a space (def <index> <size> <perm>)", |
| 228 HandlerDefineSpace }, |
| 229 { "write", "write", "write to a space (write <index> [<byte0> <byte1> ...])", |
| 230 HandlerWrite }, |
| 231 { "read", "read", "read from a space (read <index> <size>)", |
| 232 HandlerRead }, |
| 233 { "getpermissions", "getp", "print space permissions (getp <index>)", |
| 234 HandlerGetPermissions }, |
64 }; | 235 }; |
65 | 236 |
66 static int n_commands = sizeof(command_table) / sizeof(command_table[0]); | 237 static int n_commands = sizeof(command_table) / sizeof(command_table[0]); |
67 | 238 |
68 int main(int argc, char* argv[]) { | 239 int main(int argc, char* argv[]) { |
69 if (argc < 2) { | 240 if (argc < 2) { |
70 fprintf(stderr, "usage: %s <TPM command>\n or: %s help\n", | 241 fprintf(stderr, "usage: %s <TPM command> [args]\n or: %s help\n", |
71 argv[0], argv[0]); | 242 argv[0], argv[0]); |
72 exit(1); | 243 exit(1); |
73 } else { | 244 } else { |
74 command_record* c; | 245 command_record* c; |
75 const char* cmd = argv[1]; | 246 const char* cmd = argv[1]; |
| 247 nargs = argc; |
| 248 args = argv; |
76 | 249 |
77 if (strcmp(cmd, "help") == 0) { | 250 if (strcmp(cmd, "help") == 0) { |
78 printf("%23s %7s %s\n\n", "command", "abbr.", "description"); | 251 printf("%23s %7s %s\n\n", "command", "abbr.", "description"); |
79 for (c = command_table; c < command_table + n_commands; c++) { | 252 for (c = command_table; c < command_table + n_commands; c++) { |
80 printf("%23s %7s %s\n", c->name, c->abbr, c->description); | 253 printf("%23s %7s %s\n", c->name, c->abbr, c->description); |
81 } | 254 } |
82 return 0; | 255 return 0; |
83 } | 256 } |
84 | 257 |
85 TlclLibInit(); | 258 TlclLibInit(); |
86 | 259 |
87 for (c = command_table; c < command_table + n_commands; c++) { | 260 for (c = command_table; c < command_table + n_commands; c++) { |
88 if (strcmp(cmd, c->name) == 0 || strcmp(cmd, c->abbr) == 0) { | 261 if (strcmp(cmd, c->name) == 0 || strcmp(cmd, c->abbr) == 0) { |
89 uint32_t result; | 262 return ErrorCheck(c->handler(), cmd); |
90 result = c->handler(); | |
91 if (result == 0) { | |
92 return 0; | |
93 } else { | |
94 int i; | |
95 int n = sizeof(tpm_error_table) / sizeof(tpm_error_table[0]); | |
96 fprintf(stderr, "command \"%s\" failed with code 0x%x\n", | |
97 cmd, result); | |
98 for (i = 0; i < n; i++) { | |
99 if (tpm_error_table[i].code == result) { | |
100 fprintf(stderr, "%s\n%s\n", tpm_error_table[i].name, | |
101 tpm_error_table[i].description); | |
102 return 1; | |
103 } | |
104 } | |
105 fprintf(stderr, "the error code is unknown to this program\n"); | |
106 return 1; | |
107 } | |
108 } | 263 } |
109 } | 264 } |
110 | 265 |
111 /* No command matched. */ | 266 /* No command matched. */ |
112 fprintf(stderr, "%s: unknown command: %s\n", argv[0], cmd); | 267 fprintf(stderr, "%s: unknown command: %s\n", argv[0], cmd); |
113 return 1; | 268 return 1; |
114 } | 269 } |
115 } | 270 } |
OLD | NEW |