Bug Summary

File:3rdparty/vboot/firmware/lib/tpm_lite/tlcl.c
Warning:line 318, column 2
Value stored to 'cursor' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tlcl.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -resource-dir /opt/xgcc/lib/clang/17 -D CHROMEOS_ENVIRONMENT -D EC_EFS=0 -D EXTERNAL_TPM_CLEAR_REQUEST=0 -D _GNU_SOURCE -D _FILE_OFFSET_BITS=64 -D HAVE_EXECINFO_H -D HAVE_CROSID -D HAVE_NSS -D TPM_BLOCKING_CONTINUESELFTEST -I firmware/include -I firmware/lib/include -I firmware/lib/cgptlib/include -I firmware/lib/tpm_lite/include -I firmware/2lib/include -I host/include -I host/lib/include -I host/lib21/include -internal-isystem /opt/xgcc/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -source-date-epoch 1714465709 -Os -Wno-trigraphs -Wwrite-strings -Wno-format-security -Wno-address-of-packed-member -Wno-unknown-warning -std=gnu11 -fconst-strings -fdebug-compilation-dir=/home/coreboot/node-root/workspace/coreboot_scanbuild/3rdparty/vboot -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-opt-analyze-headers -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /cb-build/coreboot_scanbuild.0/sharedutils-scanbuildtmp/2024-05-02-073004-2299942-1 -x c firmware/lib/tpm_lite/tlcl.c
1/* Copyright 2012 The ChromiumOS Authors
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6/* A lightweight TPM command library.
7 *
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
10 * of the commands at compile time (or build time) and change some of
11 * the fields at run time as needed. The code in
12 * utility/tlcl_generator.c builds structures containing the commands,
13 * as well as the offsets of the fields that need to be set at run
14 * time.
15 */
16
17#include "2common.h"
18#include "2hmac.h"
19#include "2sha.h"
20#include "2sysincludes.h"
21#include "tlcl.h"
22#include "tlcl_internal.h"
23#include "tlcl_structures.h"
24
25/* Sets the size field of a TPM command. */
26static inline void SetTpmCommandSize(uint8_t* buffer, uint32_t size)
27{
28 ToTpmUint32(buffer + sizeof(uint16_t), size);
29}
30
31/* Gets the size field of a TPM command. */
32__attribute__((unused))
33static inline int TpmCommandSize(const uint8_t* buffer)
34{
35 uint32_t size;
36 FromTpmUint32(buffer + sizeof(uint16_t), &size);
37 return (int) size;
38}
39
40/* Gets the size field of a TPM request or response. */
41int TlclPacketSize(const uint8_t* packet)
42{
43 return TpmCommandSize(packet);
44}
45
46/* Gets the code field of a TPM command. */
47static inline int TpmCommandCode(const uint8_t* buffer)
48{
49 uint32_t code;
50 FromTpmUint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code);
51 return code;
52}
53
54/* Gets the return code field of a TPM result. */
55static inline int TpmReturnCode(const uint8_t* buffer)
56{
57 return TpmCommandCode(buffer);
58}
59
60/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or
61 * DOING_SELFTEST errors are returned.
62 */
63static uint32_t TlclSendReceiveNoRetry(const uint8_t* request,
64 uint8_t* response, int max_length)
65{
66
67 uint32_t response_length = max_length;
68 uint32_t result;
69
70#ifdef EXTRA_LOGGING
71 VB2_DEBUG("TPM: command: %x%x %x%x%x%x %x%x%x%x\n",vb2ex_printf(__func__, "TPM: command: %x%x %x%x%x%x %x%x%x%x\n"
, request[0], request[1], request[2], request[3], request[4],
request[5], request[6], request[7], request[8], request[9])
72 request[0], request[1],vb2ex_printf(__func__, "TPM: command: %x%x %x%x%x%x %x%x%x%x\n"
, request[0], request[1], request[2], request[3], request[4],
request[5], request[6], request[7], request[8], request[9])
73 request[2], request[3], request[4], request[5],vb2ex_printf(__func__, "TPM: command: %x%x %x%x%x%x %x%x%x%x\n"
, request[0], request[1], request[2], request[3], request[4],
request[5], request[6], request[7], request[8], request[9])
74 request[6], request[7], request[8], request[9])vb2ex_printf(__func__, "TPM: command: %x%x %x%x%x%x %x%x%x%x\n"
, request[0], request[1], request[2], request[3], request[4],
request[5], request[6], request[7], request[8], request[9])
;
75#endif
76
77 result = vb2ex_tpm_send_recv(request, TpmCommandSize(request),
78 response, &response_length);
79 if (TPM_SUCCESS((uint32_t) 0x00000000) != result) {
80 /* Communication with TPM failed, so response is garbage */
81 VB2_DEBUG("TPM: command %#x send/receive failed: %#x\n",vb2ex_printf(__func__, "TPM: command %#x send/receive failed: %#x\n"
, TpmCommandCode(request), result)
82 TpmCommandCode(request), result)vb2ex_printf(__func__, "TPM: command %#x send/receive failed: %#x\n"
, TpmCommandCode(request), result)
;
83 return result;
84 }
85 /* Otherwise, use the result code from the response */
86 result = TpmReturnCode(response);
87
88 /* TODO: add paranoia about returned response_length vs. max_length
89 * (and possibly expected length from the response header). See
90 * crosbug.com/17017 */
91
92#ifdef EXTRA_LOGGING
93 VB2_DEBUG("TPM: response: %x%x %x%x%x%x %x%x%x%x\n",vb2ex_printf(__func__, "TPM: response: %x%x %x%x%x%x %x%x%x%x\n"
, response[0], response[1], response[2], response[3], response
[4], response[5], response[6], response[7], response[8], response
[9])
94 response[0], response[1],vb2ex_printf(__func__, "TPM: response: %x%x %x%x%x%x %x%x%x%x\n"
, response[0], response[1], response[2], response[3], response
[4], response[5], response[6], response[7], response[8], response
[9])
95 response[2], response[3], response[4], response[5],vb2ex_printf(__func__, "TPM: response: %x%x %x%x%x%x %x%x%x%x\n"
, response[0], response[1], response[2], response[3], response
[4], response[5], response[6], response[7], response[8], response
[9])
96 response[6], response[7], response[8], response[9])vb2ex_printf(__func__, "TPM: response: %x%x %x%x%x%x %x%x%x%x\n"
, response[0], response[1], response[2], response[3], response
[4], response[5], response[6], response[7], response[8], response
[9])
;
97#endif
98
99 VB2_DEBUG("TPM: command %#x returned %#x\n",vb2ex_printf(__func__, "TPM: command %#x returned %#x\n", TpmCommandCode
(request), result)
100 TpmCommandCode(request), result)vb2ex_printf(__func__, "TPM: command %#x returned %#x\n", TpmCommandCode
(request), result)
;
101
102 return result;
103}
104
105/* Sends a TPM command and gets a response. Returns 0 if success or the TPM
106 * error code if error. In the firmware, waits for the self test to complete
107 * if needed. In the host, reports the first error without retries. */
108uint32_t TlclSendReceive(const uint8_t* request, uint8_t* response,
109 int max_length)
110{
111 uint32_t result = TlclSendReceiveNoRetry(request, response, max_length);
112 /* When compiling for the firmware, hide command failures due to the
113 * self test not having run or completed. */
114#ifndef CHROMEOS_ENVIRONMENT1
115 /* If the command fails because the self test has not completed, try it
116 * again after attempting to ensure that the self test has completed. */
117 if (result == TPM_E_NEEDS_SELFTEST((uint32_t) (0x800 + 1)) || result == TPM_E_DOING_SELFTEST((uint32_t) (0x800 + 2))) {
118 result = TlclContinueSelfTest();
119 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
120 return result;
121 }
122#if defined(TPM_BLOCKING_CONTINUESELFTEST1) || defined(VB_RECOVERY_MODE)
123 /* Retry only once */
124 result = TlclSendReceiveNoRetry(request, response, max_length);
125#else
126 /* This needs serious testing. The TPM specification says:
127 * "iii. The caller MUST wait for the actions of
128 * TPM_ContinueSelfTest to complete before reissuing the
129 * command C1." But, if ContinueSelfTest is non-blocking, how
130 * do we know that the actions have completed other than trying
131 * again? */
132 do {
133 result = TlclSendReceiveNoRetry(request, response,
134 max_length);
135 } while (result == TPM_E_DOING_SELFTEST((uint32_t) (0x800 + 2)));
136#endif
137 }
138#endif /* ! defined(CHROMEOS_ENVIRONMENT) */
139 return result;
140}
141
142/* Sends a command and returns the error code. */
143static uint32_t Send(const uint8_t* command)
144{
145 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
146 return TlclSendReceive(command, response, sizeof(response));
147}
148
149#ifdef CHROMEOS_ENVIRONMENT1
150
151struct auth_session
152{
153 uint32_t handle;
154 TPM_NONCE nonce_even;
155 TPM_NONCE nonce_odd;
156 uint8_t shared_secret[TPM_AUTH_DATA_LEN0x14];
157 uint8_t valid;
158};
159
160static uint32_t StartOIAPSession(struct auth_session* session,
161 const uint8_t secret[TPM_AUTH_DATA_LEN0x14])
162{
163 session->valid = 0;
164
165 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
166 uint32_t result = TlclSendReceive(tpm_oiap_cmd.buffer, response,
167 sizeof(response));
168 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
169 return result;
170 }
171
172 uint32_t size;
173 FromTpmUint32(response + sizeof(uint16_t), &size);
174 if (size < kTpmResponseHeaderLength10 + sizeof(uint32_t)
175 + sizeof(TPM_NONCE)) {
176 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
177 }
178
179 const uint8_t* cursor = response + kTpmResponseHeaderLength10;
180 session->handle = ReadTpmUint32(&cursor);
181 memcpy(session->nonce_even.nonce, cursor, sizeof(TPM_NONCE));
182 cursor += sizeof(TPM_NONCE);
183 VB2_ASSERT(cursor - response <= TPM_LARGE_ENOUGH_COMMAND_SIZE)do { if (!(cursor - response <= 256)) { vb2ex_printf(__func__
, "assertion failed: %s at %s:%d\n", "cursor - response <= TPM_LARGE_ENOUGH_COMMAND_SIZE"
, "firmware/lib/tpm_lite/tlcl.c", 183); vb2ex_abort(); for (;
;); } } while (0)
;
184
185 memcpy(session->shared_secret, secret, TPM_AUTH_DATA_LEN0x14);
186 session->valid = 1;
187
188 return result;
189}
190
191static uint32_t StartOSAPSession(
192 struct auth_session* session,
193 uint16_t entity_type,
194 uint32_t entity_value,
195 const uint8_t entity_usage_auth[TPM_AUTH_DATA_LEN0x14])
196{
197 session->valid = 0;
198
199 /* Build OSAP command. */
200 struct s_tpm_osap_cmd cmd;
201 memcpy(&cmd, &tpm_osap_cmd, sizeof(cmd));
202 ToTpmUint16(cmd.buffer + cmd.entityType, entity_type);
203 ToTpmUint32(cmd.buffer + cmd.entityValue, entity_value);
204 if (vb2ex_tpm_get_random(cmd.buffer + cmd.nonceOddOSAP,
205 sizeof(TPM_NONCE)) != VB2_SUCCESS) {
206 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
207 }
208
209 /* Send OSAP command. */
210 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
211 uint32_t result = TlclSendReceive(cmd.buffer, response,
212 sizeof(response));
213 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
214 return result;
215 }
216
217 /* Parse response. */
218 uint32_t size;
219 FromTpmUint32(response + sizeof(uint16_t), &size);
220 if (size < kTpmResponseHeaderLength10 + sizeof(uint32_t)
221 + 2 * sizeof(TPM_NONCE)) {
222 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
223 }
224
225 const uint8_t* cursor = response + kTpmResponseHeaderLength10;
226 session->handle = ReadTpmUint32(&cursor);
227 memcpy(session->nonce_even.nonce, cursor, sizeof(TPM_NONCE));
228 cursor += sizeof(TPM_NONCE);
229 const uint8_t* nonce_even_osap = cursor;
230 cursor += sizeof(TPM_NONCE);
231 VB2_ASSERT(cursor - response <= TPM_LARGE_ENOUGH_COMMAND_SIZE)do { if (!(cursor - response <= 256)) { vb2ex_printf(__func__
, "assertion failed: %s at %s:%d\n", "cursor - response <= TPM_LARGE_ENOUGH_COMMAND_SIZE"
, "firmware/lib/tpm_lite/tlcl.c", 231); vb2ex_abort(); for (;
;); } } while (0)
;
232
233 /* Compute shared secret */
234 uint8_t hmac_input[2 * sizeof(TPM_NONCE)];
235 memcpy(hmac_input, nonce_even_osap, sizeof(TPM_NONCE));
236 memcpy(hmac_input + sizeof(TPM_NONCE), cmd.buffer + cmd.nonceOddOSAP,
237 sizeof(TPM_NONCE));
238 struct vb2_hash mac;
239 if (vb2_hmac_calculate(false0, VB2_HASH_SHA1, entity_usage_auth, TPM_AUTH_DATA_LEN0x14,
240 hmac_input, sizeof(hmac_input), &mac)) {
241 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
242 }
243
244 _Static_assert(sizeof(session->shared_secret) == VB2_SHA1_DIGEST_SIZE20,
245 "The output size should match the sha1 digest size.");
246 memcpy(session->shared_secret, mac.raw, sizeof(session->shared_secret));
247
248 session->valid = 1;
249
250 return result;
251}
252
253/* Fills in the authentication block at the end of the command. The command body
254 * should already be initialized in |command_buffer|, and the included command
255 * size should account for the auth block that gets filled in. */
256static uint32_t AddRequestAuthBlock(struct auth_session* auth_session,
257 uint8_t* command_buffer,
258 uint32_t command_buffer_size,
259 uint8_t continue_auth_session)
260{
261 if (!auth_session->valid) {
262 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
263 }
264
265 /* Validity check to make sure the command buffer has sufficient space
266 * to add the auth block at the end of the command. */
267 if (command_buffer_size < kTpmRequestHeaderLength10) {
268 return TPM_E_BUFFER_SIZE((uint32_t) 0x0000500f);
269 }
270 const uint32_t size = TpmCommandSize(command_buffer);
271 if (size < kTpmResponseHeaderLength10 + kTpmRequestAuthBlockLength(sizeof(uint32_t) + sizeof(TPM_NONCE) + 1 + 0x14) ||
272 size > command_buffer_size) {
273 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
274 }
275 const uint32_t auth_offset = size - kTpmRequestAuthBlockLength(sizeof(uint32_t) + sizeof(TPM_NONCE) + 1 + 0x14);
276
277 /*
278 * The digest of the command is computed over the command buffer, but
279 * excluding the leading tag and paramSize fields.
280 */
281 struct vb2_sha1_context sha1_ctx;
282 vb2_sha1_init(&sha1_ctx);
283 vb2_sha1_update(&sha1_ctx,
284 command_buffer + sizeof(uint16_t) + sizeof(uint32_t),
285 auth_offset - sizeof(uint16_t) - sizeof(uint32_t));
286 uint8_t buf[TPM_SHA1_160_HASH_LEN0x14 + 2 * sizeof(TPM_NONCE) + 1];
287 vb2_sha1_finalize(&sha1_ctx, buf);
288
289 /* Generate a fresh nonce. */
290 if (vb2ex_tpm_get_random(auth_session->nonce_odd.nonce,
291 sizeof(TPM_NONCE)) != VB2_SUCCESS) {
292 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
293 }
294
295 /* Append the authentication block to the command buffer. */
296 uint8_t* cursor = command_buffer + auth_offset;
297 ToTpmUint32(cursor, auth_session->handle);
298 cursor += sizeof(uint32_t);
299 memcpy(cursor, auth_session->nonce_odd.nonce, sizeof(TPM_NONCE));
300 cursor += sizeof(TPM_NONCE);
301 *cursor++ = continue_auth_session;
302
303 /* Compute and append the MAC. */
304 memcpy(buf + TPM_SHA1_160_HASH_LEN0x14, auth_session->nonce_even.nonce,
305 sizeof(TPM_NONCE));
306 memcpy(buf + TPM_SHA1_160_HASH_LEN0x14 + sizeof(TPM_NONCE),
307 auth_session->nonce_odd.nonce, sizeof(TPM_NONCE));
308 buf[TPM_SHA1_160_HASH_LEN0x14 + 2 * sizeof(TPM_NONCE)] =
309 continue_auth_session;
310 struct vb2_hash mac;
311 if (vb2_hmac_calculate(false0, VB2_HASH_SHA1, auth_session->shared_secret,
312 sizeof(auth_session->shared_secret), buf, sizeof(buf), &mac)) {
313 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
314 }
315
316 memcpy(cursor, mac.sha1, sizeof(mac.sha1));
317
318 cursor += sizeof(mac.sha1);
Value stored to 'cursor' is never read
319
320 return TPM_SUCCESS((uint32_t) 0x00000000);
321}
322
323static uint32_t CheckResponseAuthBlock(struct auth_session* auth_session,
324 TPM_COMMAND_CODE ordinal,
325 uint8_t* response_buffer,
326 uint32_t response_buffer_size)
327{
328 if (!auth_session->valid) {
329 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
330 }
331
332 if (response_buffer_size < kTpmResponseHeaderLength10) {
333 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
334 }
335
336 /* Parse and validate the actual response size from the response. */
337 uint32_t size;
338 FromTpmUint32(response_buffer + sizeof(uint16_t), &size);
339 if (size >= response_buffer_size ||
340 size < kTpmResponseHeaderLength10 + kTpmResponseAuthBlockLength(sizeof(TPM_NONCE) + 1 + 0x14)) {
341 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
342 }
343 uint32_t auth_offset = size - kTpmResponseAuthBlockLength(sizeof(TPM_NONCE) + 1 + 0x14);
344
345 /*
346 * The digest of the response is computed over the return code, ordinal,
347 * response payload.
348 */
349 struct vb2_sha1_context sha1_ctx;
350 vb2_sha1_init(&sha1_ctx);
351 vb2_sha1_update(&sha1_ctx,
352 response_buffer + sizeof(uint16_t) + sizeof(uint32_t),
353 sizeof(uint32_t));
354 uint8_t ordinal_buf[sizeof(ordinal)];
355 ToTpmUint32(ordinal_buf, ordinal);
356 vb2_sha1_update(&sha1_ctx, ordinal_buf, sizeof(ordinal_buf));
357 vb2_sha1_update(&sha1_ctx,
358 response_buffer + kTpmResponseHeaderLength10,
359 auth_offset - kTpmResponseHeaderLength10);
360 uint8_t hmac_input[TPM_SHA1_160_HASH_LEN0x14 + 2 * sizeof(TPM_NONCE) + 1];
361 vb2_sha1_finalize(&sha1_ctx, hmac_input);
362
363 /* Compute the MAC. */
364 uint8_t* cursor = response_buffer + auth_offset;
365 memcpy(hmac_input + TPM_SHA1_160_HASH_LEN0x14, cursor, sizeof(TPM_NONCE));
366 cursor += sizeof(TPM_NONCE);
367 memcpy(hmac_input + TPM_SHA1_160_HASH_LEN0x14 + sizeof(TPM_NONCE),
368 auth_session->nonce_odd.nonce, sizeof(TPM_NONCE));
369 auth_session->valid = *cursor++;
370 hmac_input[TPM_SHA1_160_HASH_LEN0x14 + 2 * sizeof(TPM_NONCE)] =
371 auth_session->valid;
372 struct vb2_hash mac;
373 if (vb2_hmac_calculate(false0, VB2_HASH_SHA1, auth_session->shared_secret,
374 sizeof(auth_session->shared_secret), hmac_input,
375 sizeof(hmac_input), &mac)) {
376 auth_session->valid = 0;
377 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
378 }
379
380 /* Check the MAC. */
381 if (vb2_safe_memcmp(mac.sha1, cursor, sizeof(mac.sha1))) {
382 auth_session->valid = 0;
383 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
384 }
385
386 /* Success, save the even nonce. */
387 memcpy(auth_session->nonce_even.nonce, response_buffer + auth_offset,
388 sizeof(TPM_NONCE));
389
390 return TPM_SUCCESS((uint32_t) 0x00000000);
391}
392
393#endif /* CHROMEOS_ENVIRONMENT */
394
395/* Exported functions. */
396
397uint32_t TlclLibInit(void)
398{
399 return vb2ex_tpm_init();
400}
401
402uint32_t TlclLibClose(void)
403{
404 return vb2ex_tpm_close();
405}
406
407uint32_t TlclStartup(void)
408{
409 VB2_DEBUG("TPM: Startup\n")vb2ex_printf(__func__, "TPM: Startup\n");
410 return Send(tpm_startup_cmd.buffer);
411}
412
413uint32_t TlclSaveState(void)
414{
415 VB2_DEBUG("TPM: SaveState\n")vb2ex_printf(__func__, "TPM: SaveState\n");
416 return Send(tpm_savestate_cmd.buffer);
417}
418
419uint32_t TlclResume(void)
420{
421 VB2_DEBUG("TPM: Resume\n")vb2ex_printf(__func__, "TPM: Resume\n");
422 return Send(tpm_resume_cmd.buffer);
423}
424
425uint32_t TlclSelfTestFull(void)
426{
427 VB2_DEBUG("TPM: Self test full\n")vb2ex_printf(__func__, "TPM: Self test full\n");
428 return Send(tpm_selftestfull_cmd.buffer);
429}
430
431uint32_t TlclContinueSelfTest(void)
432{
433 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
434 VB2_DEBUG("TPM: Continue self test\n")vb2ex_printf(__func__, "TPM: Continue self test\n");
435 /* Call the No Retry version of SendReceive to avoid recursion. */
436 return TlclSendReceiveNoRetry(tpm_continueselftest_cmd.buffer,
437 response, sizeof(response));
438}
439
440uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
441{
442 VB2_DEBUG("TPM: TlclDefineSpace(%#x, %#x, %d)\n", index, perm, size)vb2ex_printf(__func__, "TPM: TlclDefineSpace(%#x, %#x, %d)\n"
, index, perm, size)
;
443 return TlclDefineSpaceEx(NULL((void*)0), 0, index, perm, size, NULL((void*)0), 0);
444}
445
446#ifdef CHROMEOS_ENVIRONMENT1
447
448uint32_t TlclUndefineSpace(uint32_t index)
449{
450 VB2_DEBUG("TPM: TlclUndefineSpace(%#x)\n", index)vb2ex_printf(__func__, "TPM: TlclUndefineSpace(%#x)\n", index
)
;
451 return TlclUndefineSpaceEx(NULL((void*)0), 0, index);
452}
453
454uint32_t TlclUndefineSpaceEx(const uint8_t* owner_auth,
455 uint32_t owner_auth_size,
456 uint32_t index)
457{
458 return TlclDefineSpaceEx(owner_auth, owner_auth_size,
459 index, 0, 0,
460 NULL((void*)0), 0);
461}
462
463#endif /* CHROMEOS_ENVIRONMENT */
464
465uint32_t TlclDefineSpaceEx(const uint8_t* owner_auth, uint32_t owner_auth_size,
466 uint32_t index, uint32_t perm, uint32_t size,
467 const void* auth_policy, uint32_t auth_policy_size)
468{
469 uint32_t result;
470
471 /* Build the request data. */
472 uint8_t cmd[sizeof(tpm_nv_definespace_cmd.buffer) +
473 kTpmRequestAuthBlockLength(sizeof(uint32_t) + sizeof(TPM_NONCE) + 1 + 0x14)];
474 memcpy(cmd, &tpm_nv_definespace_cmd, sizeof(tpm_nv_definespace_cmd));
475 ToTpmUint32(cmd + tpm_nv_definespace_cmd.index, index);
476 ToTpmUint32(cmd + tpm_nv_definespace_cmd.perm, perm);
477 ToTpmUint32(cmd + tpm_nv_definespace_cmd.size, size);
478 if (auth_policy != NULL((void*)0)) {
479 if (auth_policy_size != sizeof(TPM_NV_AUTH_POLICY)) {
480 return TPM_E_BUFFER_SIZE((uint32_t) 0x0000500f);
481 }
482
483 const TPM_NV_AUTH_POLICY* policy = auth_policy;
484 memcpy(cmd + tpm_nv_definespace_cmd.pcr_info_read,
485 &policy->pcr_info_read, sizeof(policy->pcr_info_read));
486 memcpy(cmd + tpm_nv_definespace_cmd.pcr_info_write,
487 &policy->pcr_info_write, sizeof(policy->pcr_info_write));
488 }
489
490#ifdef CHROMEOS_ENVIRONMENT1
491 struct auth_session auth_session;
492 if (owner_auth) {
493 if (owner_auth_size != TPM_AUTH_DATA_LEN0x14) {
494 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
495 }
496
497 result = StartOSAPSession(&auth_session, TPM_ET_OWNER((uint32_t) 0x02), 0,
498 owner_auth);
499 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
500 return result;
501 }
502
503 ToTpmUint32(cmd + sizeof(uint16_t), sizeof(cmd));
504 ToTpmUint16(cmd, TPM_TAG_RQU_AUTH1_COMMAND((uint16_t) 0xc2));
505 result = AddRequestAuthBlock(&auth_session, cmd, sizeof(cmd),
506 0);
507 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
508 return result;
509 }
510 }
511#endif
512
513 /* Send the command. */
514 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
515 result = TlclSendReceive(cmd, response, sizeof(response));
516 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
517 return result;
518 }
519
520#ifdef CHROMEOS_ENVIRONMENT1
521 if (owner_auth) {
522 result = CheckResponseAuthBlock(&auth_session,
523 TPM_ORD_NV_DefineSpace((uint32_t) 0x000000CC),
524 response, sizeof(response));
525 }
526#endif
527
528 return result;
529}
530
531uint32_t TlclInitNvAuthPolicy(uint32_t pcr_selection_bitmap,
532 const uint8_t pcr_values[][TPM_PCR_DIGEST20],
533 void* auth_policy, uint32_t* auth_policy_size)
534{
535 uint32_t buffer_size = *auth_policy_size;
536 *auth_policy_size = sizeof(TPM_NV_AUTH_POLICY);
537 if (!auth_policy || buffer_size < sizeof(TPM_NV_AUTH_POLICY)) {
538 return TPM_E_BUFFER_SIZE((uint32_t) 0x0000500f);
539 }
540 TPM_NV_AUTH_POLICY* policy = auth_policy;
541
542 /* Note that although the struct definition allocates space for 3 bytes
543 * worth of PCR selection, it is technically a variably-sized field in
544 * the TPM structure definition. Since this is part of the policy
545 * digest, we need to carefully match our selection sizes. For now, we
546 * use 3 bytes, which aligns with TrouSerS behavior. */
547 TPM_PCR_SELECTION* select = &policy->pcr_info_read.pcrSelection;
548 ToTpmUint16((uint8_t*)&select->sizeOfSelect, sizeof(select->pcrSelect));
549 select->pcrSelect[0] = (pcr_selection_bitmap >> 0) & 0xff;
550 select->pcrSelect[1] = (pcr_selection_bitmap >> 8) & 0xff;
551 select->pcrSelect[2] = (pcr_selection_bitmap >> 16) & 0xff;
552 VB2_ASSERT((pcr_selection_bitmap & 0xff000000) == 0)do { if (!((pcr_selection_bitmap & 0xff000000) == 0)) { vb2ex_printf
(__func__, "assertion failed: %s at %s:%d\n", "(pcr_selection_bitmap & 0xff000000) == 0"
, "firmware/lib/tpm_lite/tlcl.c", 552); vb2ex_abort(); for (;
;); } } while (0)
;
553
554 /* Allow all localities except locality 3. Rationale:
555 *
556 * We don't actually care about restricting NVRAM access to specific
557 * localities. In fact localities aren't used in Chrome OS and locality
558 * 0 is used for everything.
559 *
560 * However, the TPM specification makes an effort to not allow NVRAM
561 * spaces that do not have some write access control configured: When
562 * defining a space, either at least one of OWNERWRITE, AUTHWRITE,
563 * WRITEDEFINE, PPWRITE or a locality restriction must be specified (See
564 * TPM_NV_DefineSpace command description in the spec).
565 *
566 * This complicates matters when defining an NVRAM space that should be
567 * writable and lockable (for the remainder of the boot cycle) by the OS
568 * even when the TPM is not owned:
569 * * OWNERWRITE doesn't work because there might be no owner.
570 * * PPWRITE restricts writing to firmware only.
571 * * Use of WRITEDEFINE prevents use of WRITE_STCLEAR (i.e. the space
572 * can either not be locked, or it would remain locked until next TPM
573 * clear).
574 * * AUTHWRITE looks workable at first sight (by setting a well-known
575 * auth secret). However writes must use TPM_NV_WriteValueAuth, which
576 * only works when the TPM is owned. Interestingly, the spec admits
577 * to that being a mistake in the TPM_NV_WriteValueAuth comment but
578 * asserts that the behavior is normative.
579 *
580 * Having ruled out all attributes, we're left with locality restriction
581 * as the only option to pass the access control requirement check in
582 * TPM_NV_DefineSpace. We choose to disallow locality 3, since that is
583 * the most unlikely one to be used in practice, i.e. the spec says
584 * locality 3 is for "Auxiliary components. Use of this is optional and,
585 * if used, it is implementation dependent."
586 */
587 policy->pcr_info_read.localityAtRelease =
588 TPM_ALL_LOCALITIES((((uint32_t)1)<<0) | (((uint32_t)1)<<1) | (((uint32_t
)1)<<2) | (((uint32_t)1)<<3) | (((uint32_t)1)<<
4))
& ~TPM_LOC_THREE(((uint32_t)1)<<3);
589
590 struct vb2_sha1_context sha1_ctx;
591 vb2_sha1_init(&sha1_ctx);
592
593 vb2_sha1_update(&sha1_ctx,
594 (const uint8_t*)&policy->pcr_info_read.pcrSelection,
595 sizeof(policy->pcr_info_read.pcrSelection));
596
597 uint32_t num_pcrs = 0;
598 int i;
599 for (i = 0; i < sizeof(pcr_selection_bitmap) * 8; ++i) {
600 if ((1U << i) & pcr_selection_bitmap) {
601 num_pcrs++;
602 }
603 }
604
605 uint8_t pcrs_size[sizeof(uint32_t)];
606 ToTpmUint32(pcrs_size, num_pcrs * TPM_PCR_DIGEST20);
607 vb2_sha1_update(&sha1_ctx, pcrs_size, sizeof(pcrs_size));
608
609 for (i = 0; i < num_pcrs; ++i) {
610 vb2_sha1_update(&sha1_ctx, pcr_values[i], TPM_PCR_DIGEST20);
611 }
612
613 vb2_sha1_finalize(&sha1_ctx,
614 policy->pcr_info_read.digestAtRelease.digest);
615
616 /* Make the write policy an identical copy of the read auth policy. */
617 memcpy(&policy->pcr_info_write, &policy->pcr_info_read,
618 sizeof(policy->pcr_info_read));
619
620 return TPM_SUCCESS((uint32_t) 0x00000000);
621}
622
623uint32_t TlclWrite(uint32_t index, const void* data, uint32_t length)
624{
625 struct s_tpm_nv_write_cmd cmd;
626 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
627 const int total_length =
628 kTpmRequestHeaderLength10 + kWriteInfoLength + length;
629
630 VB2_DEBUG("TPM: TlclWrite(%#x, %d)\n", index, length)vb2ex_printf(__func__, "TPM: TlclWrite(%#x, %d)\n", index, length
)
;
631 memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd));
632 VB2_ASSERT(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE)do { if (!(total_length <= 256)) { vb2ex_printf(__func__, "assertion failed: %s at %s:%d\n"
, "total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE", "firmware/lib/tpm_lite/tlcl.c"
, 632); vb2ex_abort(); for (;;); } } while (0)
;
633 SetTpmCommandSize(cmd.buffer, total_length);
634
635 ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.index, index);
636 ToTpmUint32(cmd.buffer + tpm_nv_write_cmd.length, length);
637 memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length);
638
639 return TlclSendReceive(cmd.buffer, response, sizeof(response));
640}
641
642uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
643{
644 struct s_tpm_nv_read_cmd cmd;
645 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
646 uint32_t result;
647
648 VB2_DEBUG("TPM: TlclRead(%#x, %d)\n", index, length)vb2ex_printf(__func__, "TPM: TlclRead(%#x, %d)\n", index, length
)
;
649 memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd));
650 ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.index, index);
651 ToTpmUint32(cmd.buffer + tpm_nv_read_cmd.length, length);
652
653 result = TlclSendReceive(cmd.buffer, response, sizeof(response));
654 if (result == TPM_SUCCESS((uint32_t) 0x00000000) && length > 0) {
655 const uint8_t* nv_read_cursor =
656 response + kTpmResponseHeaderLength10;
657 uint32_t result_length = ReadTpmUint32(&nv_read_cursor);
658 if (result_length > length)
659 result_length = length; /* Truncate to fit buffer */
660 memcpy(data, nv_read_cursor, result_length);
661 }
662
663 return result;
664}
665
666uint32_t TlclPCRRead(uint32_t index, void* data, uint32_t length)
667{
668 struct s_tpm_pcr_read_cmd cmd;
669 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
670 uint32_t result;
671
672 VB2_DEBUG("TPM: TlclPCRRead(%#x, %d)\n", index, length)vb2ex_printf(__func__, "TPM: TlclPCRRead(%#x, %d)\n", index, length
)
;
673 if (length < kPcrDigestLength20) {
674 return TPM_E_IOERROR((uint32_t) 0x0000001f);
675 }
676 memcpy(&cmd, &tpm_pcr_read_cmd, sizeof(cmd));
677 ToTpmUint32(cmd.buffer + tpm_pcr_read_cmd.pcrNum, index);
678
679 result = TlclSendReceive(cmd.buffer, response, sizeof(response));
680 if (result == TPM_SUCCESS((uint32_t) 0x00000000)) {
681 const uint8_t* pcr_read_cursor =
682 response + kTpmResponseHeaderLength10;
683 memcpy(data, pcr_read_cursor, kPcrDigestLength20);
684 }
685
686 return result;
687}
688
689uint32_t TlclWriteLock(uint32_t index)
690{
691 VB2_DEBUG("TPM: Write lock %#x\n", index)vb2ex_printf(__func__, "TPM: Write lock %#x\n", index);
692 return TlclWrite(index, NULL((void*)0), 0);
693}
694
695uint32_t TlclReadLock(uint32_t index)
696{
697 VB2_DEBUG("TPM: Read lock %#x\n", index)vb2ex_printf(__func__, "TPM: Read lock %#x\n", index);
698 return TlclRead(index, NULL((void*)0), 0);
699}
700
701uint32_t TlclAssertPhysicalPresence(void)
702{
703 VB2_DEBUG("TPM: Asserting physical presence\n")vb2ex_printf(__func__, "TPM: Asserting physical presence\n");
704 return Send(tpm_ppassert_cmd.buffer);
705}
706
707uint32_t TlclPhysicalPresenceCMDEnable(void)
708{
709 VB2_DEBUG("TPM: Enable the physical presence command\n")vb2ex_printf(__func__, "TPM: Enable the physical presence command\n"
)
;
710 return Send(tpm_ppenable_cmd.buffer);
711}
712
713uint32_t TlclFinalizePhysicalPresence(void)
714{
715 VB2_DEBUG("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n")vb2ex_printf(__func__, "TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n"
)
;
716 return Send(tpm_finalizepp_cmd.buffer);
717}
718
719uint32_t TlclAssertPhysicalPresenceResult(void)
720{
721 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
722 return TlclSendReceive(tpm_ppassert_cmd.buffer, response,
723 sizeof(response));
724}
725
726uint32_t TlclLockPhysicalPresence(void)
727{
728 VB2_DEBUG("TPM: Lock physical presence\n")vb2ex_printf(__func__, "TPM: Lock physical presence\n");
729 return Send(tpm_pplock_cmd.buffer);
730}
731
732uint32_t TlclSetNvLocked(void)
733{
734 VB2_DEBUG("TPM: Set NV locked\n")vb2ex_printf(__func__, "TPM: Set NV locked\n");
735 return TlclDefineSpace(TPM_NV_INDEX_LOCK((uint32_t) 0xffffffff), 0, 0);
736}
737
738int TlclIsOwned(void)
739{
740 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256 + TPM_PUBEK_SIZE256];
741 uint32_t result;
742 result = TlclSendReceive(tpm_readpubek_cmd.buffer,
743 response, sizeof(response));
744 return (result != TPM_SUCCESS((uint32_t) 0x00000000));
745}
746
747uint32_t TlclForceClear(void)
748{
749 VB2_DEBUG("TPM: Force clear\n")vb2ex_printf(__func__, "TPM: Force clear\n");
750 return Send(tpm_forceclear_cmd.buffer);
751}
752
753uint32_t TlclSetEnable(void)
754{
755 VB2_DEBUG("TPM: Enabling TPM\n")vb2ex_printf(__func__, "TPM: Enabling TPM\n");
756 return Send(tpm_physicalenable_cmd.buffer);
757}
758
759uint32_t TlclClearEnable(void)
760{
761 VB2_DEBUG("TPM: Disabling TPM\n")vb2ex_printf(__func__, "TPM: Disabling TPM\n");
762 return Send(tpm_physicaldisable_cmd.buffer);
763}
764
765uint32_t TlclSetDeactivated(uint8_t flag)
766{
767 struct s_tpm_physicalsetdeactivated_cmd cmd;
768 VB2_DEBUG("TPM: SetDeactivated(%d)\n", flag)vb2ex_printf(__func__, "TPM: SetDeactivated(%d)\n", flag);
769 memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd));
770 *(cmd.buffer + cmd.deactivated) = flag;
771 return Send(cmd.buffer);
772}
773
774uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS* pflags)
775{
776 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
777 uint32_t size;
778 uint32_t result = TlclSendReceive(tpm_getflags_cmd.buffer, response,
779 sizeof(response));
780 if (result != TPM_SUCCESS((uint32_t) 0x00000000))
781 return result;
782 FromTpmUint32(response + kTpmResponseHeaderLength10, &size);
783 /* TODO(crbug.com/379255): This fails. Find out why.
784 * VB2_ASSERT(size == sizeof(TPM_PERMANENT_FLAGS));
785 */
786 memcpy(pflags,
787 response + kTpmResponseHeaderLength10 + sizeof(size),
788 sizeof(TPM_PERMANENT_FLAGS));
789 return result;
790}
791
792uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS* vflags)
793{
794 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
795 uint32_t size;
796 uint32_t result = TlclSendReceive(tpm_getstclearflags_cmd.buffer,
797 response, sizeof(response));
798 if (result != TPM_SUCCESS((uint32_t) 0x00000000))
799 return result;
800 FromTpmUint32(response + kTpmResponseHeaderLength10, &size);
801 /* Ugly assertion, but the struct is padded up by one byte. */
802 /* TODO(crbug.com/379255): This fails. Find out why.
803 * VB2_ASSERT(size == 7 && sizeof(TPM_STCLEAR_FLAGS) - 1 == 7);
804 */
805 memcpy(vflags,
806 response + kTpmResponseHeaderLength10 + sizeof(size),
807 sizeof(TPM_STCLEAR_FLAGS));
808 return result;
809}
810
811uint32_t TlclGetFlags(uint8_t* disable,
812 uint8_t* deactivated,
813 uint8_t *nvlocked)
814{
815 TPM_PERMANENT_FLAGS pflags;
816 uint32_t result = TlclGetPermanentFlags(&pflags);
817 if (result == TPM_SUCCESS((uint32_t) 0x00000000)) {
818 if (disable)
819 *disable = pflags.disable;
820 if (deactivated)
821 *deactivated = pflags.deactivated;
822 if (nvlocked)
823 *nvlocked = pflags.nvLocked;
824 VB2_DEBUG("TPM: Got flags disable=%d, deactivated=%d, "vb2ex_printf(__func__, "TPM: Got flags disable=%d, deactivated=%d, "
"nvlocked=%d\n", pflags.disable, pflags.deactivated, pflags.
nvLocked)
825 "nvlocked=%d\n",vb2ex_printf(__func__, "TPM: Got flags disable=%d, deactivated=%d, "
"nvlocked=%d\n", pflags.disable, pflags.deactivated, pflags.
nvLocked)
826 pflags.disable, pflags.deactivated, pflags.nvLocked)vb2ex_printf(__func__, "TPM: Got flags disable=%d, deactivated=%d, "
"nvlocked=%d\n", pflags.disable, pflags.deactivated, pflags.
nvLocked)
;
827 }
828 return result;
829}
830
831uint32_t TlclSetGlobalLock(void)
832{
833 uint32_t x;
834 VB2_DEBUG("TPM: Set global lock\n")vb2ex_printf(__func__, "TPM: Set global lock\n");
835 return TlclWrite(TPM_NV_INDEX0((uint32_t) 0x00000000), (uint8_t*) &x, 0);
836}
837
838uint32_t TlclExtend(int pcr_num, const uint8_t* in_digest,
839 uint8_t* out_digest)
840{
841 struct s_tpm_extend_cmd cmd;
842 uint8_t response[kTpmResponseHeaderLength10 + kPcrDigestLength20];
843 uint32_t result;
844
845 memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd));
846 ToTpmUint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num);
847 memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength20);
848
849 result = TlclSendReceive(cmd.buffer, response, sizeof(response));
850 if (result != TPM_SUCCESS((uint32_t) 0x00000000))
851 return result;
852
853 memcpy(out_digest, response + kTpmResponseHeaderLength10,
854 kPcrDigestLength20);
855 return result;
856}
857
858uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions)
859{
860 uint32_t dummy_attributes;
861 TPM_NV_AUTH_POLICY dummy_policy;
862 uint32_t dummy_policy_size = sizeof(dummy_policy);
863
864 return TlclGetSpaceInfo(index, permissions, &dummy_attributes,
865 &dummy_policy, &dummy_policy_size);
866}
867
868static int DecodePCRInfo(const uint8_t** cursor,
869 const uint8_t* end,
870 TPM_PCR_INFO_SHORT* pcr_info)
871{
872 const size_t available_size = end - *cursor;
873 if (available_size < sizeof(uint16_t)) {
874 return 0;
875 }
876
877 uint16_t size_of_select = 0;
878 FromTpmUint16(*cursor, &size_of_select);
879
880 /* Compute the actual size of the encoded PCR selection (which is a
881 * variable-length field). */
882 const size_t encoded_pcr_info_size = sizeof(TPM_PCR_INFO_SHORT) -
883 sizeof(pcr_info->pcrSelection.pcrSelect) + size_of_select;
884 if (available_size < encoded_pcr_info_size ||
885 size_of_select > sizeof(pcr_info->pcrSelection.pcrSelect)) {
886 return 0;
887 }
888
889 memset(&pcr_info->pcrSelection, 0, sizeof(pcr_info->pcrSelection));
890 const size_t pcr_selection_size =
891 sizeof(size_of_select) + size_of_select;
892 memcpy(&pcr_info->pcrSelection, *cursor, pcr_selection_size);
893 *cursor += pcr_selection_size;
894
895 pcr_info->localityAtRelease = **cursor;
896 (*cursor)++;
897
898 memcpy(&pcr_info->digestAtRelease, *cursor, sizeof(TPM_COMPOSITE_HASH));
899 *cursor += sizeof(TPM_COMPOSITE_HASH);
900
901 return 1;
902}
903
904uint32_t TlclGetSpaceInfo(uint32_t index, uint32_t *attributes, uint32_t *size,
905 void* auth_policy, uint32_t* auth_policy_size)
906{
907 TPM_NV_AUTH_POLICY* policy;
908 uint32_t buffer_size = *auth_policy_size;
909 *auth_policy_size = sizeof(TPM_NV_AUTH_POLICY);
910 if (buffer_size < sizeof(TPM_NV_AUTH_POLICY)) {
911 return TPM_E_BUFFER_SIZE((uint32_t) 0x0000500f);
912 }
913 policy = auth_policy;
914
915 struct s_tpm_getspaceinfo_cmd cmd;
916 memcpy(&cmd, &tpm_getspaceinfo_cmd, sizeof(cmd));
917 ToTpmUint32(cmd.buffer + tpm_getspaceinfo_cmd.index, index);
918 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
919 uint32_t result = TlclSendReceive(cmd.buffer, response,
920 sizeof(response));
921 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
922 return result;
923 }
924
925 uint32_t response_size = TpmCommandSize(response);
926 if (response_size > sizeof(response)) {
927 return TPM_E_RESPONSE_TOO_LARGE((uint32_t) 0x00005005);
928 }
929
930 const uint8_t* cursor = response + kTpmResponseHeaderLength10;
931 uint32_t cap_size = ReadTpmUint32(&cursor);
932 if (cap_size >
933 response_size - sizeof(cap_size) - kTpmResponseHeaderLength10) {
934 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
935 }
936 const uint8_t* end = cursor + cap_size;
937
938 cursor += sizeof(uint16_t); /* skip tag */
939 uint32_t response_index = ReadTpmUint32(&cursor);
940 if (index != response_index) {
941 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
942 }
943
944 if (!DecodePCRInfo(&cursor, end, &policy->pcr_info_read) ||
945 !DecodePCRInfo(&cursor, end, &policy->pcr_info_write)) {
946 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
947 }
948
949 /* Make sure that the remaining data in the buffer matches the size of
950 * the remaining fields to decode. */
951 if (end - cursor !=
952 2 * sizeof(uint32_t) + 3 * sizeof(uint8_t) + sizeof(uint16_t)) {
953 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
954 }
955
956 cursor += sizeof(uint16_t); /* skip TPM_NV_ATTRIBUTES tag */
957 *attributes = ReadTpmUint32(&cursor);
958 cursor += sizeof(uint8_t); /* skip bReadSTClear */
959 cursor += sizeof(uint8_t); /* skip bWriteSTClear */
960 cursor += sizeof(uint8_t); /* skip bWriteDefine */
961 *size = ReadTpmUint32(&cursor);
962
963 return TPM_SUCCESS((uint32_t) 0x00000000);
964}
965
966uint32_t TlclGetOwnership(uint8_t* owned)
967{
968 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
969 uint32_t size;
970 uint32_t result = TlclSendReceive(tpm_getownership_cmd.buffer,
971 response, sizeof(response));
972 if (result != TPM_SUCCESS((uint32_t) 0x00000000))
973 return result;
974 FromTpmUint32(response + kTpmResponseHeaderLength10, &size);
975 /* TODO(crbug.com/379255): This fails. Find out why.
976 * VB2_ASSERT(size == sizeof(*owned));
977 */
978 memcpy(owned,
979 response + kTpmResponseHeaderLength10 + sizeof(size),
980 sizeof(*owned));
981 return result;
982}
983
984uint32_t TlclGetRandom(uint8_t* data, uint32_t length, uint32_t *size)
985{
986 struct s_tpm_get_random_cmd cmd;
987 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
988 uint32_t result;
989
990 VB2_DEBUG("TPM: TlclGetRandom(%d)\n", length)vb2ex_printf(__func__, "TPM: TlclGetRandom(%d)\n", length);
991 memcpy(&cmd, &tpm_get_random_cmd, sizeof(cmd));
992 ToTpmUint32(cmd.buffer + tpm_get_random_cmd.bytesRequested, length);
993 /* There must be room in the response buffer for the bytes. */
994 if (length > TPM_LARGE_ENOUGH_COMMAND_SIZE256 - kTpmResponseHeaderLength10
995 - sizeof(uint32_t)) {
996 return TPM_E_IOERROR((uint32_t) 0x0000001f);
997 }
998
999 result = TlclSendReceive(cmd.buffer, response, sizeof(response));
1000 if (result == TPM_SUCCESS((uint32_t) 0x00000000)) {
1001 const uint8_t* get_random_cursor =
1002 response + kTpmResponseHeaderLength10;
1003 *size = ReadTpmUint32(&get_random_cursor);
1004
1005 /* There must be room in the target buffer for the bytes. */
1006 if (*size > length) {
1007 return TPM_E_RESPONSE_TOO_LARGE((uint32_t) 0x00005005);
1008 }
1009 memcpy(data, get_random_cursor, *size);
1010 }
1011
1012 return result;
1013}
1014
1015uint32_t TlclGetVersion(uint32_t* vendor, uint64_t* firmware_version,
1016 uint8_t* vendor_specific_buf,
1017 size_t* vendor_specific_buf_size)
1018{
1019 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
1020 uint32_t result = TlclSendReceive(tpm_getversionval_cmd.buffer,
1021 response, sizeof(response));
1022 if (result != TPM_SUCCESS((uint32_t) 0x00000000))
1023 return result;
1024
1025 const uint8_t* cursor = response + kTpmResponseHeaderLength10;
1026 uint32_t size = ReadTpmUint32(&cursor);
1027
1028 /* Verify size >= sizeof(TPM_CAP_VERSION_INFO). */
1029 const uint32_t kSizeofCapVersionInfo = 15;
1030 if (size < kSizeofCapVersionInfo ||
1031 kTpmResponseHeaderLength10 + sizeof(size) + size >
1032 TPM_LARGE_ENOUGH_COMMAND_SIZE256) {
1033 return TPM_E_IOERROR((uint32_t) 0x0000001f);
1034 }
1035
1036 cursor += sizeof(uint16_t); /* tag */
1037 cursor += sizeof(uint16_t); /* spec version */
1038
1039 *firmware_version = ReadTpmUint16(&cursor);
1040
1041 cursor += sizeof(uint16_t); /* specLevel */
1042 cursor += sizeof(uint8_t); /* errataRev */
1043
1044 *vendor = ReadTpmUint32(&cursor);
1045
1046 if (vendor_specific_buf_size) {
1047 uint16_t vendor_specific_size = ReadTpmUint16(&cursor);
1048
1049 if (size < kSizeofCapVersionInfo + vendor_specific_size) {
1050 return TPM_E_IOERROR((uint32_t) 0x0000001f);
1051 }
1052 if (vendor_specific_buf) {
1053 if (vendor_specific_size > *vendor_specific_buf_size) {
1054 vendor_specific_size =
1055 *vendor_specific_buf_size;
1056 }
1057 memcpy(vendor_specific_buf, cursor,
1058 vendor_specific_size);
1059 cursor += vendor_specific_size;
1060 }
1061 *vendor_specific_buf_size = vendor_specific_size;
1062 }
1063
1064 return TPM_SUCCESS((uint32_t) 0x00000000);
1065}
1066
1067static void ParseIFXFirmwarePackage(const uint8_t** cursor,
1068 TPM_IFX_FIRMWAREPACKAGE* firmware_package)
1069{
1070 firmware_package->FwPackageIdentifier = ReadTpmUint32(cursor);
1071 firmware_package->Version = ReadTpmUint32(cursor);
1072 firmware_package->StaleVersion = ReadTpmUint32(cursor);
1073}
1074
1075uint32_t TlclIFXFieldUpgradeInfo(TPM_IFX_FIELDUPGRADEINFO* info)
1076{
1077 uint32_t vendor;
1078 uint64_t firmware_version;
1079 uint32_t result =
1080 TlclGetVersion(&vendor, &firmware_version, NULL((void*)0), NULL((void*)0));
1081 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1082 return result;
1083 }
1084 if (vendor != 0x49465800) {
1085 return TPM_E_BAD_ORDINAL((uint32_t) 0x0000000a);
1086 }
1087
1088 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
1089 result = TlclSendReceive(tpm_ifx_fieldupgradeinforequest2_cmd.buffer,
1090 response, sizeof(response));
1091 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1092 return result;
1093 }
1094
1095 const uint8_t* cursor = response + kTpmResponseHeaderLength10;
1096 uint16_t size = ReadTpmUint16(&cursor);
1097
1098 /* Comments below indicate skipped fields of unknown purpose that are
1099 * marked "internal" in the firmware updater source. */
1100 cursor += sizeof(uint16_t); /* internal1 */
1101 info->wMaxDataSize = ReadTpmUint16(&cursor);
1102 cursor += sizeof(uint16_t); /* sSecurityModuleLogic.internal1 */
1103 cursor += sizeof(uint32_t); /* sSecurityModuleLogic.internal2 */
1104 cursor += sizeof(uint8_t[34]); /* sSecurityModuleLogic.internal3 */
1105 ParseIFXFirmwarePackage(&cursor, &info->sBootloaderFirmwarePackage);
1106 uint16_t fw_entry_count = ReadTpmUint16(&cursor);
1107 if (fw_entry_count > ARRAY_SIZE(info->sFirmwarePackages)(sizeof(info->sFirmwarePackages) / sizeof((info->sFirmwarePackages
)[0]))
) {
1108 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1109 }
1110 uint16_t i;
1111 for (i = 0; i < fw_entry_count; ++i) {
1112 ParseIFXFirmwarePackage(&cursor, &info->sFirmwarePackages[i]);
1113 }
1114 info->wSecurityModuleStatus = ReadTpmUint16(&cursor);
1115 ParseIFXFirmwarePackage(&cursor, &info->sProcessFirmwarePackage);
1116 cursor += sizeof(uint16_t); /* internal6 */
1117 cursor += sizeof(uint8_t[6]); /* internal7 */
1118 info->wFieldUpgradeCounter = ReadTpmUint16(&cursor);
1119
1120 uint32_t parsed_bytes = cursor - response;
1121 VB2_ASSERT(parsed_bytes <= TPM_LARGE_ENOUGH_COMMAND_SIZE)do { if (!(parsed_bytes <= 256)) { vb2ex_printf(__func__, "assertion failed: %s at %s:%d\n"
, "parsed_bytes <= TPM_LARGE_ENOUGH_COMMAND_SIZE", "firmware/lib/tpm_lite/tlcl.c"
, 1121); vb2ex_abort(); for (;;); } } while (0)
;
1122 if (parsed_bytes > kTpmResponseHeaderLength10 + sizeof(size) + size) {
1123 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1124 }
1125
1126 return result;
1127}
1128
1129#ifdef CHROMEOS_ENVIRONMENT1
1130
1131static uint32_t ParseRsaKeyParms(const uint8_t* buffer,
1132 const uint8_t* end,
1133 uint32_t* key_len,
1134 uint32_t* num_primes,
1135 uint32_t* exponent)
1136{
1137 if (end - buffer < 3 * sizeof(uint32_t)) {
1138 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1139 }
1140 *key_len = ReadTpmUint32(&buffer);
1141 *num_primes = ReadTpmUint32(&buffer);
1142 uint32_t exponent_size = ReadTpmUint32(&buffer);
1143 if (end - buffer < exponent_size) {
1144 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1145 }
1146
1147 if (exponent_size == 0) {
1148 *exponent = 0x10001;
1149 } else if (exponent_size <= sizeof(*exponent)) {
1150 *exponent = 0;
1151 int i;
1152 for (i = 0; i < exponent_size; ++i) {
1153 *exponent |= (*buffer++) << (8 * i);
1154 }
1155 } else {
1156 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
1157 }
1158
1159 return TPM_SUCCESS((uint32_t) 0x00000000);
1160}
1161
1162static uint32_t ParseTpmPubKey(const uint8_t** buffer,
1163 const uint8_t* end,
1164 uint32_t* algorithm,
1165 uint16_t* enc_scheme,
1166 uint16_t* sig_scheme,
1167 uint32_t* key_len,
1168 uint32_t* num_primes,
1169 uint32_t* exponent,
1170 uint8_t* modulus,
1171 uint32_t* modulus_size)
1172{
1173 uint32_t result = TPM_SUCCESS((uint32_t) 0x00000000);
1174
1175 if (end - *buffer < 2 * sizeof(uint32_t) + 2 * sizeof(uint16_t)) {
1176 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1177 }
1178
1179 *algorithm = ReadTpmUint32(buffer);
1180 *enc_scheme = ReadTpmUint16(buffer);
1181 *sig_scheme = ReadTpmUint16(buffer);
1182
1183 uint32_t parm_size = ReadTpmUint32(buffer);
1184 if (end - *buffer < parm_size) {
1185 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1186 }
1187
1188 if (*algorithm == TPM_ALG_RSA((uint16_t)0x0001)) {
1189 result = ParseRsaKeyParms(*buffer, *buffer + parm_size,
1190 key_len, num_primes, exponent);
1191 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1192 return result;
1193 }
1194 } else {
1195 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
1196 }
1197
1198 *buffer += parm_size;
1199
1200 if (end - *buffer < sizeof(uint32_t)) {
1201 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1202 }
1203
1204 uint32_t actual_modulus_size = ReadTpmUint32(buffer);
1205 if (end - *buffer < actual_modulus_size) {
1206 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1207 }
1208
1209 if (modulus && *modulus_size >= actual_modulus_size) {
1210 memcpy(modulus, *buffer, actual_modulus_size);
1211 } else {
1212 result = TPM_E_BUFFER_SIZE((uint32_t) 0x0000500f);
1213 }
1214 *modulus_size = actual_modulus_size;
1215 *buffer += actual_modulus_size;
1216
1217 return result;
1218}
1219
1220uint32_t TlclReadPubek(uint32_t* public_exponent,
1221 uint8_t* modulus,
1222 uint32_t* modulus_size)
1223{
1224 struct s_tpm_readpubek_cmd cmd;
1225 memcpy(&cmd, &tpm_readpubek_cmd, sizeof(cmd));
1226 if (vb2ex_tpm_get_random(cmd.buffer + tpm_readpubek_cmd.antiReplay,
1227 sizeof(TPM_NONCE)) != VB2_SUCCESS) {
1228 return TPM_E_INTERNAL_ERROR((uint32_t) 0x0000500d);
1229 }
1230
1231 /* The response contains the public endorsement key, so use a large
1232 * response buffer. */
1233 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256 + TPM_RSA_2048_LEN0x100];
1234 uint32_t result = TlclSendReceive(cmd.buffer, response,
1235 sizeof(response));
1236 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1237 return result;
1238 }
1239
1240 const uint8_t* cursor = response + kTpmResponseHeaderLength10;
1241 const uint8_t* end = response + sizeof(response);
1242
1243 /* Parse the key */
1244 uint32_t algorithm;
1245 uint16_t enc_scheme;
1246 uint16_t sig_scheme;
1247 uint32_t key_len;
1248 uint32_t num_primes;
1249 result = ParseTpmPubKey(&cursor, end, &algorithm, &enc_scheme,
1250 &sig_scheme, &key_len, &num_primes,
1251 public_exponent, modulus, modulus_size);
1252 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1253 return result;
1254 }
1255
1256 /* Parse the checksum */
1257 if (end - cursor < TPM_SHA1_160_HASH_LEN0x14) {
1258 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1259 }
1260 const uint8_t* checksum = cursor;
1261 cursor += TPM_SHA1_160_HASH_LEN0x14;
1262
1263 /* Check the digest */
1264 struct vb2_sha1_context sha1_ctx;
1265 vb2_sha1_init(&sha1_ctx);
1266 vb2_sha1_update(&sha1_ctx, response + kTpmResponseHeaderLength10,
1267 checksum - (response + kTpmResponseHeaderLength10));
1268 vb2_sha1_update(&sha1_ctx, cmd.buffer + tpm_readpubek_cmd.antiReplay,
1269 sizeof(TPM_NONCE));
1270 uint8_t digest[TPM_SHA1_160_HASH_LEN0x14];
1271 vb2_sha1_finalize(&sha1_ctx, digest);
1272 if (vb2_safe_memcmp(digest, checksum, sizeof(digest))) {
1273 return TPM_E_AUTHFAIL((uint32_t) 0x00000001);
1274 }
1275
1276 /* Validate expectations for the EK. */
1277 if (algorithm != TPM_ALG_RSA((uint16_t)0x0001) ||
1278 enc_scheme != TPM_ES_RSAESOAEP_SHA1_MGF1((uint16_t)0x0003) ||
1279 sig_scheme != TPM_SS_NONE((uint16_t)0x0001) ||
1280 key_len != 2048 ||
1281 num_primes != 2) {
1282 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1283 }
1284
1285 return result;
1286}
1287
1288uint32_t TlclTakeOwnership(uint8_t enc_owner_auth[TPM_RSA_2048_LEN0x100],
1289 uint8_t enc_srk_auth[TPM_RSA_2048_LEN0x100],
1290 uint8_t owner_auth[TPM_AUTH_DATA_LEN0x14])
1291{
1292 /* Start an OAIP session. */
1293 struct auth_session auth_session;
1294 uint32_t result = StartOIAPSession(&auth_session, owner_auth);
1295 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1296 return result;
1297 }
1298
1299 /* Build the TakeOwnership command. */
1300 struct s_tpm_takeownership_cmd cmd;
1301 memcpy(&cmd, &tpm_takeownership_cmd, sizeof(cmd));
1302 memcpy(cmd.buffer + tpm_takeownership_cmd.encOwnerAuth, enc_owner_auth,
1303 TPM_RSA_2048_LEN0x100);
1304 memcpy(cmd.buffer + tpm_takeownership_cmd.encSrkAuth, enc_srk_auth,
1305 TPM_RSA_2048_LEN0x100);
1306 result = AddRequestAuthBlock(&auth_session, cmd.buffer,
1307 sizeof(cmd.buffer), 0);
1308 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1309 return result;
1310 }
1311
1312 /* The response buffer needs to be large to hold the public half of the
1313 * generated SRK. */
1314 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256 + TPM_RSA_2048_LEN0x100];
1315 result = TlclSendReceive(cmd.buffer, response, sizeof(response));
1316 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1317 return result;
1318 }
1319
1320 /* Check the auth tag on the response. */
1321 result = CheckResponseAuthBlock(&auth_session, TPM_ORD_TakeOwnership((uint32_t) 0x0000000D),
1322 response, sizeof(response));
1323 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1324 return result;
1325 }
1326
1327 return TPM_SUCCESS((uint32_t) 0x00000000);
1328}
1329
1330uint32_t TlclCreateDelegationFamily(uint8_t family_label)
1331{
1332 struct s_tpm_create_delegation_family_cmd cmd;
1333 memcpy(&cmd, &tpm_create_delegation_family_cmd, sizeof(cmd));
1334 cmd.buffer[tpm_create_delegation_family_cmd.familyLabel] = family_label;
1335 return Send(cmd.buffer);
1336}
1337
1338uint32_t TlclReadDelegationFamilyTable(TPM_FAMILY_TABLE_ENTRY *table,
1339 uint32_t* table_size)
1340{
1341 uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE256];
1342 uint32_t result = TlclSendReceive(tpm_delegate_read_table_cmd.buffer,
1343 response, sizeof(response));
1344 if (result != TPM_SUCCESS((uint32_t) 0x00000000)) {
1345 return result;
1346 }
1347
1348 uint32_t size;
1349 FromTpmUint32(response + sizeof(uint16_t), &size);
1350 if (size < kTpmRequestHeaderLength10 + sizeof(uint32_t) ||
1351 size > sizeof(response)) {
1352 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1353 }
1354
1355 const uint8_t* cursor = response + kTpmRequestHeaderLength10;
1356 uint32_t table_bytes = ReadTpmUint32(&cursor);
1357
1358 if (table_bytes > size - (cursor - response)) {
1359 return TPM_E_INVALID_RESPONSE((uint32_t) 0x0000500e);
1360 }
1361
1362 const uint32_t table_entry_size =
1363 sizeof(uint16_t) + sizeof(uint8_t) + 3 * sizeof(uint32_t);
1364 uint32_t table_entries = table_bytes / table_entry_size;
1365 int i;
1366 for (i = 0; i < table_entries; ++i) {
1367 if (i >= *table_size || !table) {
1368 result = TPM_E_BUFFER_SIZE((uint32_t) 0x0000500f);
1369 break;
1370 }
1371
1372 table[i].tag = ReadTpmUint16(&cursor);
1373 table[i].familyLabel = *cursor++;
1374 table[i].familyID = ReadTpmUint32(&cursor);
1375 table[i].verificationCount = ReadTpmUint32(&cursor);
1376 table[i].flags = ReadTpmUint32(&cursor);
1377 }
1378
1379 *table_size = table_entries;
1380
1381 return result;
1382}
1383
1384#endif /* CHROMEOS_ENVIRONMENT */