OLD | NEW |
1 /* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2010-2011 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 | 5 |
6 /* A lightweight TPM command library. | 6 /* A lightweight TPM command library. |
7 * | 7 * |
8 * The general idea is that TPM commands are array of bytes whose | 8 * The general idea is that TPM commands are array of bytes whose |
9 * fields are mostly compile-time constant. The goal is to build much | 9 * fields are mostly compile-time constant. The goal is to build much |
10 * of the commands at compile time (or build time) and change some of | 10 * of the commands at compile time (or build time) and change some of |
(...skipping 26 matching lines...) Expand all Loading... |
37 uint32_t code; | 37 uint32_t code; |
38 FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); | 38 FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); |
39 return code; | 39 return code; |
40 } | 40 } |
41 | 41 |
42 /* Gets the return code field of a TPM result. */ | 42 /* Gets the return code field of a TPM result. */ |
43 static INLINE int TpmReturnCode(const uint8_t* buffer) { | 43 static INLINE int TpmReturnCode(const uint8_t* buffer) { |
44 return TpmCommandCode(buffer); | 44 return TpmCommandCode(buffer); |
45 } | 45 } |
46 | 46 |
47 /* Sends a TPM command and gets a response. Returns 0 if success or the TPM | 47 /* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or |
48 * error code if error. */ | 48 * DOING_SELFTEST errors are returned. |
49 static uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response, | 49 */ |
50 int max_length) { | 50 static uint32_t TlclSendReceiveNoRetry(const uint8_t* request, |
51 | 51 uint8_t* response, int max_length) { |
52 uint32_t result; | 52 uint32_t result; |
53 | 53 |
54 #ifdef EXTRA_LOGGING | 54 #ifdef EXTRA_LOGGING |
55 VBDEBUG(("TPM: command: %x%x %x%x%x%x %x%x%x%x\n", | 55 VBDEBUG(("TPM: command: %x%x %x%x%x%x %x%x%x%x\n", |
56 request[0], request[1], | 56 request[0], request[1], |
57 request[2], request[3], request[4], request[5], | 57 request[2], request[3], request[4], request[5], |
58 request[6], request[7], request[8], request[9])); | 58 request[6], request[7], request[8], request[9])); |
59 #endif | 59 #endif |
60 | 60 |
61 result = TlclStubSendReceive(request, TpmCommandSize(request), | 61 result = TlclStubSendReceive(request, TpmCommandSize(request), |
(...skipping 14 matching lines...) Expand all Loading... |
76 response[6], response[7], response[8], response[9])); | 76 response[6], response[7], response[8], response[9])); |
77 #endif | 77 #endif |
78 | 78 |
79 VBDEBUG(("TPM: command 0x%x returned 0x%x\n", | 79 VBDEBUG(("TPM: command 0x%x returned 0x%x\n", |
80 TpmCommandCode(request), result)); | 80 TpmCommandCode(request), result)); |
81 | 81 |
82 return result; | 82 return result; |
83 } | 83 } |
84 | 84 |
85 | 85 |
| 86 /* Sends a TPM command and gets a response. Returns 0 if success or the TPM |
| 87 * error code if error. In the firmware, waits for the self test to complete |
| 88 * if needed. In the host, reports the first error without retries. */ |
| 89 static uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response, |
| 90 int max_length) { |
| 91 uint32_t result = TlclSendReceiveNoRetry(request, response, max_length); |
| 92 /* When compiling for the firmware, hide command failures due to the self |
| 93 * test not having run or completed. */ |
| 94 #ifndef CHROMEOS_ENVIRONMENT |
| 95 /* If the command fails because the self test has not completed, try it |
| 96 * again after attempting to ensure that the self test has completed. */ |
| 97 if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) { |
| 98 result = TlclContinueSelfTest(); |
| 99 if (result != TPM_SUCCESS) { |
| 100 return result; |
| 101 } |
| 102 #if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE) |
| 103 /* Retry only once */ |
| 104 result = TlclSendReceiveNoRetry(request, response, max_length); |
| 105 #else |
| 106 /* This needs serious testing. The TPM specification says: "iii. The |
| 107 * caller MUST wait for the actions of TPM_ContinueSelfTest to complete |
| 108 * before reissuing the command C1." But, if ContinueSelfTest is |
| 109 * non-blocking, how do we know that the actions have completed other than |
| 110 * trying again? */ |
| 111 do { |
| 112 result = TlclSendReceiveNoRetry(request, response, max_length); |
| 113 } while (result == TPM_E_DOING_SELFTEST); |
| 114 #endif |
| 115 } |
| 116 #endif /* ! defined(CHROMEOS_ENVIRONMENT) */ |
| 117 return result; |
| 118 } |
| 119 |
86 /* Sends a command and returns the error code. */ | 120 /* Sends a command and returns the error code. */ |
87 static uint32_t Send(const uint8_t* command) { | 121 static uint32_t Send(const uint8_t* command) { |
88 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 122 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
89 return TlclSendReceive(command, response, sizeof(response)); | 123 return TlclSendReceive(command, response, sizeof(response)); |
90 } | 124 } |
91 | 125 |
92 /* Exported functions. */ | 126 /* Exported functions. */ |
93 | 127 |
94 uint32_t TlclLibInit(void) { | 128 uint32_t TlclLibInit(void) { |
95 return TlclStubInit(); | 129 return TlclStubInit(); |
96 } | 130 } |
97 | 131 |
98 uint32_t TlclStartup(void) { | 132 uint32_t TlclStartup(void) { |
99 VBDEBUG(("TPM: Startup\n")); | 133 VBDEBUG(("TPM: Startup\n")); |
100 return Send(tpm_startup_cmd.buffer); | 134 return Send(tpm_startup_cmd.buffer); |
101 } | 135 } |
102 | 136 |
| 137 uint32_t TlclSaveState(void) { |
| 138 VBDEBUG(("TPM: SaveState\n")); |
| 139 return Send(tpm_savestate_cmd.buffer); |
| 140 } |
| 141 |
103 uint32_t TlclResume(void) { | 142 uint32_t TlclResume(void) { |
104 VBDEBUG(("TPM: Resume\n")); | 143 VBDEBUG(("TPM: Resume\n")); |
105 return Send(tpm_resume_cmd.buffer); | 144 return Send(tpm_resume_cmd.buffer); |
106 } | 145 } |
107 | 146 |
108 uint32_t TlclSelfTestFull(void) { | 147 uint32_t TlclSelfTestFull(void) { |
109 VBDEBUG(("TPM: Self test full\n")); | 148 VBDEBUG(("TPM: Self test full\n")); |
110 return Send(tpm_selftestfull_cmd.buffer); | 149 return Send(tpm_selftestfull_cmd.buffer); |
111 } | 150 } |
112 | 151 |
113 uint32_t TlclContinueSelfTest(void) { | 152 uint32_t TlclContinueSelfTest(void) { |
| 153 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
114 VBDEBUG(("TPM: Continue self test\n")); | 154 VBDEBUG(("TPM: Continue self test\n")); |
115 return Send(tpm_continueselftest_cmd.buffer); | 155 /* Call the No Retry version of SendReceive to avoid recursion. */ |
| 156 return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer, |
| 157 response, sizeof(response)); |
116 } | 158 } |
117 | 159 |
118 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { | 160 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { |
119 struct s_tpm_nv_definespace_cmd cmd; | 161 struct s_tpm_nv_definespace_cmd cmd; |
120 VBDEBUG(("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size)); | 162 VBDEBUG(("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size)); |
121 Memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); | 163 Memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd)); |
122 ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); | 164 ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.index, index); |
123 ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); | 165 ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm); |
124 ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); | 166 ToTpmUint32(cmd.buffer + tpm_nv_definespace_cmd.size, size); |
125 return Send(cmd.buffer); | 167 return Send(cmd.buffer); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 } | 326 } |
285 return result; | 327 return result; |
286 } | 328 } |
287 | 329 |
288 uint32_t TlclSetGlobalLock(void) { | 330 uint32_t TlclSetGlobalLock(void) { |
289 uint32_t x; | 331 uint32_t x; |
290 VBDEBUG(("TPM: Set global lock\n")); | 332 VBDEBUG(("TPM: Set global lock\n")); |
291 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); | 333 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); |
292 } | 334 } |
293 | 335 |
294 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) { | 336 uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest, |
| 337 uint8_t* out_digest) { |
295 struct s_tpm_extend_cmd cmd; | 338 struct s_tpm_extend_cmd cmd; |
296 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; | 339 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; |
297 uint32_t result; | 340 uint32_t result; |
298 | 341 |
299 Memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); | 342 Memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); |
300 ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); | 343 ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); |
301 Memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); | 344 Memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); |
302 | 345 |
303 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); | 346 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); |
304 if (result != TPM_SUCCESS) | 347 if (result != TPM_SUCCESS) |
(...skipping 13 matching lines...) Expand all Loading... |
318 Memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd)); | 361 Memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd)); |
319 ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index); | 362 ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index); |
320 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); | 363 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); |
321 if (result != TPM_SUCCESS) | 364 if (result != TPM_SUCCESS) |
322 return result; | 365 return result; |
323 | 366 |
324 nvdata = response + kTpmResponseHeaderLength + sizeof(size); | 367 nvdata = response + kTpmResponseHeaderLength + sizeof(size); |
325 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); | 368 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); |
326 return result; | 369 return result; |
327 } | 370 } |
OLD | NEW |