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 |