| 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 fields are | 8 * The general idea is that TPM commands are array of bytes whose fields are |
| 9 * mostly compile-time constant. The goal is to build much of the commands at | 9 * mostly compile-time constant. The goal is to build much of the commands at |
| 10 * compile time (or build time) and change some of the fields at run time as | 10 * compile time (or build time) and change some of the fields at run time as |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 response_tag == TPM_TAG_RSP_COMMAND) || | 196 response_tag == TPM_TAG_RSP_COMMAND) || |
| 197 (tag == TPM_TAG_RQU_AUTH1_COMMAND && | 197 (tag == TPM_TAG_RQU_AUTH1_COMMAND && |
| 198 response_tag == TPM_TAG_RSP_AUTH1_COMMAND) || | 198 response_tag == TPM_TAG_RSP_AUTH1_COMMAND) || |
| 199 (tag == TPM_TAG_RQU_AUTH2_COMMAND && | 199 (tag == TPM_TAG_RQU_AUTH2_COMMAND && |
| 200 response_tag == TPM_TAG_RSP_AUTH2_COMMAND)); | 200 response_tag == TPM_TAG_RSP_AUTH2_COMMAND)); |
| 201 assert(response_length == TpmCommandSize(response)); | 201 assert(response_length == TpmCommandSize(response)); |
| 202 #endif /* FIRMWARE */ | 202 #endif /* FIRMWARE */ |
| 203 | 203 |
| 204 } | 204 } |
| 205 | 205 |
| 206 /* Sends a command and checks the result for errors. Note that this error | 206 /* Sends a command and returns the error code. |
| 207 * checking is only meaningful when running in user mode. TODO: The entire | |
| 208 * error recovery strategy in the firmware needs more work. | |
| 209 */ | 207 */ |
| 210 static void Send(uint8_t* command) { | 208 static uint32_t Send(uint8_t* command) { |
| 211 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 209 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 212 SendReceive(command, response, sizeof(response)); | 210 SendReceive(command, response, sizeof(response)); |
| 213 CheckResult(command, response, false); | 211 return TpmReturnCode(response); |
| 214 } | 212 } |
| 215 | 213 |
| 216 | |
| 217 /* Exported functions. | 214 /* Exported functions. |
| 218 */ | 215 */ |
| 219 | 216 |
| 220 void TlclLog(char* format, ...) { | 217 void TlclLog(char* format, ...) { |
| 221 va_list ap; | 218 va_list ap; |
| 222 if (tlcl_log_level > 0) { | 219 if (tlcl_log_level > 0) { |
| 223 va_start(ap, format); | 220 va_start(ap, format); |
| 224 vprintf(format, ap); | 221 vprintf(format, ap); |
| 225 va_end(ap); | 222 va_end(ap); |
| 226 } | 223 } |
| 227 } | 224 } |
| 228 | 225 |
| 229 void TlclSetLogLevel(int level) { | 226 void TlclSetLogLevel(int level) { |
| 230 tlcl_log_level = level; | 227 tlcl_log_level = level; |
| 231 } | 228 } |
| 232 | 229 |
| 233 void TlclLibInit(void) { | 230 void TlclLibInit(void) { |
| 234 #if USE_TPM_EMULATOR | 231 #if USE_TPM_EMULATOR |
| 235 tpmemu_init(); | 232 tpmemu_init(); |
| 236 #else | 233 #else |
| 237 #if !FIRMWARE | 234 #if !FIRMWARE |
| 238 tpm_fd = open("/dev/tpm0", O_RDWR); | 235 tpm_fd = open("/dev/tpm0", O_RDWR); |
| 239 if (tpm_fd < 0) { | 236 if (tpm_fd < 0) { |
| 240 error("cannot open TPM device: %s\n", strerror(errno)); | 237 error("cannot open TPM device: %s\n", strerror(errno)); |
| 241 } | 238 } |
| 242 #endif /* !FIRMWARE */ | 239 #endif /* !FIRMWARE */ |
| 243 #endif /* USE_TPM_EMULATOR */ | 240 #endif /* USE_TPM_EMULATOR */ |
| 244 } | 241 } |
| 245 | 242 |
| 246 void TlclStartup(void) { | 243 uint32_t TlclStartup(void) { |
| 247 Send(tpm_startup_cmd.buffer); | 244 return Send(tpm_startup_cmd.buffer); |
| 248 } | 245 } |
| 249 | 246 |
| 250 void TlclSelftestfull(void) { | 247 uint32_t TlclSelftestfull(void) { |
| 251 Send(tpm_selftestfull_cmd.buffer); | 248 return Send(tpm_selftestfull_cmd.buffer); |
| 252 } | 249 } |
| 253 | 250 |
| 254 void TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { | 251 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { |
| 255 ToTpmUint32(tpm_nv_definespace_cmd.index, index); | 252 ToTpmUint32(tpm_nv_definespace_cmd.index, index); |
| 256 ToTpmUint32(tpm_nv_definespace_cmd.perm, perm); | 253 ToTpmUint32(tpm_nv_definespace_cmd.perm, perm); |
| 257 ToTpmUint32(tpm_nv_definespace_cmd.size, size); | 254 ToTpmUint32(tpm_nv_definespace_cmd.size, size); |
| 258 Send(tpm_nv_definespace_cmd.buffer); | 255 return Send(tpm_nv_definespace_cmd.buffer); |
| 259 } | 256 } |
| 260 | 257 |
| 261 uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) { | 258 uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) { |
| 262 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 259 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 263 const int total_length = | 260 const int total_length = |
| 264 kTpmRequestHeaderLength + kWriteInfoLength + length; | 261 kTpmRequestHeaderLength + kWriteInfoLength + length; |
| 265 | 262 |
| 266 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); | 263 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); |
| 267 SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length); | 264 SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length); |
| 268 | 265 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 289 if (result == TPM_SUCCESS && length > 0) { | 286 if (result == TPM_SUCCESS && length > 0) { |
| 290 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; | 287 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; |
| 291 FromTpmUint32(nv_read_cursor, &result_length); | 288 FromTpmUint32(nv_read_cursor, &result_length); |
| 292 nv_read_cursor += sizeof(uint32_t); | 289 nv_read_cursor += sizeof(uint32_t); |
| 293 memcpy(data, nv_read_cursor, result_length); | 290 memcpy(data, nv_read_cursor, result_length); |
| 294 } | 291 } |
| 295 | 292 |
| 296 return result; | 293 return result; |
| 297 } | 294 } |
| 298 | 295 |
| 299 void TlclWriteLock(uint32_t index) { | 296 uint32_t TlclWriteLock(uint32_t index) { |
| 300 if (TlclWrite(index, NULL, 0) != TPM_SUCCESS) { | 297 return TlclWrite(index, NULL, 0); |
| 301 error("failed to write lock space 0x%x\n", index); | |
| 302 } | |
| 303 } | 298 } |
| 304 | 299 |
| 305 void TlclReadLock(uint32_t index) { | 300 uint32_t TlclReadLock(uint32_t index) { |
| 306 if (TlclRead(index, NULL, 0) != TPM_SUCCESS) { | 301 return TlclRead(index, NULL, 0); |
| 307 error("failed to read lock space 0x%x\n", index); | |
| 308 } | |
| 309 } | 302 } |
| 310 | 303 |
| 311 void TlclAssertPhysicalPresence(void) { | 304 uint32_t TlclAssertPhysicalPresence(void) { |
| 312 Send(tpm_ppassert_cmd.buffer); | 305 return Send(tpm_ppassert_cmd.buffer); |
| 313 } | 306 } |
| 314 | 307 |
| 315 uint32_t TlclLockPhysicalPresence(void) { | 308 uint32_t TlclLockPhysicalPresence(void) { |
| 316 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 309 return Send(tpm_pplock_cmd.buffer); |
| 317 SendReceive(tpm_pplock_cmd.buffer, response, sizeof(response)); | |
| 318 return TpmReturnCode(response); | |
| 319 } | 310 } |
| 320 | 311 |
| 321 void TlclSetNvLocked(void) { | 312 uint32_t TlclSetNvLocked(void) { |
| 322 TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); | 313 return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); |
| 323 } | 314 } |
| 324 | 315 |
| 325 int TlclIsOwned(void) { | 316 int TlclIsOwned(void) { |
| 326 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; | 317 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; |
| 327 uint32_t result; | 318 uint32_t result; |
| 328 SendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); | 319 SendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); |
| 329 result = TpmReturnCode(response); | 320 result = TpmReturnCode(response); |
| 330 return (result != TPM_SUCCESS); | 321 return (result != TPM_SUCCESS); |
| 331 } | 322 } |
| 332 | 323 |
| 333 void TlclForceClear(void) { | 324 uint32_t TlclForceClear(void) { |
| 334 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 325 return Send(tpm_forceclear_cmd.buffer); |
| 335 uint32_t result; | |
| 336 SendReceive(tpm_forceclear_cmd.buffer, response, sizeof(response)); | |
| 337 result = TpmReturnCode(response); | |
| 338 if (result != TPM_SUCCESS) { | |
| 339 warning("ForceClear failed with code %d (0x%x)\n", result, result); | |
| 340 } | |
| 341 } | 326 } |
| 342 | 327 |
| 343 void TlclSetEnable(void) { | 328 uint32_t TlclSetEnable(void) { |
| 344 Send(tpm_physicalenable_cmd.buffer); | 329 return Send(tpm_physicalenable_cmd.buffer); |
| 345 } | 330 } |
| 346 | 331 |
| 347 int TlclSetDeactivated(uint8_t flag) { | 332 uint32_t TlclSetDeactivated(uint8_t flag) { |
| 348 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | |
| 349 uint32_t result; | |
| 350 *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag; | 333 *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag; |
| 351 SendReceive(tpm_physicalsetdeactivated_cmd.buffer, | 334 return Send(tpm_physicalsetdeactivated_cmd.buffer); |
| 352 response, sizeof(response)); | |
| 353 result = TpmReturnCode(response); | |
| 354 return result; | |
| 355 } | 335 } |
| 356 | 336 |
| 357 int TlclGetFlags(uint8_t* disable, uint8_t* deactivated) { | 337 uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated) { |
| 358 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 338 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 359 TPM_PERMANENT_FLAGS* pflags; | 339 TPM_PERMANENT_FLAGS* pflags; |
| 360 uint32_t result; | 340 uint32_t result; |
| 361 uint32_t size; | 341 uint32_t size; |
| 362 | 342 |
| 363 SendReceive(tpm_getcapability_cmd.buffer, response, sizeof(response)); | 343 SendReceive(tpm_getcapability_cmd.buffer, response, sizeof(response)); |
| 364 result = TpmReturnCode(response); | 344 result = TpmReturnCode(response); |
| 365 if (result != TPM_SUCCESS) { | 345 if (result != TPM_SUCCESS) { |
| 366 return result; | 346 return result; |
| 367 } | 347 } |
| 368 FromTpmUint32(response + kTpmResponseHeaderLength, &size); | 348 FromTpmUint32(response + kTpmResponseHeaderLength, &size); |
| 369 assert(size == sizeof(TPM_PERMANENT_FLAGS)); | 349 assert(size == sizeof(TPM_PERMANENT_FLAGS)); |
| 370 pflags = | 350 pflags = |
| 371 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); | 351 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); |
| 372 *disable = pflags->disable; | 352 *disable = pflags->disable; |
| 373 *deactivated = pflags->deactivated; | 353 *deactivated = pflags->deactivated; |
| 374 return result; | 354 return result; |
| 375 } | 355 } |
| 376 | 356 |
| 377 uint32_t TlclSetGlobalLock(void) { | 357 uint32_t TlclSetGlobalLock(void) { |
| 378 uint32_t x; | 358 uint32_t x; |
| 379 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); | 359 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); |
| 380 } | 360 } |
| OLD | NEW |