blob: b9857d476d5598526e684ade7f29c63cd3939fec [file] [log] [blame]
Joel Kitching9adf2aa2019-08-20 17:43:50 +08001/* Copyright 2016 The Chromium OS Authors. All rights reserved.
Vadim Bendebury25589e52016-06-28 10:27:16 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
Randall Spangler21015892017-01-03 13:49:18 -08006#include "2common.h"
Joel Kitchingffd42a82019-08-29 13:58:52 +08007#include "2sysincludes.h"
Vadim Bendebury25589e52016-06-28 10:27:16 -07008#include "tpm2_marshaling.h"
Vadim Bendebury25589e52016-06-28 10:27:16 -07009
10static uint16_t tpm_tag; /* Depends on the command type. */
Andrey Proninbea3f792016-07-18 11:24:55 -070011static int ph_disabled; /* Platform hierarchy disabled. */
Vadim Bendebury25589e52016-06-28 10:27:16 -070012
13static void write_be16(void *dest, uint16_t val)
14{
15 uint8_t *byte_dest = dest;
16
17 byte_dest[0] = val >> 8;
18 byte_dest[1] = val;
19}
20
21static void write_be32(void *dest, uint32_t val)
22{
23 uint8_t *byte_dest = dest;
24
25 byte_dest[0] = val >> 24;
26 byte_dest[1] = val >> 16;
27 byte_dest[2] = val >> 8;
28 byte_dest[3] = val;
29}
30
31static uint16_t read_be16(const void *src)
32{
33 const uint8_t *s = src;
34 return (((uint16_t)s[0]) << 8) | (((uint16_t)s[1]) << 0);
35}
36
37static inline uint32_t read_be32(const void *src)
38{
39 const uint8_t *s = src;
40
41 return (((uint32_t)s[0]) << 24) | (((uint32_t)s[1]) << 16) |
42 (((uint32_t)s[2]) << 8) | (((uint32_t)s[3]) << 0);
43}
44
45/*
46 * Each unmarshaling function receives a pointer to the buffer pointer and a
47 * pointer to the size of data still in the buffer. The function extracts data
48 * from the buffer and adjusts both buffer pointer and remaining data size.
49 *
50 * Should there be not enough data in the buffer to unmarshal the required
51 * object, the remaining data size is set to -1 to indicate the error. The
52 * remaining data size is expected to be set to zero once the last data item
53 * has been extracted from the buffer.
54 */
55
Andrey Pronin09606822016-07-22 18:45:07 -070056static uint8_t unmarshal_u8(void **buffer, int *buffer_space)
57{
58 uint8_t value;
59
60 if (*buffer_space < sizeof(value)) {
61 *buffer_space = -1; /* Indicate a failure. */
62 return 0;
63 }
64
65 value = *(uint8_t *)(*buffer);
66 *buffer = (void *) ((uintptr_t) (*buffer) + sizeof(value));
67 *buffer_space -= sizeof(value);
68
69 return value;
70}
71
Vadim Bendebury25589e52016-06-28 10:27:16 -070072static uint16_t unmarshal_u16(void **buffer, int *buffer_space)
73{
74 uint16_t value;
75
76 if (*buffer_space < sizeof(value)) {
77 *buffer_space = -1; /* Indicate a failure. */
78 return 0;
79 }
80
81 value = read_be16(*buffer);
82 *buffer = (void *) ((uintptr_t) (*buffer) + sizeof(value));
83 *buffer_space -= sizeof(value);
84
85 return value;
86}
87
Andrey Pronin085c2052016-07-25 15:15:04 -070088static uint32_t unmarshal_u32(void **buffer, int *buffer_space)
Vadim Bendebury25589e52016-06-28 10:27:16 -070089{
90 uint32_t value;
91
92 if (*buffer_space < sizeof(value)) {
93 *buffer_space = -1; /* Indicate a failure. */
94 return 0;
95 }
96
97 value = read_be32(*buffer);
98 *buffer = (void *) ((uintptr_t) (*buffer) + sizeof(value));
99 *buffer_space -= sizeof(value);
100
101 return value;
102}
103
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800104#define unmarshal_TPM_HANDLE(a, b) unmarshal_u32(a, b)
105#define unmarshal_ALG_ID(a, b) unmarshal_u16(a, b)
106
Vadim Bendebury25589e52016-06-28 10:27:16 -0700107static void unmarshal_TPM2B_MAX_NV_BUFFER(void **buffer,
108 int *size,
109 TPM2B_MAX_NV_BUFFER *nv_buffer)
110{
111 nv_buffer->t.size = unmarshal_u16(buffer, size);
112 if (nv_buffer->t.size > *size) {
Randall Spanglera6094782017-01-20 14:54:47 -0800113 VB2_DEBUG("size mismatch: expected %d, remaining %d\n",
114 nv_buffer->t.size, *size);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700115 return;
116 }
117
118 nv_buffer->t.buffer = *buffer;
119
120 *buffer = ((uint8_t *)(*buffer)) + nv_buffer->t.size;
121 *size -= nv_buffer->t.size;
122}
123
Andrey Pronin09606822016-07-22 18:45:07 -0700124static void unmarshal_authorization_section(void **buffer, int *size,
Julius Werner52fa8c12019-05-07 12:59:47 -0700125 const char *cmd_name)
Andrey Pronin09606822016-07-22 18:45:07 -0700126{
127 /*
128 * Let's ignore the authorisation section. It should be 5 bytes total,
129 * just confirm that this is the case and report any discrepancy.
130 */
131 if (*size != 5)
Randall Spanglera6094782017-01-20 14:54:47 -0800132 VB2_DEBUG("unexpected authorisation section size %d for %s\n",
133 *size, cmd_name);
Andrey Pronin09606822016-07-22 18:45:07 -0700134
135 *buffer = ((uint8_t *)(*buffer)) + *size;
136 *size = 0;
137}
138
Vadim Bendebury25589e52016-06-28 10:27:16 -0700139static void unmarshal_nv_read(void **buffer, int *size,
140 struct nv_read_response *nvr)
141{
142 /* Total size of the parameter field. */
143 nvr->params_size = unmarshal_u32(buffer, size);
144 unmarshal_TPM2B_MAX_NV_BUFFER(buffer, size, &nvr->buffer);
145
146 if (nvr->params_size !=
147 (nvr->buffer.t.size + sizeof(nvr->buffer.t.size))) {
Randall Spanglera6094782017-01-20 14:54:47 -0800148 VB2_DEBUG("parameter/buffer %d/%d size mismatch",
149 nvr->params_size, nvr->buffer.t.size);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700150 return;
151 }
152
153 if (*size < 0)
154 return;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700155
Andrey Pronin09606822016-07-22 18:45:07 -0700156 unmarshal_authorization_section(buffer, size, "NV_Read");
157}
158
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800159static void unmarshal_TPM2B(void **buffer,
160 int *size,
161 TPM2B *tpm2b)
162{
163 tpm2b->size = unmarshal_u16(buffer, size);
164 if (tpm2b->size > *size) {
Randall Spanglera6094782017-01-20 14:54:47 -0800165 VB2_DEBUG("size mismatch: expected %d, remaining %d\n",
166 tpm2b->size, *size);
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800167 *size = -1;
168 return;
169 }
170
171 tpm2b->buffer = *buffer;
172
173 *buffer = ((uint8_t *)(*buffer)) + tpm2b->size;
174 *size -= tpm2b->size;
175}
176
177static void unmarshal_TPMS_NV_PUBLIC(void **buffer,
178 int *size,
179 TPMS_NV_PUBLIC *pub)
180{
181 int tpm2b_size = unmarshal_u16(buffer, size);
182 if (tpm2b_size > *size) {
Randall Spanglera6094782017-01-20 14:54:47 -0800183 VB2_DEBUG("size mismatch: expected %d, remaining %d\n",
184 tpm2b_size, *size);
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800185 *size = -1;
186 return;
187 }
188 *size -= tpm2b_size;
189
190 pub->nvIndex = unmarshal_TPM_HANDLE(buffer, &tpm2b_size);
191 pub->nameAlg = unmarshal_ALG_ID(buffer, &tpm2b_size);
192 pub->attributes = unmarshal_u32(buffer, &tpm2b_size);
193 unmarshal_TPM2B(buffer, &tpm2b_size, &pub->authPolicy);
194 pub->dataSize = unmarshal_u16(buffer, &tpm2b_size);
195
196 if (tpm2b_size != 0) {
Randall Spanglera6094782017-01-20 14:54:47 -0800197 VB2_DEBUG("TPMS_NV_PUBLIC size doesn't match size field\n");
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800198 *size = -1;
199 return;
200 }
201}
202
203static void unmarshal_nv_read_public(void **buffer, int *size,
204 struct nv_read_public_response *nv_pub)
205{
206 unmarshal_TPMS_NV_PUBLIC(buffer, size, &nv_pub->nvPublic);
207 unmarshal_TPM2B(buffer, size, &nv_pub->nvName);
208
209 if (*size > 0) {
Randall Spanglera6094782017-01-20 14:54:47 -0800210 VB2_DEBUG("extra %d bytes after nvName\n", *size);
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800211 *size = -1;
212 return;
213 }
214}
215
Andrey Pronin09606822016-07-22 18:45:07 -0700216static void unmarshal_TPML_TAGGED_TPM_PROPERTY(void **buffer, int *size,
217 TPML_TAGGED_TPM_PROPERTY *prop)
218{
219 prop->count = unmarshal_u32(buffer, size);
220
221 if (prop->count != 1) {
222 *size = -1;
Randall Spanglera6094782017-01-20 14:54:47 -0800223 VB2_DEBUG("Request to unmarshal unsupported "
Randall Spangler21015892017-01-03 13:49:18 -0800224 "number of properties: %u\n",
Randall Spanglera6094782017-01-20 14:54:47 -0800225 prop->count);
Andrey Pronin09606822016-07-22 18:45:07 -0700226 return;
227 }
228
229 prop->tpm_property[0].property = unmarshal_u32(buffer, size);
230 prop->tpm_property[0].value = unmarshal_u32(buffer, size);
231}
232
233static void unmarshal_TPMS_CAPABILITY_DATA(void **buffer, int *size,
234 TPMS_CAPABILITY_DATA *cap_data)
235{
236 cap_data->capability = unmarshal_u32(buffer, size);
237
238 switch (cap_data->capability) {
239
240 case TPM_CAP_TPM_PROPERTIES:
241 unmarshal_TPML_TAGGED_TPM_PROPERTY(buffer, size,
242 &cap_data->data.
243 tpm_properties);
244 break;
245
246 default:
247 *size = -1;
Randall Spanglera6094782017-01-20 14:54:47 -0800248 VB2_DEBUG("Request to unmarshal unsupported capability %#x\n",
249 cap_data->capability);
Andrey Pronin09606822016-07-22 18:45:07 -0700250 }
251}
252
253static void unmarshal_get_capability(void **buffer, int *size,
254 struct get_capability_response *cap)
255{
256 /* Total size of the parameter field. */
257 cap->more_data = unmarshal_u8(buffer, size);
258 unmarshal_TPMS_CAPABILITY_DATA(buffer, size, &cap->capability_data);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700259}
260
Stephen Boyd8fbb4b82018-11-07 22:43:19 -0800261static void unmarshal_get_random(void **buffer, int *size,
262 struct get_random_response *random)
263{
264 unmarshal_TPM2B(buffer, size, &random->random_bytes);
265}
Vadim Bendebury25589e52016-06-28 10:27:16 -0700266
267/*
268 * Each marshaling function receives a pointer to the buffer to marshal into,
269 * a pointer to the data item to be marshaled, and a pointer to the remaining
270 * room in the buffer.
271 */
272
Joel Kitching9ad8a412018-08-02 16:21:17 +0800273/*
274 * Marshaling an arbitrary blob requires its size in addition to common
275 * parameter set.
276 */
Vadim Bendebury25589e52016-06-28 10:27:16 -0700277static void marshal_blob(void **buffer, void *blob,
278 size_t blob_size, int *buffer_space)
279{
280 if (*buffer_space < blob_size) {
281 *buffer_space = -1;
282 return;
283 }
284
Randall Spangler664096b2016-10-13 16:16:41 -0700285 memcpy(*buffer, blob, blob_size);
Yi Chou5c3a7822021-01-15 17:48:57 +0800286 *buffer_space -= blob_size;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700287 *buffer = (void *)((uintptr_t)(*buffer) + blob_size);
288}
289
290static void marshal_u8(void **buffer, uint8_t value, int *buffer_space)
291{
292 uint8_t *bp = *buffer;
293
294 if (*buffer_space < sizeof(value)) {
295 *buffer_space = -1;
296 return;
297 }
298
299 *bp++ = value;
300 *buffer = bp;
301 *buffer_space -= sizeof(value);
302}
303
304static void marshal_u16(void **buffer, uint16_t value, int *buffer_space)
305{
306 if (*buffer_space < sizeof(value)) {
307 *buffer_space = -1;
308 return;
309 }
310 write_be16(*buffer, value);
311 *buffer = (void *)((uintptr_t)(*buffer) + sizeof(value));
312 *buffer_space -= sizeof(value);
313}
314
315static void marshal_u32(void **buffer, uint32_t value, int *buffer_space)
316{
317 if (*buffer_space < sizeof(value)) {
318 *buffer_space = -1;
319 return;
320 }
321
322 write_be32(*buffer, value);
323 *buffer = (void *)((uintptr_t)(*buffer) + sizeof(value));
324 *buffer_space -= sizeof(value);
325}
326
Vadim Bendebury25589e52016-06-28 10:27:16 -0700327#define marshal_TPM_HANDLE(a, b, c) marshal_u32(a, b, c)
Andrey Pronin16cacfa2016-07-25 18:00:47 -0700328#define marshal_TPM_SU(a, b, c) marshal_u16(a, b, c)
Andrey Pronin055788b2016-10-31 19:39:44 -0700329#define marshal_ALG_ID(a, b, c) marshal_u16(a, b, c)
Yi Chou5c3a7822021-01-15 17:48:57 +0800330#define marshal_TPMI_ALG_HASH(a, b, c) marshal_u16(a, b, c)
Andrey Pronin055788b2016-10-31 19:39:44 -0700331
332/*
333 * For TPM2B* structures the size field (16 or 32 bits) goes before the data.
334 * When marshaling, we first reserve the space for the size field, then
335 * marshal the data, then fill the reserved size field with the actual size
336 * of the marshaled data.
337 */
338typedef struct {
339 int size;
340 void *location;
341} tpm2_marshal_size_field;
342
343static void marshal_reserve_size_field(void **buffer,
344 tpm2_marshal_size_field *field,
345 int field_size,
346 int *buffer_space)
347{
348 if (field_size != sizeof(uint32_t) && field_size != sizeof(uint16_t)) {
Randall Spanglera6094782017-01-20 14:54:47 -0800349 VB2_DEBUG("Unsupported size field size: %d\n", field_size);
Andrey Pronin055788b2016-10-31 19:39:44 -0700350 *buffer_space = -1;
351 return;
352 }
353 if (*buffer_space < field_size) {
354 *buffer_space = -1;
355 return;
356 }
357 field->size = field_size;
358 field->location = *buffer;
359 *buffer_space -= field_size;
360 *buffer = (void *)(((uintptr_t) *buffer) + field_size);
361}
362
363static void marshal_fill_size_field(void **buffer,
364 tpm2_marshal_size_field *field,
365 int include_size_field,
366 int *buffer_space)
367{
368 uintptr_t size = (uintptr_t) *buffer - (uintptr_t) field->location;
369
370 if (*buffer_space < 0)
371 return; /* The structure did not fit. */
372
373 if (!include_size_field)
374 size -= field->size;
375 if (field->size == sizeof(uint32_t))
376 marshal_u32(&field->location, size, &field->size);
377 else /* if (field->size == sizeof(uint16_t)) */
378 marshal_u16(&field->location, size, &field->size);
379}
Vadim Bendebury25589e52016-06-28 10:27:16 -0700380
381static void marshal_session_header(void **buffer,
382 struct tpm2_session_header *session_header,
383 int *buffer_space)
384{
Andrey Pronin055788b2016-10-31 19:39:44 -0700385 tpm2_marshal_size_field size_field;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700386
387 /* Skip room for the session header size. */
Andrey Pronin055788b2016-10-31 19:39:44 -0700388 marshal_reserve_size_field(buffer, &size_field,
389 sizeof(uint32_t), buffer_space);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700390
391 marshal_u32(buffer, session_header->session_handle, buffer_space);
392 marshal_u16(buffer, session_header->nonce_size, buffer_space);
393 marshal_blob(buffer, session_header->nonce,
394 session_header->nonce_size, buffer_space);
395 marshal_u8(buffer, session_header->session_attrs, buffer_space);
396 marshal_u16(buffer, session_header->auth_size, buffer_space);
397 marshal_blob(buffer, session_header->auth,
398 session_header->auth_size, buffer_space);
399
Vadim Bendebury25589e52016-06-28 10:27:16 -0700400 /* Paste in the session size. */
Andrey Pronin055788b2016-10-31 19:39:44 -0700401 marshal_fill_size_field(buffer, &size_field, 0, buffer_space);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700402}
403
404static void marshal_TPM2B(void **buffer,
405 TPM2B *data,
406 int *buffer_space)
407{
408 size_t total_size = data->size + sizeof(data->size);
409
410 if (total_size > *buffer_space) {
411 *buffer_space = -1;
412 return;
413 }
414 marshal_u16(buffer, data->size, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700415 memcpy(*buffer, data->buffer, data->size);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700416 *buffer = ((uint8_t *)(*buffer)) + data->size;
417 *buffer_space -= data->size;
418}
419
Andrey Pronin055788b2016-10-31 19:39:44 -0700420static void marshal_TPMS_NV_PUBLIC(void **buffer,
421 TPMS_NV_PUBLIC *data,
422 int *buffer_space)
423{
424 tpm2_marshal_size_field size_field;
425
426 /* Skip room for the size. */
427 marshal_reserve_size_field(buffer, &size_field,
428 sizeof(uint16_t), buffer_space);
429
430 marshal_TPM_HANDLE(buffer, data->nvIndex, buffer_space);
431 marshal_ALG_ID(buffer, data->nameAlg, buffer_space);
432 marshal_u32(buffer, data->attributes, buffer_space);
433 marshal_TPM2B(buffer, &data->authPolicy, buffer_space);
434 marshal_u16(buffer, data->dataSize, buffer_space);
435
436 /* Paste in the structure size. */
437 marshal_fill_size_field(buffer, &size_field, 0, buffer_space);
438}
439
440static void marshal_nv_define_space(void **buffer,
441 struct tpm2_nv_define_space_cmd
442 *command_body,
443 int *buffer_space)
444{
445 struct tpm2_session_header session_header;
446
447 /* Use platform authorization if PLATFORMCREATE is set, and owner
448 * authorization otherwise (per TPM2 Spec. Part 2. Section 31.3.1).
449 * Owner authorization with empty password will work only until
450 * ownership is taken. Platform authorization will work only until
451 * platform hierarchy is disabled (i.e. in firmware or in recovery
452 * mode).
453 */
454 if (command_body->publicInfo.attributes & TPMA_NV_PLATFORMCREATE)
455 marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
456 else
457 marshal_TPM_HANDLE(buffer, TPM_RH_OWNER, buffer_space);
458
459 memset(&session_header, 0, sizeof(session_header));
460 session_header.session_handle = TPM_RS_PW;
461 marshal_session_header(buffer, &session_header, buffer_space);
462 tpm_tag = TPM_ST_SESSIONS;
463
464 marshal_TPM2B(buffer, &command_body->auth, buffer_space);
465 marshal_TPMS_NV_PUBLIC(buffer, &command_body->publicInfo, buffer_space);
466}
467
Meng-Huan Yu737e34e2018-10-19 21:03:35 +0800468static void marshal_nv_undefine_space(void **buffer,
469 struct tpm2_nv_undefine_space_cmd
470 *command_body,
471 int *buffer_space)
472{
473 struct tpm2_session_header session_header;
474
475 /* Use platform authorization if PLATFORMCREATE is set, and owner
476 * authorization otherwise (per TPM2 Spec. Part 2. Section 31.3.1).
477 * Owner authorization with empty password will work only until
478 * ownership is taken. Platform authorization will work only until
479 * platform hierarchy is disabled (i.e. in firmware or in recovery
480 * mode).
481 */
482 if (command_body->use_platform_auth)
483 marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
484 else
485 marshal_TPM_HANDLE(buffer, TPM_RH_OWNER, buffer_space);
486 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
487
488 memset(&session_header, 0, sizeof(session_header));
489 session_header.session_handle = TPM_RS_PW;
490 marshal_session_header(buffer, &session_header, buffer_space);
491 tpm_tag = TPM_ST_SESSIONS;
492}
493
Andrey Pronin055788b2016-10-31 19:39:44 -0700494/* Determine which authorization should be used when writing or write-locking
495 * an NV index.
496 *
497 * Use a simplified approach:
498 * 1) Use platform auth for indexes defined by TPM and Platform, as
499 * specified in "Registry of reserved TPM 2.0 handles and localities".
500 * That will only work for indexes with PPWRITE, and until the platform
501 * hierarchy is disabled.
502 * 2) Use empty password auth for other indexes.
503 * That will only work for indexes with AUTHWRITE and empty auth value.
504 *
505 * A more honest approach would require the caller to specify the
506 * authorization, or would check the NV index attributes.
507 * But that's not needed now, as all indexes defined by firmware are
508 * in the TPM range and have PPWRITE. The indexes defined by the
509 * OS are in the Owner range and have either OWNERWRITE or AUTHWRITE,
510 * but we don't ever use Tlcl to write to OWNERWRITE indexes.
511 */
512static TPM_HANDLE get_nv_index_write_auth(TPMI_RH_NV_INDEX nvIndex)
513{
514 return nvIndex >= TPMI_RH_NV_INDEX_OWNER_START ?
515 nvIndex :
516 TPM_RH_PLATFORM;
517}
518
Vadim Bendebury25589e52016-06-28 10:27:16 -0700519static void marshal_nv_write(void **buffer,
520 struct tpm2_nv_write_cmd *command_body,
521 int *buffer_space)
522{
523 struct tpm2_session_header session_header;
524
Andrey Pronin055788b2016-10-31 19:39:44 -0700525 marshal_TPM_HANDLE(buffer,
526 get_nv_index_write_auth(command_body->nvIndex),
527 buffer_space);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700528 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700529 memset(&session_header, 0, sizeof(session_header));
Vadim Bendebury25589e52016-06-28 10:27:16 -0700530 session_header.session_handle = TPM_RS_PW;
531 marshal_session_header(buffer, &session_header, buffer_space);
532 tpm_tag = TPM_ST_SESSIONS;
533
534 marshal_TPM2B(buffer, &command_body->data.b, buffer_space);
535 marshal_u16(buffer, command_body->offset, buffer_space);
536}
537
538static void marshal_nv_read(void **buffer,
539 struct tpm2_nv_read_cmd *command_body,
540 int *buffer_space)
541{
542 struct tpm2_session_header session_header;
543
Andrey Proninbea3f792016-07-18 11:24:55 -0700544 /* Use empty password auth if platform hierarchy is disabled */
545 if (ph_disabled)
546 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
547 else
548 marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700549 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700550 memset(&session_header, 0, sizeof(session_header));
Vadim Bendebury25589e52016-06-28 10:27:16 -0700551 session_header.session_handle = TPM_RS_PW;
552 marshal_session_header(buffer, &session_header, buffer_space);
553 tpm_tag = TPM_ST_SESSIONS;
554 marshal_u16(buffer, command_body->size, buffer_space);
555 marshal_u16(buffer, command_body->offset, buffer_space);
556}
557
Stephen Barber5d996692016-08-04 16:05:01 -0700558static void marshal_nv_read_lock(void **buffer,
559 struct tpm2_nv_read_lock_cmd *command_body,
560 int *buffer_space)
561{
562 struct tpm2_session_header session_header;
563
564 tpm_tag = TPM_ST_SESSIONS;
Andrey Pronin4ad42032016-11-11 18:00:23 -0800565 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
Stephen Barber5d996692016-08-04 16:05:01 -0700566 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700567 memset(&session_header, 0, sizeof(session_header));
Stephen Barber5d996692016-08-04 16:05:01 -0700568 session_header.session_handle = TPM_RS_PW;
569 marshal_session_header(buffer, &session_header, buffer_space);
570}
571
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700572static void marshal_nv_write_lock(void **buffer,
573 struct tpm2_nv_write_lock_cmd *command_body,
574 int *buffer_space)
575{
576 struct tpm2_session_header session_header;
577
578 tpm_tag = TPM_ST_SESSIONS;
Andrey Pronin055788b2016-10-31 19:39:44 -0700579 marshal_TPM_HANDLE(buffer,
580 get_nv_index_write_auth(command_body->nvIndex),
581 buffer_space);
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700582 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700583 memset(&session_header, 0, sizeof(session_header));
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700584 session_header.session_handle = TPM_RS_PW;
585 marshal_session_header(buffer, &session_header, buffer_space);
586}
587
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800588static void marshal_nv_read_public(void **buffer,
589 struct tpm2_nv_read_public_cmd *command_body,
590 int *buffer_space)
591{
592 tpm_tag = TPM_ST_NO_SESSIONS;
593
594 marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
595}
596
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700597static void marshal_hierarchy_control(void **buffer,
598 struct tpm2_hierarchy_control_cmd
599 *command_body,
600 int *buffer_space)
601{
602 struct tpm2_session_header session_header;
603
604 tpm_tag = TPM_ST_SESSIONS;
605 marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700606 memset(&session_header, 0, sizeof(session_header));
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700607 session_header.session_handle = TPM_RS_PW;
608 marshal_session_header(buffer, &session_header, buffer_space);
609
610 marshal_TPM_HANDLE(buffer, command_body->enable, buffer_space);
611 marshal_u8(buffer, command_body->state, buffer_space);
612}
Vadim Bendebury25589e52016-06-28 10:27:16 -0700613
Andrey Pronin09606822016-07-22 18:45:07 -0700614static void marshal_get_capability(void **buffer,
615 struct tpm2_get_capability_cmd
616 *command_body,
617 int *buffer_space)
618{
619 tpm_tag = TPM_ST_NO_SESSIONS;
620
621 marshal_u32(buffer, command_body->capability, buffer_space);
622 marshal_u32(buffer, command_body->property, buffer_space);
623 marshal_u32(buffer, command_body->property_count, buffer_space);
624}
625
Stephen Boyd8fbb4b82018-11-07 22:43:19 -0800626static void marshal_get_random(void **buffer, struct tpm2_get_random_cmd
627 *command_body,
628 int *buffer_space)
629{
630 tpm_tag = TPM_ST_NO_SESSIONS;
631
632 marshal_u16(buffer, command_body->bytes_requested, buffer_space);
633}
634
Andrey Pronin16cacfa2016-07-25 18:00:47 -0700635static void marshal_clear(void **buffer,
636 void *command_body,
637 int *buffer_space)
638{
639 struct tpm2_session_header session_header;
640
641 tpm_tag = TPM_ST_SESSIONS;
642 marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
Randall Spangler664096b2016-10-13 16:16:41 -0700643 memset(&session_header, 0, sizeof(session_header));
Andrey Pronin16cacfa2016-07-25 18:00:47 -0700644 session_header.session_handle = TPM_RS_PW;
645 marshal_session_header(buffer, &session_header, buffer_space);
646}
647
648static void marshal_self_test(void **buffer,
649 struct tpm2_self_test_cmd *command_body,
650 int *buffer_space)
651{
652 tpm_tag = TPM_ST_NO_SESSIONS;
653
654 marshal_u8(buffer, command_body->full_test, buffer_space);
655}
656
657static void marshal_startup(void **buffer,
658 struct tpm2_startup_cmd *command_body,
659 int *buffer_space)
660{
661 tpm_tag = TPM_ST_NO_SESSIONS;
662
663 marshal_TPM_SU(buffer, command_body->startup_type, buffer_space);
664}
665
666static void marshal_shutdown(void **buffer,
667 struct tpm2_shutdown_cmd *command_body,
668 int *buffer_space)
669{
670 tpm_tag = TPM_ST_NO_SESSIONS;
671
672 marshal_TPM_SU(buffer, command_body->shutdown_type, buffer_space);
673}
674
Yi Chou5c3a7822021-01-15 17:48:57 +0800675static void marshal_TPMT_HA(void **buffer,
676 TPMT_HA *data,
677 int *buffer_space)
678{
679 if (data->hashAlg != TPM_ALG_SHA256)
680 {
681 VB2_DEBUG("Unsupported TPMT_HA hash algorithm: %#x\n",
682 data->hashAlg);
683 *buffer_space = -1;
684 return;
685 }
686 marshal_TPMI_ALG_HASH(buffer, data->hashAlg, buffer_space);
687 /* We only support SHA256 now. */
688 marshal_blob(buffer, data->digest.sha256,
689 SHA256_DIGEST_SIZE, buffer_space);
690}
691
692static void marshal_TPML_DIGEST_VALUES(void **buffer,
693 TPML_DIGEST_VALUES *data,
694 int *buffer_space)
695{
696 int i;
697
698 marshal_u32(buffer, data->count, buffer_space);
699 for (i = 0; i < data->count; i++)
700 marshal_TPMT_HA(buffer, &data->digests[i], buffer_space);
701}
702
703static void marshal_pcr_extend(void **buffer,
704 struct tpm2_pcr_extend_cmd *command_body,
705 int *buffer_space)
706{
707 struct tpm2_session_header session_header;
708
709 tpm_tag = TPM_ST_SESSIONS;
710 marshal_TPM_HANDLE(buffer, command_body->pcrHandle, buffer_space);
711 memset(&session_header, 0, sizeof(session_header));
712 session_header.session_handle = TPM_RS_PW;
713 marshal_session_header(buffer, &session_header, buffer_space);
714 marshal_TPML_DIGEST_VALUES(buffer, &command_body->digests, buffer_space);
715}
716
Vadim Bendebury25589e52016-06-28 10:27:16 -0700717int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
718 void *buffer, int buffer_size)
719{
720 void *cmd_body = (uint8_t *)buffer + sizeof(struct tpm_header);
721 int max_body_size = buffer_size - sizeof(struct tpm_header);
722 int body_size = max_body_size;
723
724 /* Will be modified when marshaling some commands. */
725 tpm_tag = TPM_ST_NO_SESSIONS;
726
727 switch (command) {
728
Andrey Pronin055788b2016-10-31 19:39:44 -0700729 case TPM2_NV_DefineSpace:
730 marshal_nv_define_space(&cmd_body, tpm_command_body, &body_size);
731 break;
732
Meng-Huan Yu737e34e2018-10-19 21:03:35 +0800733 case TPM2_NV_UndefineSpace:
734 marshal_nv_undefine_space(&cmd_body, tpm_command_body, &body_size);
735 break;
736
Vadim Bendebury25589e52016-06-28 10:27:16 -0700737 case TPM2_NV_Read:
738 marshal_nv_read(&cmd_body, tpm_command_body, &body_size);
739 break;
740
741 case TPM2_NV_Write:
742 marshal_nv_write(&cmd_body, tpm_command_body, &body_size);
743 break;
744
Stephen Barber5d996692016-08-04 16:05:01 -0700745 case TPM2_NV_ReadLock:
746 marshal_nv_read_lock(&cmd_body, tpm_command_body, &body_size);
747 break;
748
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700749 case TPM2_NV_WriteLock:
750 marshal_nv_write_lock(&cmd_body, tpm_command_body, &body_size);
751 break;
752
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800753 case TPM2_NV_ReadPublic:
754 marshal_nv_read_public(&cmd_body, tpm_command_body, &body_size);
755 break;
756
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700757 case TPM2_Hierarchy_Control:
758 marshal_hierarchy_control(&cmd_body,
759 tpm_command_body, &body_size);
760 break;
761
Andrey Pronin09606822016-07-22 18:45:07 -0700762 case TPM2_GetCapability:
763 marshal_get_capability(&cmd_body, tpm_command_body, &body_size);
764 break;
765
Stephen Boyd8fbb4b82018-11-07 22:43:19 -0800766 case TPM2_GetRandom:
767 marshal_get_random(&cmd_body, tpm_command_body, &body_size);
768 break;
769
Andrey Pronin16cacfa2016-07-25 18:00:47 -0700770 case TPM2_Clear:
771 marshal_clear(&cmd_body, tpm_command_body, &body_size);
772 break;
773
774 case TPM2_SelfTest:
775 marshal_self_test(&cmd_body, tpm_command_body, &body_size);
776 break;
777
778 case TPM2_Startup:
779 marshal_startup(&cmd_body, tpm_command_body, &body_size);
780 break;
781
782 case TPM2_Shutdown:
783 marshal_shutdown(&cmd_body, tpm_command_body, &body_size);
784 break;
785
Yi Chou5c3a7822021-01-15 17:48:57 +0800786 case TPM2_PCR_Extend:
787 marshal_pcr_extend(&cmd_body, tpm_command_body, &body_size);
788 break;
789
Vadim Bendebury25589e52016-06-28 10:27:16 -0700790 default:
791 body_size = -1;
Randall Spanglera6094782017-01-20 14:54:47 -0800792 VB2_DEBUG("Request to marshal unsupported command %#x\n",
793 command);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700794 }
795
796 if (body_size > 0) {
797
798 /* See how much room was taken by marshaling. */
799 body_size = max_body_size - body_size;
800
801 body_size += sizeof(struct tpm_header);
802
803 marshal_u16(&buffer, tpm_tag, &max_body_size);
804 marshal_u32(&buffer, body_size, &max_body_size);
805 marshal_u32(&buffer, command, &max_body_size);
806 }
807
808 return body_size;
809}
810
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700811int tpm_unmarshal_response(TPM_CC command,
812 void *response_body,
813 int cr_size,
814 struct tpm2_response *response)
Vadim Bendebury25589e52016-06-28 10:27:16 -0700815{
Vadim Bendebury25589e52016-06-28 10:27:16 -0700816 if (cr_size < sizeof(struct tpm_header))
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700817 return -1;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700818
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700819 response->hdr.tpm_tag = unmarshal_u16(&response_body, &cr_size);
820 response->hdr.tpm_size = unmarshal_u32(&response_body, &cr_size);
Andrey Pronina872e9b2018-03-26 10:22:20 -0700821 response->hdr.tpm_code = unmarshal_u32(&response_body, &cr_size);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700822
823 if (!cr_size) {
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700824 if (response->hdr.tpm_size != sizeof(response->hdr))
Randall Spanglera6094782017-01-20 14:54:47 -0800825 VB2_DEBUG("size mismatch in response to command %#x\n",
826 command);
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700827 return 0;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700828 }
829
830 switch (command) {
831 case TPM2_NV_Read:
832 unmarshal_nv_read(&response_body, &cr_size,
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700833 &response->nvr);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700834 break;
835
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800836 case TPM2_NV_ReadPublic:
837 unmarshal_nv_read_public(&response_body, &cr_size,
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700838 &response->nv_read_public);
Andrey Pronin1afcfc12016-11-09 20:19:32 -0800839 break;
840
Andrey Pronin09606822016-07-22 18:45:07 -0700841 case TPM2_GetCapability:
842 unmarshal_get_capability(&response_body, &cr_size,
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700843 &response->cap);
Andrey Pronin09606822016-07-22 18:45:07 -0700844 break;
845
Stephen Boyd8fbb4b82018-11-07 22:43:19 -0800846 case TPM2_GetRandom:
847 unmarshal_get_random(&response_body, &cr_size,
848 &response->random);
849 break;
850
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700851 case TPM2_Hierarchy_Control:
Vadim Bendebury25589e52016-06-28 10:27:16 -0700852 case TPM2_NV_Write:
Vadim Bendeburyae703f62016-07-06 09:07:54 -0700853 case TPM2_NV_WriteLock:
Andrey Pronin4ad42032016-11-11 18:00:23 -0800854 case TPM2_NV_ReadLock:
Andrey Pronin16cacfa2016-07-25 18:00:47 -0700855 case TPM2_Clear:
856 case TPM2_SelfTest:
857 case TPM2_Startup:
858 case TPM2_Shutdown:
Andrey Pronin055788b2016-10-31 19:39:44 -0700859 case TPM2_NV_DefineSpace:
Meng-Huan Yu737e34e2018-10-19 21:03:35 +0800860 case TPM2_NV_UndefineSpace:
Yi Chou5c3a7822021-01-15 17:48:57 +0800861 case TPM2_PCR_Extend:
Vadim Bendebury25589e52016-06-28 10:27:16 -0700862 /* Session data included in response can be safely ignored. */
863 cr_size = 0;
864 break;
865
866 default:
867 {
868 int i;
869
Randall Spanglera6094782017-01-20 14:54:47 -0800870 VB2_DEBUG("Request to unmarshal unexpected command %#x,"
Randall Spangler21015892017-01-03 13:49:18 -0800871 " code %#x",
Randall Spanglera6094782017-01-20 14:54:47 -0800872 command,
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700873 response->hdr.tpm_code);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700874
875 for (i = 0; i < cr_size; i++) {
876 if (!(i % 16))
Randall Spanglera6094782017-01-20 14:54:47 -0800877 VB2_DEBUG_RAW("\n");
878 VB2_DEBUG_RAW("%2.2x ",
879 ((uint8_t *)response_body)[i]);
Vadim Bendebury25589e52016-06-28 10:27:16 -0700880 }
881 }
Randall Spangler21015892017-01-03 13:49:18 -0800882 VB2_DEBUG("\n");
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700883 return -1;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700884 }
885
886 if (cr_size) {
Randall Spanglera6094782017-01-20 14:54:47 -0800887 VB2_DEBUG("got %d bytes back in response to %#x,"
Randall Spangler21015892017-01-03 13:49:18 -0800888 " failed to parse (%d)\n",
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700889 response->hdr.tpm_size,
Randall Spangler21015892017-01-03 13:49:18 -0800890 command, cr_size);
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700891 return -1;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700892 }
893
894 /* The entire message have been parsed. */
Andrey Pronin3ee5c7d2018-03-22 17:45:20 -0700895 return 0;
Vadim Bendebury25589e52016-06-28 10:27:16 -0700896}
Andrey Proninbea3f792016-07-18 11:24:55 -0700897
Andrey Pronin5be84672016-07-25 16:28:39 -0700898uint32_t tpm_get_packet_size(const uint8_t *packet)
899{
900 /* 0: tag (16 bit)
901 * 2: size (32 bit)
902 */
903 return read_be32(packet + 2);
904}
905
906uint32_t tpm_get_packet_response_code(const uint8_t *packet)
907{
908 /* 0: tag (16 bit)
909 * 2: size (32 bit)
910 * 6: resp code (32 bit)
911 */
912 return read_be32(packet + 6);
913}
914
Andrey Proninbea3f792016-07-18 11:24:55 -0700915void tpm_set_ph_disabled(int flag)
916{
917 ph_disabled = flag;
918}
Andrey Pronin3e0a3522016-07-22 18:45:37 -0700919
920int tpm_is_ph_disabled(void)
921{
922 return ph_disabled;
923}