| 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 | 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 27 matching lines...) Expand all Loading... |
| 38 uint32_t code; | 38 uint32_t code; |
| 39 FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); | 39 FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code); |
| 40 return code; | 40 return code; |
| 41 } | 41 } |
| 42 | 42 |
| 43 /* Gets the return code field of a TPM result. */ | 43 /* Gets the return code field of a TPM result. */ |
| 44 static INLINE int TpmReturnCode(const uint8_t* buffer) { | 44 static INLINE int TpmReturnCode(const uint8_t* buffer) { |
| 45 return TpmCommandCode(buffer); | 45 return TpmCommandCode(buffer); |
| 46 } | 46 } |
| 47 | 47 |
| 48 /* Checks for errors in a TPM response. */ | 48 /* Sends a TPM command and gets a response. Returns 0 if success or the TPM |
| 49 static void CheckResult(uint8_t* request, uint8_t* response, int warn_only) { | 49 * error code if error. */ |
| 50 int command = TpmCommandCode(request); | 50 static uint32_t TlclSendReceive(uint8_t* request, uint8_t* response, |
| 51 int result = TpmReturnCode(response); | 51 int max_length) { |
| 52 if (result != TPM_SUCCESS) { | |
| 53 if (warn_only) | |
| 54 VBDEBUG(("TPM: command 0x%x failed: 0x%x\n", command, result)); | |
| 55 else | |
| 56 error("TPM: command 0x%x failed: 0x%x\n", command, result); | |
| 57 } | |
| 58 } | |
| 59 | 52 |
| 60 /* Sends a TPM command and gets a response. */ | 53 uint32_t result; |
| 61 static void TlclSendReceive(uint8_t* request, uint8_t* response, | |
| 62 int max_length) { | |
| 63 | 54 |
| 64 #ifdef EXTRA_LOGGING | 55 #ifdef EXTRA_LOGGING |
| 65 VBDEBUG(("TPM: command: %x%x %x%x%x%x %x%x%x%x\n", | 56 VBDEBUG(("TPM: command: %x%x %x%x%x%x %x%x%x%x\n", |
| 66 request[0], request[1], | 57 request[0], request[1], |
| 67 request[2], request[3], request[4], request[5], | 58 request[2], request[3], request[4], request[5], |
| 68 request[6], request[7], request[8], request[9])); | 59 request[6], request[7], request[8], request[9])); |
| 69 #endif | 60 #endif |
| 70 | 61 |
| 71 TlclStubSendReceive(request, TpmCommandSize(request), | 62 result = TlclStubSendReceive(request, TpmCommandSize(request), |
| 72 response, max_length); | 63 response, max_length); |
| 64 if (0 != result) { |
| 65 /* Communication with TPM failed, so response is garbage */ |
| 66 VBDEBUG(("TPM: command 0x%x send/receive failed: 0x%x\n", |
| 67 TpmCommandCode(request), result)); |
| 68 return TPM_E_COMMUNICATION_ERROR; |
| 69 } |
| 70 /* Otherwise, use the result code from the response */ |
| 71 result = TpmReturnCode(response); |
| 73 | 72 |
| 74 #ifdef EXTRA_LOGGING | 73 #ifdef EXTRA_LOGGING |
| 75 VBDEBUG(("TPM: response: %x%x %x%x%x%x %x%x%x%x\n", | 74 VBDEBUG(("TPM: response: %x%x %x%x%x%x %x%x%x%x\n", |
| 76 response[0], response[1], | 75 response[0], response[1], |
| 77 response[2], response[3], response[4], response[5], | 76 response[2], response[3], response[4], response[5], |
| 78 response[6], response[7], response[8], response[9])); | 77 response[6], response[7], response[8], response[9])); |
| 79 #endif | 78 #endif |
| 80 | 79 |
| 81 #ifdef VBOOT_DEBUG | 80 VBDEBUG(("TPM: command 0x%x returned 0x%x\n", |
| 82 { | 81 TpmCommandCode(request), result)); |
| 83 int command = TpmCommandCode(request); | 82 |
| 84 int result = TpmReturnCode(response); | 83 return result; |
| 85 VBDEBUG(("TPM: command 0x%x returned 0x%x\n", command, result)); | |
| 86 } | |
| 87 #endif | |
| 88 } | 84 } |
| 89 | 85 |
| 90 | 86 |
| 91 /* Sends a command and returns the error code. */ | 87 /* Sends a command and returns the error code. */ |
| 92 static uint32_t Send(uint8_t* command) { | 88 static uint32_t Send(uint8_t* command) { |
| 93 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 89 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 94 TlclSendReceive(command, response, sizeof(response)); | 90 return TlclSendReceive(command, response, sizeof(response)); |
| 95 return TpmReturnCode(response); | |
| 96 } | 91 } |
| 97 | 92 |
| 98 /* Exported functions. */ | 93 /* Exported functions. */ |
| 99 | 94 |
| 100 void TlclLibInit(void) { | 95 void TlclLibInit(void) { |
| 101 TlclStubInit(); | 96 TlclStubInit(); |
| 102 } | 97 } |
| 103 | 98 |
| 104 uint32_t TlclStartup(void) { | 99 uint32_t TlclStartup(void) { |
| 105 VBDEBUG(("TPM: Startup\n")); | 100 VBDEBUG(("TPM: Startup\n")); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 134 | 129 |
| 135 VBDEBUG(("TPM: TlclWrite(0x%x, %d)\n", index, length)); | 130 VBDEBUG(("TPM: TlclWrite(0x%x, %d)\n", index, length)); |
| 136 Memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); | 131 Memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd)); |
| 137 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); | 132 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); |
| 138 SetTpmCommandSize(cmd.buffer, total_length); | 133 SetTpmCommandSize(cmd.buffer, total_length); |
| 139 | 134 |
| 140 ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.index, index); | 135 ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.index, index); |
| 141 ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.length, length); | 136 ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.length, length); |
| 142 Memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); | 137 Memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length); |
| 143 | 138 |
| 144 TlclSendReceive(cmd.buffer, response, sizeof(response)); | 139 return TlclSendReceive(cmd.buffer, response, sizeof(response)); |
| 145 CheckResult(cmd.buffer, response, 1); | |
| 146 | |
| 147 return TpmReturnCode(response); | |
| 148 } | 140 } |
| 149 | 141 |
| 150 uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) { | 142 uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) { |
| 151 struct s_tpm_nv_read_cmd cmd; | 143 struct s_tpm_nv_read_cmd cmd; |
| 152 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 144 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 153 uint32_t result_length; | 145 uint32_t result_length; |
| 154 uint32_t result; | 146 uint32_t result; |
| 155 | 147 |
| 156 VBDEBUG(("TPM: TlclRead(0x%x, %d)\n", index, length)); | 148 VBDEBUG(("TPM: TlclRead(0x%x, %d)\n", index, length)); |
| 157 Memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); | 149 Memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd)); |
| 158 ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.index, index); | 150 ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.index, index); |
| 159 ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.length, length); | 151 ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.length, length); |
| 160 | 152 |
| 161 TlclSendReceive(cmd.buffer, response, sizeof(response)); | 153 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); |
| 162 result = TpmReturnCode(response); | |
| 163 if (result == TPM_SUCCESS && length > 0) { | 154 if (result == TPM_SUCCESS && length > 0) { |
| 164 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; | 155 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; |
| 165 FromTpmUint32(nv_read_cursor, &result_length); | 156 FromTpmUint32(nv_read_cursor, &result_length); |
| 166 nv_read_cursor += sizeof(uint32_t); | 157 nv_read_cursor += sizeof(uint32_t); |
| 167 Memcpy(data, nv_read_cursor, result_length); | 158 Memcpy(data, nv_read_cursor, result_length); |
| 168 } | 159 } |
| 169 | 160 |
| 170 return result; | 161 return result; |
| 171 } | 162 } |
| 172 | 163 |
| 173 uint32_t TlclWriteLock(uint32_t index) { | 164 uint32_t TlclWriteLock(uint32_t index) { |
| 174 VBDEBUG(("TPM: Write lock 0x%x\n", index)); | 165 VBDEBUG(("TPM: Write lock 0x%x\n", index)); |
| 175 return TlclWrite(index, NULL, 0); | 166 return TlclWrite(index, NULL, 0); |
| 176 } | 167 } |
| 177 | 168 |
| 178 uint32_t TlclReadLock(uint32_t index) { | 169 uint32_t TlclReadLock(uint32_t index) { |
| 179 VBDEBUG(("TPM: Read lock 0x%x\n", index)); | 170 VBDEBUG(("TPM: Read lock 0x%x\n", index)); |
| 180 return TlclRead(index, NULL, 0); | 171 return TlclRead(index, NULL, 0); |
| 181 } | 172 } |
| 182 | 173 |
| 183 uint32_t TlclAssertPhysicalPresence(void) { | 174 uint32_t TlclAssertPhysicalPresence(void) { |
| 184 VBDEBUG(("TPM: Asserting physical presence\n")); | 175 VBDEBUG(("TPM: Asserting physical presence\n")); |
| 185 return Send(tpm_ppassert_cmd.buffer); | 176 return Send(tpm_ppassert_cmd.buffer); |
| 186 } | 177 } |
| 187 | 178 |
| 188 uint32_t TlclAssertPhysicalPresenceResult(void) { | 179 uint32_t TlclAssertPhysicalPresenceResult(void) { |
| 189 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 180 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 190 TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); | 181 return TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); |
| 191 return TpmReturnCode(response); | |
| 192 } | 182 } |
| 193 | 183 |
| 194 uint32_t TlclLockPhysicalPresence(void) { | 184 uint32_t TlclLockPhysicalPresence(void) { |
| 195 VBDEBUG(("TPM: Lock physical presence\n")); | 185 VBDEBUG(("TPM: Lock physical presence\n")); |
| 196 return Send(tpm_pplock_cmd.buffer); | 186 return Send(tpm_pplock_cmd.buffer); |
| 197 } | 187 } |
| 198 | 188 |
| 199 uint32_t TlclSetNvLocked(void) { | 189 uint32_t TlclSetNvLocked(void) { |
| 200 VBDEBUG(("TPM: Set NV locked\n")); | 190 VBDEBUG(("TPM: Set NV locked\n")); |
| 201 return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); | 191 return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); |
| 202 } | 192 } |
| 203 | 193 |
| 204 int TlclIsOwned(void) { | 194 int TlclIsOwned(void) { |
| 205 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; | 195 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; |
| 206 uint32_t result; | 196 uint32_t result; |
| 207 TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); | 197 result = TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response))
; |
| 208 result = TpmReturnCode(response); | |
| 209 return (result != TPM_SUCCESS); | 198 return (result != TPM_SUCCESS); |
| 210 } | 199 } |
| 211 | 200 |
| 212 uint32_t TlclForceClear(void) { | 201 uint32_t TlclForceClear(void) { |
| 213 VBDEBUG(("TPM: Force clear\n")); | 202 VBDEBUG(("TPM: Force clear\n")); |
| 214 return Send(tpm_forceclear_cmd.buffer); | 203 return Send(tpm_forceclear_cmd.buffer); |
| 215 } | 204 } |
| 216 | 205 |
| 217 uint32_t TlclSetEnable(void) { | 206 uint32_t TlclSetEnable(void) { |
| 218 VBDEBUG(("TPM: Enabling TPM\n")); | 207 VBDEBUG(("TPM: Enabling TPM\n")); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 232 return Send(cmd.buffer); | 221 return Send(cmd.buffer); |
| 233 } | 222 } |
| 234 | 223 |
| 235 uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated, uint8_t *nvlocked)
{ | 224 uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated, uint8_t *nvlocked)
{ |
| 236 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 225 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 237 TPM_PERMANENT_FLAGS* pflags; | 226 TPM_PERMANENT_FLAGS* pflags; |
| 238 uint32_t result; | 227 uint32_t result; |
| 239 uint32_t size; | 228 uint32_t size; |
| 240 VBDEBUG(("TPM: Get flags\n")); | 229 VBDEBUG(("TPM: Get flags\n")); |
| 241 | 230 |
| 242 TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); | 231 result = TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); |
| 243 result = TpmReturnCode(response); | 232 if (result != TPM_SUCCESS) |
| 244 if (result != TPM_SUCCESS) { | |
| 245 return result; | 233 return result; |
| 246 } | 234 |
| 247 FromTpmUint32(response + kTpmResponseHeaderLength, &size); | 235 FromTpmUint32(response + kTpmResponseHeaderLength, &size); |
| 248 assert(size == sizeof(TPM_PERMANENT_FLAGS)); | 236 assert(size == sizeof(TPM_PERMANENT_FLAGS)); |
| 249 pflags = | 237 pflags = |
| 250 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); | 238 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); |
| 251 VBDEBUG(("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", | 239 VBDEBUG(("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", |
| 252 pflags->disable, pflags->deactivated, pflags->nvLocked)); | 240 pflags->disable, pflags->deactivated, pflags->nvLocked)); |
| 253 if (disable) | 241 if (disable) |
| 254 *disable = pflags->disable; | 242 *disable = pflags->disable; |
| 255 if (deactivated) | 243 if (deactivated) |
| 256 *deactivated = pflags->deactivated; | 244 *deactivated = pflags->deactivated; |
| 257 if (nvlocked) | 245 if (nvlocked) |
| 258 *nvlocked = pflags->nvLocked; | 246 *nvlocked = pflags->nvLocked; |
| 259 return result; | 247 return result; |
| 260 } | 248 } |
| 261 | 249 |
| 262 uint32_t TlclSetGlobalLock(void) { | 250 uint32_t TlclSetGlobalLock(void) { |
| 263 uint32_t x; | 251 uint32_t x; |
| 264 VBDEBUG(("TPM: Set Set global lock\n")); | 252 VBDEBUG(("TPM: Set global lock\n")); |
| 265 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); | 253 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); |
| 266 } | 254 } |
| 267 | 255 |
| 268 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) { | 256 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) { |
| 269 struct s_tpm_extend_cmd cmd; | 257 struct s_tpm_extend_cmd cmd; |
| 270 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; | 258 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; |
| 259 uint32_t result; |
| 271 | 260 |
| 272 Memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); | 261 Memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd)); |
| 273 ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); | 262 ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num); |
| 274 Memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); | 263 Memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength); |
| 275 TlclSendReceive(cmd.buffer, response, sizeof(response)); | 264 |
| 265 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); |
| 266 if (result != TPM_SUCCESS) |
| 267 return result; |
| 268 |
| 276 Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); | 269 Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); |
| 277 return TpmReturnCode(response); | 270 return result; |
| 278 } | 271 } |
| 279 | 272 |
| 280 uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) { | 273 uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) { |
| 281 struct s_tpm_getpermissions_cmd cmd; | 274 struct s_tpm_getpermissions_cmd cmd; |
| 282 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 275 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 283 uint8_t* nvdata; | 276 uint8_t* nvdata; |
| 284 uint32_t result; | 277 uint32_t result; |
| 285 uint32_t size; | 278 uint32_t size; |
| 286 | 279 |
| 287 Memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd)); | 280 Memcpy(&cmd, &tpm_getpermissions_cmd, sizeof(cmd)); |
| 288 ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index); | 281 ToTpmUint32(cmd.buffer + tpm_getpermissions_cmd.index, index); |
| 289 TlclSendReceive(cmd.buffer, response, sizeof(response)); | 282 result = TlclSendReceive(cmd.buffer, response, sizeof(response)); |
| 290 result = TpmReturnCode(response); | 283 if (result != TPM_SUCCESS) |
| 291 if (result != TPM_SUCCESS) { | |
| 292 return result; | 284 return result; |
| 293 } | 285 |
| 294 nvdata = response + kTpmResponseHeaderLength + sizeof(size); | 286 nvdata = response + kTpmResponseHeaderLength + sizeof(size); |
| 295 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); | 287 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); |
| 296 return result; | 288 return result; |
| 297 } | 289 } |
| OLD | NEW |