| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 static INLINE int TpmReturnCode(const uint8_t* buffer) { | 45 static INLINE int TpmReturnCode(const uint8_t* buffer) { |
| 46 return TpmCommandCode(buffer); | 46 return TpmCommandCode(buffer); |
| 47 } | 47 } |
| 48 | 48 |
| 49 /* Checks for errors in a TPM response. */ | 49 /* Checks for errors in a TPM response. */ |
| 50 static void CheckResult(uint8_t* request, uint8_t* response, int warn_only) { | 50 static void CheckResult(uint8_t* request, uint8_t* response, int warn_only) { |
| 51 int command = TpmCommandCode(request); | 51 int command = TpmCommandCode(request); |
| 52 int result = TpmReturnCode(response); | 52 int result = TpmReturnCode(response); |
| 53 if (result != TPM_SUCCESS) { | 53 if (result != TPM_SUCCESS) { |
| 54 if (warn_only) | 54 if (warn_only) |
| 55 VBDEBUG(("TPM command %d 0x%x failed: %d 0x%x\n", | 55 VBDEBUG(("TPM: command 0x%x failed: 0x%x\n", command, result)); |
| 56 command, command, result, result)); | |
| 57 else | 56 else |
| 58 error("TPM command %d 0x%x failed: %d 0x%x\n", | 57 error("TPM: command 0x%x failed: 0x%x\n", command, result); |
| 59 command, command, result, result); | |
| 60 } | 58 } |
| 61 } | 59 } |
| 62 | 60 |
| 63 /* Sends a TPM command and gets a response. */ | 61 /* Sends a TPM command and gets a response. */ |
| 64 static void TlclSendReceive(uint8_t* request, uint8_t* response, | 62 static void TlclSendReceive(uint8_t* request, uint8_t* response, |
| 65 int max_length) { | 63 int max_length) { |
| 64 |
| 66 TlclStubSendReceive(request, TpmCommandSize(request), | 65 TlclStubSendReceive(request, TpmCommandSize(request), |
| 67 response, max_length); | 66 response, max_length); |
| 67 |
| 68 #ifdef VBOOT_DEBUG |
| 69 { |
| 70 int command = TpmCommandCode(request); |
| 71 int result = TpmReturnCode(response); |
| 72 VBDEBUG(("TPM: command 0x%x returned 0x%x\n", command, result)); |
| 73 } |
| 74 #endif |
| 68 } | 75 } |
| 69 | 76 |
| 70 | 77 |
| 71 /* Sends a command and returns the error code. */ | 78 /* Sends a command and returns the error code. */ |
| 72 static uint32_t Send(uint8_t* command) { | 79 static uint32_t Send(uint8_t* command) { |
| 73 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 80 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 74 TlclSendReceive(command, response, sizeof(response)); | 81 TlclSendReceive(command, response, sizeof(response)); |
| 75 return TpmReturnCode(response); | 82 return TpmReturnCode(response); |
| 76 } | 83 } |
| 77 | 84 |
| 78 /* Exported functions. */ | 85 /* Exported functions. */ |
| 79 | 86 |
| 80 void TlclLibInit(void) { | 87 void TlclLibInit(void) { |
| 81 TlclStubInit(); | 88 TlclStubInit(); |
| 82 } | 89 } |
| 83 | 90 |
| 84 uint32_t TlclStartup(void) { | 91 uint32_t TlclStartup(void) { |
| 92 VBDEBUG(("TPM: Startup\n")); |
| 85 return Send(tpm_startup_cmd.buffer); | 93 return Send(tpm_startup_cmd.buffer); |
| 86 } | 94 } |
| 87 | 95 |
| 88 uint32_t TlclSelftestfull(void) { | 96 uint32_t TlclSelfTestFull(void) { |
| 97 VBDEBUG(("TPM: Self test full\n")); |
| 89 return Send(tpm_selftestfull_cmd.buffer); | 98 return Send(tpm_selftestfull_cmd.buffer); |
| 90 } | 99 } |
| 91 | 100 |
| 92 uint32_t TlclContinueSelfTest(void) { | 101 uint32_t TlclContinueSelfTest(void) { |
| 102 VBDEBUG(("TPM: Continue self test\n")); |
| 93 return Send(tpm_continueselftest_cmd.buffer); | 103 return Send(tpm_continueselftest_cmd.buffer); |
| 94 } | 104 } |
| 95 | 105 |
| 96 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { | 106 uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { |
| 107 VBDEBUG(("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size)); |
| 97 ToTpmUint32(tpm_nv_definespace_cmd.index, index); | 108 ToTpmUint32(tpm_nv_definespace_cmd.index, index); |
| 98 ToTpmUint32(tpm_nv_definespace_cmd.perm, perm); | 109 ToTpmUint32(tpm_nv_definespace_cmd.perm, perm); |
| 99 ToTpmUint32(tpm_nv_definespace_cmd.size, size); | 110 ToTpmUint32(tpm_nv_definespace_cmd.size, size); |
| 100 return Send(tpm_nv_definespace_cmd.buffer); | 111 return Send(tpm_nv_definespace_cmd.buffer); |
| 101 } | 112 } |
| 102 | 113 |
| 103 uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) { | 114 uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) { |
| 104 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 115 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 105 const int total_length = | 116 const int total_length = |
| 106 kTpmRequestHeaderLength + kWriteInfoLength + length; | 117 kTpmRequestHeaderLength + kWriteInfoLength + length; |
| 107 | 118 |
| 119 VBDEBUG(("TPM: TlclWrite(0x%x, %d)\n", index, length)); |
| 108 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); | 120 assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); |
| 109 SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length); | 121 SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length); |
| 110 | 122 |
| 111 ToTpmUint32(tpm_nv_write_cmd.index, index); | 123 ToTpmUint32(tpm_nv_write_cmd.index, index); |
| 112 ToTpmUint32(tpm_nv_write_cmd.length, length); | 124 ToTpmUint32(tpm_nv_write_cmd.length, length); |
| 113 Memcpy(tpm_nv_write_cmd.data, data, length); | 125 Memcpy(tpm_nv_write_cmd.data, data, length); |
| 114 | 126 |
| 115 TlclSendReceive(tpm_nv_write_cmd.buffer, response, sizeof(response)); | 127 TlclSendReceive(tpm_nv_write_cmd.buffer, response, sizeof(response)); |
| 116 CheckResult(tpm_nv_write_cmd.buffer, response, 1); | 128 CheckResult(tpm_nv_write_cmd.buffer, response, 1); |
| 117 | 129 |
| 118 return TpmReturnCode(response); | 130 return TpmReturnCode(response); |
| 119 } | 131 } |
| 120 | 132 |
| 121 uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) { | 133 uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) { |
| 122 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 134 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 123 uint32_t result_length; | 135 uint32_t result_length; |
| 124 uint32_t result; | 136 uint32_t result; |
| 125 | 137 |
| 138 VBDEBUG(("TPM: TlclRead(0x%x, %d)\n", index, length)); |
| 126 ToTpmUint32(tpm_nv_read_cmd.index, index); | 139 ToTpmUint32(tpm_nv_read_cmd.index, index); |
| 127 ToTpmUint32(tpm_nv_read_cmd.length, length); | 140 ToTpmUint32(tpm_nv_read_cmd.length, length); |
| 128 | 141 |
| 129 TlclSendReceive(tpm_nv_read_cmd.buffer, response, sizeof(response)); | 142 TlclSendReceive(tpm_nv_read_cmd.buffer, response, sizeof(response)); |
| 130 result = TpmReturnCode(response); | 143 result = TpmReturnCode(response); |
| 131 if (result == TPM_SUCCESS && length > 0) { | 144 if (result == TPM_SUCCESS && length > 0) { |
| 132 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; | 145 uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; |
| 133 FromTpmUint32(nv_read_cursor, &result_length); | 146 FromTpmUint32(nv_read_cursor, &result_length); |
| 134 nv_read_cursor += sizeof(uint32_t); | 147 nv_read_cursor += sizeof(uint32_t); |
| 135 Memcpy(data, nv_read_cursor, result_length); | 148 Memcpy(data, nv_read_cursor, result_length); |
| 136 } | 149 } |
| 137 | 150 |
| 138 return result; | 151 return result; |
| 139 } | 152 } |
| 140 | 153 |
| 141 uint32_t TlclWriteLock(uint32_t index) { | 154 uint32_t TlclWriteLock(uint32_t index) { |
| 155 VBDEBUG(("TPM: Write lock 0x%x\n", index)); |
| 142 return TlclWrite(index, NULL, 0); | 156 return TlclWrite(index, NULL, 0); |
| 143 } | 157 } |
| 144 | 158 |
| 145 uint32_t TlclReadLock(uint32_t index) { | 159 uint32_t TlclReadLock(uint32_t index) { |
| 160 VBDEBUG(("TPM: Read lock 0x%x\n", index)); |
| 146 return TlclRead(index, NULL, 0); | 161 return TlclRead(index, NULL, 0); |
| 147 } | 162 } |
| 148 | 163 |
| 149 uint32_t TlclAssertPhysicalPresence(void) { | 164 uint32_t TlclAssertPhysicalPresence(void) { |
| 165 VBDEBUG(("TPM: Asserting physical presence\n")); |
| 150 return Send(tpm_ppassert_cmd.buffer); | 166 return Send(tpm_ppassert_cmd.buffer); |
| 151 } | 167 } |
| 152 | 168 |
| 153 uint32_t TlclAssertPhysicalPresenceResult(void) { | 169 uint32_t TlclAssertPhysicalPresenceResult(void) { |
| 154 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 170 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 155 TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); | 171 TlclSendReceive(tpm_ppassert_cmd.buffer, response, sizeof(response)); |
| 156 return TpmReturnCode(response); | 172 return TpmReturnCode(response); |
| 157 } | 173 } |
| 158 | 174 |
| 159 uint32_t TlclLockPhysicalPresence(void) { | 175 uint32_t TlclLockPhysicalPresence(void) { |
| 176 VBDEBUG(("TPM: Lock physical presence\n")); |
| 160 return Send(tpm_pplock_cmd.buffer); | 177 return Send(tpm_pplock_cmd.buffer); |
| 161 } | 178 } |
| 162 | 179 |
| 163 uint32_t TlclSetNvLocked(void) { | 180 uint32_t TlclSetNvLocked(void) { |
| 181 VBDEBUG(("TPM: Set NV locked\n")); |
| 164 return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); | 182 return TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); |
| 165 } | 183 } |
| 166 | 184 |
| 167 int TlclIsOwned(void) { | 185 int TlclIsOwned(void) { |
| 168 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; | 186 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE + TPM_PUBEK_SIZE]; |
| 169 uint32_t result; | 187 uint32_t result; |
| 170 TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); | 188 TlclSendReceive(tpm_readpubek_cmd.buffer, response, sizeof(response)); |
| 171 result = TpmReturnCode(response); | 189 result = TpmReturnCode(response); |
| 172 return (result != TPM_SUCCESS); | 190 return (result != TPM_SUCCESS); |
| 173 } | 191 } |
| 174 | 192 |
| 175 uint32_t TlclForceClear(void) { | 193 uint32_t TlclForceClear(void) { |
| 194 VBDEBUG(("TPM: Force clear\n")); |
| 176 return Send(tpm_forceclear_cmd.buffer); | 195 return Send(tpm_forceclear_cmd.buffer); |
| 177 } | 196 } |
| 178 | 197 |
| 179 uint32_t TlclSetEnable(void) { | 198 uint32_t TlclSetEnable(void) { |
| 199 VBDEBUG(("TPM: Enabling TPM\n")); |
| 180 return Send(tpm_physicalenable_cmd.buffer); | 200 return Send(tpm_physicalenable_cmd.buffer); |
| 181 } | 201 } |
| 182 | 202 |
| 183 uint32_t TlclClearEnable(void) { | 203 uint32_t TlclClearEnable(void) { |
| 204 VBDEBUG(("TPM: Disabling TPM\n")); |
| 184 return Send(tpm_physicaldisable_cmd.buffer); | 205 return Send(tpm_physicaldisable_cmd.buffer); |
| 185 } | 206 } |
| 186 | 207 |
| 187 uint32_t TlclSetDeactivated(uint8_t flag) { | 208 uint32_t TlclSetDeactivated(uint8_t flag) { |
| 209 VBDEBUG(("TPM: SetDeactivated(%d)\n", flag)); |
| 188 *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag; | 210 *((uint8_t*)tpm_physicalsetdeactivated_cmd.deactivated) = flag; |
| 189 return Send(tpm_physicalsetdeactivated_cmd.buffer); | 211 return Send(tpm_physicalsetdeactivated_cmd.buffer); |
| 190 } | 212 } |
| 191 | 213 |
| 192 uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated) { | 214 uint32_t TlclGetFlags(uint8_t* disable, uint8_t* deactivated, uint8_t *nvlocked)
{ |
| 193 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 215 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 194 TPM_PERMANENT_FLAGS* pflags; | 216 TPM_PERMANENT_FLAGS* pflags; |
| 195 uint32_t result; | 217 uint32_t result; |
| 196 uint32_t size; | 218 uint32_t size; |
| 219 VBDEBUG(("TPM: Get flags\n")); |
| 197 | 220 |
| 198 TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); | 221 TlclSendReceive(tpm_getflags_cmd.buffer, response, sizeof(response)); |
| 199 result = TpmReturnCode(response); | 222 result = TpmReturnCode(response); |
| 200 if (result != TPM_SUCCESS) { | 223 if (result != TPM_SUCCESS) { |
| 201 return result; | 224 return result; |
| 202 } | 225 } |
| 203 FromTpmUint32(response + kTpmResponseHeaderLength, &size); | 226 FromTpmUint32(response + kTpmResponseHeaderLength, &size); |
| 204 assert(size == sizeof(TPM_PERMANENT_FLAGS)); | 227 assert(size == sizeof(TPM_PERMANENT_FLAGS)); |
| 205 pflags = | 228 pflags = |
| 206 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); | 229 (TPM_PERMANENT_FLAGS*) (response + kTpmResponseHeaderLength + sizeof(size)); |
| 207 *disable = pflags->disable; | 230 VBDEBUG(("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n", |
| 208 *deactivated = pflags->deactivated; | 231 pflags->disable, pflags->deactivated, pflags->nvLocked)); |
| 232 if (disable) |
| 233 *disable = pflags->disable; |
| 234 if (deactivated) |
| 235 *deactivated = pflags->deactivated; |
| 236 if (nvlocked) |
| 237 *nvlocked = pflags->nvLocked; |
| 209 return result; | 238 return result; |
| 210 } | 239 } |
| 211 | 240 |
| 212 uint32_t TlclSetGlobalLock(void) { | 241 uint32_t TlclSetGlobalLock(void) { |
| 213 uint32_t x; | 242 uint32_t x; |
| 243 VBDEBUG(("TPM: Set Set global lock\n")); |
| 214 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); | 244 return TlclWrite(TPM_NV_INDEX0, (uint8_t*) &x, 0); |
| 215 } | 245 } |
| 216 | 246 |
| 217 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) { | 247 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest) { |
| 218 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; | 248 uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength]; |
| 219 ToTpmUint32(tpm_extend_cmd.pcrNum, pcr_num); | 249 ToTpmUint32(tpm_extend_cmd.pcrNum, pcr_num); |
| 220 Memcpy(tpm_extend_cmd.inDigest, in_digest, kPcrDigestLength); | 250 Memcpy(tpm_extend_cmd.inDigest, in_digest, kPcrDigestLength); |
| 221 TlclSendReceive(tpm_extend_cmd.buffer, response, sizeof(response)); | 251 TlclSendReceive(tpm_extend_cmd.buffer, response, sizeof(response)); |
| 222 Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); | 252 Memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength); |
| 223 return TpmReturnCode(response); | 253 return TpmReturnCode(response); |
| 224 } | 254 } |
| 225 | 255 |
| 226 uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) { | 256 uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) { |
| 227 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; | 257 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
| 228 uint8_t* nvdata; | 258 uint8_t* nvdata; |
| 229 uint32_t result; | 259 uint32_t result; |
| 230 uint32_t size; | 260 uint32_t size; |
| 231 | 261 |
| 232 ToTpmUint32(tpm_getpermissions_cmd.index, index); | 262 ToTpmUint32(tpm_getpermissions_cmd.index, index); |
| 233 TlclSendReceive(tpm_getpermissions_cmd.buffer, response, sizeof(response)); | 263 TlclSendReceive(tpm_getpermissions_cmd.buffer, response, sizeof(response)); |
| 234 result = TpmReturnCode(response); | 264 result = TpmReturnCode(response); |
| 235 if (result != TPM_SUCCESS) { | 265 if (result != TPM_SUCCESS) { |
| 236 return result; | 266 return result; |
| 237 } | 267 } |
| 238 nvdata = response + kTpmResponseHeaderLength + sizeof(size); | 268 nvdata = response + kTpmResponseHeaderLength + sizeof(size); |
| 239 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); | 269 FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions); |
| 240 return result; | 270 return result; |
| 241 } | 271 } |
| OLD | NEW |