xref: /aosp_15_r20/external/vboot_reference/firmware/lib/tpm2_lite/marshaling.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2016 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 #include "2common.h"
7 #include "2sysincludes.h"
8 #include "tpm2_marshaling.h"
9 
10 static uint16_t tpm_tag;  /* Depends on the command type. */
11 static int ph_disabled;   /* Platform hierarchy disabled. */
12 
write_be16(void * dest,uint16_t val)13 static 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 
write_be32(void * dest,uint32_t val)21 static 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 
read_be16(const void * src)31 static 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 
read_be32(const void * src)37 static 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 
unmarshal_u8(void ** buffer,int * buffer_space)56 static 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 
unmarshal_u16(void ** buffer,int * buffer_space)72 static 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 
unmarshal_u32(void ** buffer,int * buffer_space)88 static uint32_t unmarshal_u32(void **buffer, int *buffer_space)
89 {
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 
104 #define unmarshal_TPM_HANDLE(a, b) unmarshal_u32(a, b)
105 #define unmarshal_ALG_ID(a, b) unmarshal_u16(a, b)
106 
unmarshal_TPM2B(void ** buffer,int * size,TPM2B * tpm2b)107 static void unmarshal_TPM2B(void **buffer, int *size, TPM2B *tpm2b)
108 {
109 	tpm2b->size = unmarshal_u16(buffer, size);
110 	if (tpm2b->size > *size) {
111 		VB2_DEBUG("size mismatch: expected %d, remaining %d\n", tpm2b->size, *size);
112 		tpm2b->buffer = NULL;
113 		tpm2b->size = 0;
114 		*buffer = NULL;
115 		*size = -1;
116 		return;
117 	}
118 
119 	tpm2b->buffer = *buffer;
120 
121 	*buffer = ((uint8_t *)(*buffer)) + tpm2b->size;
122 	*size -= tpm2b->size;
123 }
124 
unmarshal_authorization_section(void ** buffer,int * size,const char * cmd_name)125 static void unmarshal_authorization_section(void **buffer, int *size,
126 					    const char *cmd_name)
127 {
128 	/*
129 	 * Let's ignore the authorisation section. It should be 5 bytes total,
130 	 * just confirm that this is the case and report any discrepancy.
131 	 */
132 	if (*size != 5)
133 		VB2_DEBUG("unexpected authorisation section size %d for %s\n",
134 			  *size, cmd_name);
135 
136 	*buffer = ((uint8_t *)(*buffer)) + *size;
137 	*size = 0;
138 }
139 
unmarshal_nv_read(void ** buffer,int * size,struct nv_read_response * nvr)140 static void unmarshal_nv_read(void **buffer, int *size,
141 			      struct nv_read_response *nvr)
142 {
143 	/* Total size of the parameter field. */
144 	nvr->params_size = unmarshal_u32(buffer, size);
145 	unmarshal_TPM2B(buffer, size, &nvr->buffer);
146 
147 	if (nvr->params_size != (nvr->buffer.size + sizeof(nvr->buffer.size))) {
148 		VB2_DEBUG("parameter/buffer %d/%d size mismatch", nvr->params_size,
149 			  nvr->buffer.size);
150 		return;
151 	}
152 
153 	if (*size < 0)
154 		return;
155 
156 	unmarshal_authorization_section(buffer, size, "NV_Read");
157 }
158 
unmarshal_read_public(void ** buffer,int * size,struct read_public_response * rpr)159 static void unmarshal_read_public(void **buffer, int *size,
160 				  struct read_public_response *rpr)
161 {
162 	unmarshal_TPM2B(buffer, size, &rpr->buffer);
163 
164 	if (*size < 0)
165 		return;
166 
167 	/* Drain the name & authorization sections. */
168 	*buffer = ((uint8_t *)(*buffer)) + *size;
169 	*size = 0;
170 }
171 
unmarshal_TPMS_NV_PUBLIC(void ** buffer,int * size,TPMS_NV_PUBLIC * pub)172 static void unmarshal_TPMS_NV_PUBLIC(void **buffer,
173 				     int *size,
174 				     TPMS_NV_PUBLIC *pub)
175 {
176 	int tpm2b_size = unmarshal_u16(buffer, size);
177 	if (tpm2b_size > *size) {
178 		VB2_DEBUG("size mismatch: expected %d, remaining %d\n",
179 			  tpm2b_size, *size);
180 		*size = -1;
181 		return;
182 	}
183 	*size -= tpm2b_size;
184 
185 	pub->nvIndex = unmarshal_TPM_HANDLE(buffer, &tpm2b_size);
186 	pub->nameAlg = unmarshal_ALG_ID(buffer, &tpm2b_size);
187 	pub->attributes = unmarshal_u32(buffer, &tpm2b_size);
188 	unmarshal_TPM2B(buffer, &tpm2b_size, &pub->authPolicy);
189 	pub->dataSize = unmarshal_u16(buffer, &tpm2b_size);
190 
191 	if (tpm2b_size != 0) {
192 		VB2_DEBUG("TPMS_NV_PUBLIC size doesn't match size field\n");
193 		*size = -1;
194 		return;
195 	}
196 }
197 
unmarshal_nv_read_public(void ** buffer,int * size,struct nv_read_public_response * nv_pub)198 static void unmarshal_nv_read_public(void **buffer, int *size,
199 				     struct nv_read_public_response *nv_pub)
200 {
201 	unmarshal_TPMS_NV_PUBLIC(buffer, size, &nv_pub->nvPublic);
202 	unmarshal_TPM2B(buffer, size, &nv_pub->nvName);
203 
204 	if (*size > 0) {
205 		VB2_DEBUG("extra %d bytes after nvName\n", *size);
206 		*size = -1;
207 		return;
208 	}
209 }
210 
unmarshal_TPML_TAGGED_TPM_PROPERTY(void ** buffer,int * size,TPML_TAGGED_TPM_PROPERTY * prop)211 static void unmarshal_TPML_TAGGED_TPM_PROPERTY(void **buffer, int *size,
212 					       TPML_TAGGED_TPM_PROPERTY *prop)
213 {
214 	prop->count = unmarshal_u32(buffer, size);
215 
216 	if (prop->count != 1) {
217 		*size = -1;
218 		VB2_DEBUG("Request to unmarshal unsupported "
219 			  "number of properties: %u\n",
220 			  prop->count);
221 		return;
222 	}
223 
224 	prop->tpm_property[0].property = unmarshal_u32(buffer, size);
225 	prop->tpm_property[0].value = unmarshal_u32(buffer, size);
226 }
227 
unmarshal_TPMS_CAPABILITY_DATA(void ** buffer,int * size,TPMS_CAPABILITY_DATA * cap_data)228 static void unmarshal_TPMS_CAPABILITY_DATA(void **buffer, int *size,
229 					   TPMS_CAPABILITY_DATA *cap_data)
230 {
231 	cap_data->capability = unmarshal_u32(buffer, size);
232 
233 	switch (cap_data->capability) {
234 
235 	case TPM_CAP_TPM_PROPERTIES:
236 		unmarshal_TPML_TAGGED_TPM_PROPERTY(buffer, size,
237 						   &cap_data->data.
238 						       tpm_properties);
239 		break;
240 
241 	default:
242 		*size = -1;
243 		VB2_DEBUG("Request to unmarshal unsupported capability %#x\n",
244 			  cap_data->capability);
245 	}
246 }
247 
unmarshal_get_capability(void ** buffer,int * size,struct get_capability_response * cap)248 static void unmarshal_get_capability(void **buffer, int *size,
249 				     struct get_capability_response *cap)
250 {
251 	/* Total size of the parameter field. */
252 	cap->more_data = unmarshal_u8(buffer, size);
253 	unmarshal_TPMS_CAPABILITY_DATA(buffer, size, &cap->capability_data);
254 }
255 
unmarshal_get_random(void ** buffer,int * size,struct get_random_response * random)256 static void unmarshal_get_random(void **buffer, int *size,
257 				 struct get_random_response *random)
258 {
259 	unmarshal_TPM2B(buffer, size, &random->random_bytes);
260 }
261 
unmarshal_create_primary(void ** buffer,int * size,struct create_primary_response * resp)262 static void unmarshal_create_primary(void **buffer, int *size,
263 				     struct create_primary_response *resp)
264 {
265 	resp->object_handle = unmarshal_TPM_HANDLE(buffer, size);
266 
267 	/* Drain the remaining sections. */
268 	*buffer = ((uint8_t *)(*buffer)) + *size;
269 	*size = 0;
270 }
271 
272 /*
273  * Each marshaling function receives a pointer to the buffer to marshal into,
274  * a pointer to the data item to be marshaled, and a pointer to the remaining
275  * room in the buffer.
276  */
277 
278 /*
279  * Marshaling an arbitrary blob requires its size in addition to common
280  * parameter set.
281  */
marshal_blob(void ** buffer,void * blob,size_t blob_size,int * buffer_space)282 static void marshal_blob(void **buffer, void *blob,
283 			 size_t blob_size, int *buffer_space)
284 {
285 	if (*buffer_space < blob_size) {
286 		*buffer_space = -1;
287 		return;
288 	}
289 
290 	memcpy(*buffer, blob, blob_size);
291 	*buffer_space -= blob_size;
292 	*buffer = (void *)((uintptr_t)(*buffer) + blob_size);
293 }
294 
marshal_u8(void ** buffer,uint8_t value,int * buffer_space)295 static void marshal_u8(void **buffer, uint8_t value, int *buffer_space)
296 {
297 	uint8_t *bp = *buffer;
298 
299 	if (*buffer_space < sizeof(value)) {
300 		*buffer_space = -1;
301 		return;
302 	}
303 
304 	*bp++ = value;
305 	*buffer = bp;
306 	*buffer_space -= sizeof(value);
307 }
308 
marshal_u16(void ** buffer,uint16_t value,int * buffer_space)309 static void marshal_u16(void **buffer, uint16_t value, int *buffer_space)
310 {
311 	if (*buffer_space < sizeof(value)) {
312 		*buffer_space = -1;
313 		return;
314 	}
315 	write_be16(*buffer, value);
316 	*buffer = (void *)((uintptr_t)(*buffer) + sizeof(value));
317 	*buffer_space -= sizeof(value);
318 }
319 
marshal_u32(void ** buffer,uint32_t value,int * buffer_space)320 static void marshal_u32(void **buffer, uint32_t value, int *buffer_space)
321 {
322 	if (*buffer_space < sizeof(value)) {
323 		*buffer_space = -1;
324 		return;
325 	}
326 
327 	write_be32(*buffer, value);
328 	*buffer = (void *)((uintptr_t)(*buffer) + sizeof(value));
329 	*buffer_space -= sizeof(value);
330 }
331 
332 #define marshal_TPM_HANDLE(a, b, c) marshal_u32(a, b, c)
333 #define marshal_TPM_SU(a, b, c) marshal_u16(a, b, c)
334 #define marshal_ALG_ID(a, b, c) marshal_u16(a, b, c)
335 #define marshal_TPMI_ALG_HASH(a, b, c) marshal_u16(a, b, c)
336 
337 /*
338  * For TPM2B* structures the size field (16 or 32 bits) goes before the data.
339  * When marshaling, we first reserve the space for the size field, then
340  * marshal the data, then fill the reserved size field with the actual size
341  * of the marshaled data.
342  */
343 typedef struct {
344 	int size;
345 	void *location;
346 } tpm2_marshal_size_field;
347 
marshal_reserve_size_field(void ** buffer,tpm2_marshal_size_field * field,int field_size,int * buffer_space)348 static void marshal_reserve_size_field(void **buffer,
349 				       tpm2_marshal_size_field *field,
350 				       int field_size,
351 				       int *buffer_space)
352 {
353 	if (field_size != sizeof(uint32_t) && field_size != sizeof(uint16_t)) {
354 		VB2_DEBUG("Unsupported size field size: %d\n", field_size);
355 		*buffer_space = -1;
356 		return;
357 	}
358 	if (*buffer_space < field_size) {
359 		*buffer_space = -1;
360 		return;
361 	}
362 	field->size = field_size;
363 	field->location = *buffer;
364 	*buffer_space -= field_size;
365 	*buffer = (void *)(((uintptr_t) *buffer) + field_size);
366 }
367 
marshal_fill_size_field(void ** buffer,tpm2_marshal_size_field * field,int include_size_field,int * buffer_space)368 static void marshal_fill_size_field(void **buffer,
369 				    tpm2_marshal_size_field *field,
370 				    int include_size_field,
371 				    int *buffer_space)
372 {
373 	uintptr_t size = (uintptr_t) *buffer - (uintptr_t) field->location;
374 
375 	if (*buffer_space < 0)
376 		return;  /* The structure did not fit. */
377 
378 	if (!include_size_field)
379 		size -= field->size;
380 	if (field->size == sizeof(uint32_t))
381 		marshal_u32(&field->location, size, &field->size);
382 	else /* if (field->size == sizeof(uint16_t)) */
383 		marshal_u16(&field->location, size, &field->size);
384 }
385 
marshal_session_header(void ** buffer,struct tpm2_session_header * session_header,int * buffer_space)386 static void marshal_session_header(void **buffer,
387 				   struct tpm2_session_header *session_header,
388 				   int *buffer_space)
389 {
390 	tpm2_marshal_size_field size_field;
391 
392 	/* Skip room for the session header size. */
393 	marshal_reserve_size_field(buffer, &size_field,
394 				   sizeof(uint32_t), buffer_space);
395 
396 	marshal_u32(buffer, session_header->session_handle, buffer_space);
397 	marshal_u16(buffer, session_header->nonce_size, buffer_space);
398 	marshal_blob(buffer, session_header->nonce,
399 		     session_header->nonce_size, buffer_space);
400 	marshal_u8(buffer, session_header->session_attrs, buffer_space);
401 	marshal_u16(buffer, session_header->auth_size, buffer_space);
402 	marshal_blob(buffer, session_header->auth,
403 		     session_header->auth_size, buffer_space);
404 
405 	/* Paste in the session size. */
406 	marshal_fill_size_field(buffer, &size_field, 0, buffer_space);
407 }
408 
marshal_TPM2B(void ** buffer,TPM2B * data,int * buffer_space)409 static void marshal_TPM2B(void **buffer,
410 			  TPM2B *data,
411 			  int *buffer_space)
412 {
413 	size_t total_size = data->size + sizeof(data->size);
414 
415 	if (total_size > *buffer_space) {
416 		*buffer_space = -1;
417 		return;
418 	}
419 	marshal_u16(buffer, data->size, buffer_space);
420 	memcpy(*buffer, data->buffer, data->size);
421 	*buffer = ((uint8_t *)(*buffer)) + data->size;
422 	*buffer_space -= data->size;
423 }
424 
marshal_TPMS_NV_PUBLIC(void ** buffer,TPMS_NV_PUBLIC * data,int * buffer_space)425 static void marshal_TPMS_NV_PUBLIC(void **buffer,
426 				   TPMS_NV_PUBLIC *data,
427 				   int *buffer_space)
428 {
429 	tpm2_marshal_size_field size_field;
430 
431 	/* Skip room for the size. */
432 	marshal_reserve_size_field(buffer, &size_field,
433 				   sizeof(uint16_t), buffer_space);
434 
435 	marshal_TPM_HANDLE(buffer, data->nvIndex, buffer_space);
436 	marshal_ALG_ID(buffer, data->nameAlg, buffer_space);
437 	marshal_u32(buffer, data->attributes, buffer_space);
438 	marshal_TPM2B(buffer, &data->authPolicy, buffer_space);
439 	marshal_u16(buffer, data->dataSize, buffer_space);
440 
441 	/* Paste in the structure size. */
442 	marshal_fill_size_field(buffer, &size_field, 0, buffer_space);
443 }
444 
marshal_nv_define_space(void ** buffer,struct tpm2_nv_define_space_cmd * command_body,int * buffer_space)445 static void marshal_nv_define_space(void **buffer,
446 				    struct tpm2_nv_define_space_cmd
447 				        *command_body,
448 				    int *buffer_space)
449 {
450 	struct tpm2_session_header session_header;
451 
452 	/* Use platform authorization if PLATFORMCREATE is set, and owner
453 	 * authorization otherwise (per TPM2 Spec. Part 2. Section 31.3.1).
454 	 * Owner authorization with empty password will work only until
455 	 * ownership is taken. Platform authorization will work only until
456 	 * platform hierarchy is disabled (i.e. in firmware or in recovery
457 	 * mode).
458 	 */
459 	if (command_body->publicInfo.attributes & TPMA_NV_PLATFORMCREATE)
460 		marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
461 	else
462 		marshal_TPM_HANDLE(buffer, TPM_RH_OWNER, buffer_space);
463 
464 	memset(&session_header, 0, sizeof(session_header));
465 	session_header.session_handle = TPM_RS_PW;
466 	marshal_session_header(buffer, &session_header, buffer_space);
467 	tpm_tag = TPM_ST_SESSIONS;
468 
469 	marshal_TPM2B(buffer, &command_body->auth, buffer_space);
470 	marshal_TPMS_NV_PUBLIC(buffer, &command_body->publicInfo, buffer_space);
471 }
472 
marshal_nv_undefine_space(void ** buffer,struct tpm2_nv_undefine_space_cmd * command_body,int * buffer_space)473 static void marshal_nv_undefine_space(void **buffer,
474 				      struct tpm2_nv_undefine_space_cmd
475 				          *command_body,
476 				      int *buffer_space)
477 {
478 	struct tpm2_session_header session_header;
479 
480 	/* Use platform authorization if PLATFORMCREATE is set, and owner
481 	 * authorization otherwise (per TPM2 Spec. Part 2. Section 31.3.1).
482 	 * Owner authorization with empty password will work only until
483 	 * ownership is taken. Platform authorization will work only until
484 	 * platform hierarchy is disabled (i.e. in firmware or in recovery
485 	 * mode).
486 	 */
487 	if (command_body->use_platform_auth)
488 		marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
489 	else
490 		marshal_TPM_HANDLE(buffer, TPM_RH_OWNER, buffer_space);
491 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
492 
493 	memset(&session_header, 0, sizeof(session_header));
494 	session_header.session_handle = TPM_RS_PW;
495 	marshal_session_header(buffer, &session_header, buffer_space);
496 	tpm_tag = TPM_ST_SESSIONS;
497 }
498 
499 /* Determine which authorization should be used when writing or write-locking
500  * an NV index.
501  *
502  * Use a simplified approach:
503  * 1) Use platform auth for indexes defined by TPM and Platform, as
504  * specified in "Registry of reserved TPM 2.0 handles and localities".
505  * That will only work for indexes with PPWRITE, and until the platform
506  * hierarchy is disabled.
507  * 2) Use empty password auth for other indexes.
508  * That will only work for indexes with AUTHWRITE and empty auth value.
509  *
510  * A more honest approach would require the caller to specify the
511  * authorization, or would check the NV index attributes.
512  * But that's not needed now, as all indexes defined by firmware are
513  * in the TPM range and have PPWRITE. The indexes defined by the
514  * OS are in the Owner range and have either OWNERWRITE or AUTHWRITE,
515  * but we don't ever use Tlcl to write to OWNERWRITE indexes.
516  */
get_nv_index_write_auth(TPMI_RH_NV_INDEX nvIndex)517 static TPM_HANDLE get_nv_index_write_auth(TPMI_RH_NV_INDEX nvIndex)
518 {
519 	return nvIndex >= TPMI_RH_NV_INDEX_OWNER_START ?
520 	       nvIndex :
521 	       TPM_RH_PLATFORM;
522 }
523 
marshal_nv_write(void ** buffer,struct tpm2_nv_write_cmd * command_body,int * buffer_space)524 static void marshal_nv_write(void **buffer,
525 			     struct tpm2_nv_write_cmd *command_body,
526 			     int *buffer_space)
527 {
528 	struct tpm2_session_header session_header;
529 
530 	marshal_TPM_HANDLE(buffer,
531 			   get_nv_index_write_auth(command_body->nvIndex),
532 			   buffer_space);
533 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
534 	memset(&session_header, 0, sizeof(session_header));
535 	session_header.session_handle = TPM_RS_PW;
536 	marshal_session_header(buffer, &session_header, buffer_space);
537 	tpm_tag = TPM_ST_SESSIONS;
538 
539 	marshal_TPM2B(buffer, &command_body->data, buffer_space);
540 	marshal_u16(buffer, command_body->offset, buffer_space);
541 }
542 
marshal_nv_read(void ** buffer,struct tpm2_nv_read_cmd * command_body,int * buffer_space)543 static void marshal_nv_read(void **buffer,
544 			    struct tpm2_nv_read_cmd *command_body,
545 			    int *buffer_space)
546 {
547 	struct tpm2_session_header session_header;
548 
549 	/* Use empty password auth if platform hierarchy is disabled */
550 	if (ph_disabled)
551 		marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
552 	else
553 		marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
554 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
555 	memset(&session_header, 0, sizeof(session_header));
556 	session_header.session_handle = TPM_RS_PW;
557 	marshal_session_header(buffer, &session_header, buffer_space);
558 	tpm_tag = TPM_ST_SESSIONS;
559 	marshal_u16(buffer, command_body->size, buffer_space);
560 	marshal_u16(buffer, command_body->offset, buffer_space);
561 }
562 
marshal_nv_read_lock(void ** buffer,struct tpm2_nv_read_lock_cmd * command_body,int * buffer_space)563 static void marshal_nv_read_lock(void **buffer,
564 				  struct tpm2_nv_read_lock_cmd *command_body,
565 				  int *buffer_space)
566 {
567 	struct tpm2_session_header session_header;
568 
569 	tpm_tag = TPM_ST_SESSIONS;
570 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
571 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
572 	memset(&session_header, 0, sizeof(session_header));
573 	session_header.session_handle = TPM_RS_PW;
574 	marshal_session_header(buffer, &session_header, buffer_space);
575 }
576 
marshal_nv_write_lock(void ** buffer,struct tpm2_nv_write_lock_cmd * command_body,int * buffer_space)577 static void marshal_nv_write_lock(void **buffer,
578 				  struct tpm2_nv_write_lock_cmd *command_body,
579 				  int *buffer_space)
580 {
581 	struct tpm2_session_header session_header;
582 
583 	tpm_tag = TPM_ST_SESSIONS;
584 	marshal_TPM_HANDLE(buffer,
585 			   get_nv_index_write_auth(command_body->nvIndex),
586 			   buffer_space);
587 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
588 	memset(&session_header, 0, sizeof(session_header));
589 	session_header.session_handle = TPM_RS_PW;
590 	marshal_session_header(buffer, &session_header, buffer_space);
591 }
592 
marshal_nv_read_public(void ** buffer,struct tpm2_nv_read_public_cmd * command_body,int * buffer_space)593 static void marshal_nv_read_public(void **buffer,
594 				   struct tpm2_nv_read_public_cmd *command_body,
595 				   int *buffer_space)
596 {
597 	tpm_tag = TPM_ST_NO_SESSIONS;
598 
599 	marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
600 }
601 
marshal_hierarchy_control(void ** buffer,struct tpm2_hierarchy_control_cmd * command_body,int * buffer_space)602 static void marshal_hierarchy_control(void **buffer,
603 				      struct tpm2_hierarchy_control_cmd
604 				          *command_body,
605 				      int *buffer_space)
606 {
607 	struct tpm2_session_header session_header;
608 
609 	tpm_tag = TPM_ST_SESSIONS;
610 	marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
611 	memset(&session_header, 0, sizeof(session_header));
612 	session_header.session_handle = TPM_RS_PW;
613 	marshal_session_header(buffer, &session_header, buffer_space);
614 
615 	marshal_TPM_HANDLE(buffer, command_body->enable, buffer_space);
616 	marshal_u8(buffer, command_body->state, buffer_space);
617 }
618 
marshal_read_public(void ** buffer,struct tpm2_read_public_cmd * command_body,int * buffer_space)619 static void marshal_read_public(void **buffer,
620 				struct tpm2_read_public_cmd *command_body,
621 				int *buffer_space)
622 {
623 	marshal_u32(buffer, command_body->object_handle, buffer_space);
624 }
625 
marshal_get_capability(void ** buffer,struct tpm2_get_capability_cmd * command_body,int * buffer_space)626 static void marshal_get_capability(void **buffer,
627 				   struct tpm2_get_capability_cmd
628 				       *command_body,
629 				   int *buffer_space)
630 {
631 	tpm_tag = TPM_ST_NO_SESSIONS;
632 
633 	marshal_u32(buffer, command_body->capability, buffer_space);
634 	marshal_u32(buffer, command_body->property, buffer_space);
635 	marshal_u32(buffer, command_body->property_count, buffer_space);
636 }
637 
marshal_get_random(void ** buffer,struct tpm2_get_random_cmd * command_body,int * buffer_space)638 static void marshal_get_random(void **buffer, struct tpm2_get_random_cmd
639 				       *command_body,
640 				   int *buffer_space)
641 {
642 	tpm_tag = TPM_ST_NO_SESSIONS;
643 
644 	marshal_u16(buffer, command_body->bytes_requested, buffer_space);
645 }
646 
marshal_clear(void ** buffer,void * command_body,int * buffer_space)647 static void marshal_clear(void **buffer,
648 			  void *command_body,
649 			  int *buffer_space)
650 {
651 	struct tpm2_session_header session_header;
652 
653 	tpm_tag = TPM_ST_SESSIONS;
654 	marshal_TPM_HANDLE(buffer, TPM_RH_PLATFORM, buffer_space);
655 	memset(&session_header, 0, sizeof(session_header));
656 	session_header.session_handle = TPM_RS_PW;
657 	marshal_session_header(buffer, &session_header, buffer_space);
658 }
659 
marshal_self_test(void ** buffer,struct tpm2_self_test_cmd * command_body,int * buffer_space)660 static void marshal_self_test(void **buffer,
661 			      struct tpm2_self_test_cmd *command_body,
662 			      int *buffer_space)
663 {
664 	tpm_tag = TPM_ST_NO_SESSIONS;
665 
666 	marshal_u8(buffer, command_body->full_test, buffer_space);
667 }
668 
marshal_startup(void ** buffer,struct tpm2_startup_cmd * command_body,int * buffer_space)669 static void marshal_startup(void **buffer,
670 			    struct tpm2_startup_cmd *command_body,
671 			    int *buffer_space)
672 {
673 	tpm_tag = TPM_ST_NO_SESSIONS;
674 
675 	marshal_TPM_SU(buffer, command_body->startup_type, buffer_space);
676 }
677 
marshal_shutdown(void ** buffer,struct tpm2_shutdown_cmd * command_body,int * buffer_space)678 static void marshal_shutdown(void **buffer,
679 			     struct tpm2_shutdown_cmd *command_body,
680 			     int *buffer_space)
681 {
682 	tpm_tag = TPM_ST_NO_SESSIONS;
683 
684 	marshal_TPM_SU(buffer, command_body->shutdown_type, buffer_space);
685 }
686 
marshal_evict_control(void ** buffer,struct tpm2_evict_control_cmd * command_body,int * buffer_space)687 static void marshal_evict_control(void **buffer,
688 				  struct tpm2_evict_control_cmd *command_body,
689 				  int *buffer_space)
690 {
691 	struct tpm2_session_header session_header;
692 
693 	marshal_TPM_HANDLE(buffer, command_body->auth, buffer_space);
694 	marshal_TPM_HANDLE(buffer, command_body->object_handle, buffer_space);
695 
696 	memset(&session_header, 0, sizeof(session_header));
697 	session_header.session_handle = TPM_RS_PW;
698 	marshal_session_header(buffer, &session_header, buffer_space);
699 	tpm_tag = TPM_ST_SESSIONS;
700 
701 	marshal_TPM_HANDLE(buffer, command_body->persistent_handle,
702 			   buffer_space);
703 }
704 
marshal_create_primary(void ** buffer,struct tpm2_create_primary_cmd * command_body,int * buffer_space)705 static void marshal_create_primary(void **buffer,
706 				   struct tpm2_create_primary_cmd *command_body,
707 				   int *buffer_space)
708 {
709 	struct tpm2_session_header session_header;
710 
711 	marshal_TPM_HANDLE(buffer, command_body->primary_handle, buffer_space);
712 
713 	memset(&session_header, 0, sizeof(session_header));
714 	session_header.session_handle = TPM_RS_PW;
715 	marshal_session_header(buffer, &session_header, buffer_space);
716 	tpm_tag = TPM_ST_SESSIONS;
717 
718 	marshal_TPM2B(buffer, &command_body->in_sensitive, buffer_space);
719 	marshal_TPM2B(buffer, &command_body->in_public, buffer_space);
720 	// Empty outsideInfo.
721 	marshal_u16(buffer, 0, buffer_space);
722 	// Empty creationPCR.
723 	marshal_u32(buffer, 0, buffer_space);
724 }
725 
marshal_TPMT_HA(void ** buffer,TPMT_HA * data,int * buffer_space)726 static void marshal_TPMT_HA(void **buffer,
727 			    TPMT_HA *data,
728 			    int *buffer_space)
729 {
730 	if (data->hashAlg != TPM_ALG_SHA256)
731 	{
732 		VB2_DEBUG("Unsupported TPMT_HA hash algorithm: %#x\n",
733 			  data->hashAlg);
734 		*buffer_space = -1;
735 		return;
736 	}
737 	marshal_TPMI_ALG_HASH(buffer, data->hashAlg, buffer_space);
738 	/* We only support SHA256 now. */
739 	marshal_blob(buffer, data->digest.sha256,
740 		     SHA256_DIGEST_SIZE, buffer_space);
741 }
742 
marshal_TPML_DIGEST_VALUES(void ** buffer,TPML_DIGEST_VALUES * data,int * buffer_space)743 static void marshal_TPML_DIGEST_VALUES(void **buffer,
744 				       TPML_DIGEST_VALUES *data,
745 				       int *buffer_space)
746 {
747 	int i;
748 
749 	marshal_u32(buffer, data->count, buffer_space);
750 	for (i = 0; i < data->count; i++)
751 		marshal_TPMT_HA(buffer, &data->digests[i], buffer_space);
752 }
753 
marshal_pcr_extend(void ** buffer,struct tpm2_pcr_extend_cmd * command_body,int * buffer_space)754 static void marshal_pcr_extend(void **buffer,
755 			       struct tpm2_pcr_extend_cmd *command_body,
756 			       int *buffer_space)
757 {
758 	struct tpm2_session_header session_header;
759 
760 	tpm_tag = TPM_ST_SESSIONS;
761 	marshal_TPM_HANDLE(buffer, command_body->pcrHandle, buffer_space);
762 	memset(&session_header, 0, sizeof(session_header));
763 	session_header.session_handle = TPM_RS_PW;
764 	marshal_session_header(buffer, &session_header, buffer_space);
765 	marshal_TPML_DIGEST_VALUES(buffer, &command_body->digests, buffer_space);
766 }
767 
tpm_marshal_command(TPM_CC command,void * tpm_command_body,void * buffer,int buffer_size)768 int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
769 			void *buffer, int buffer_size)
770 {
771 	void *cmd_body = (uint8_t *)buffer + sizeof(struct tpm_header);
772 	int max_body_size = buffer_size - sizeof(struct tpm_header);
773 	int body_size = max_body_size;
774 
775 	/* Will be modified when marshaling some commands. */
776 	tpm_tag = TPM_ST_NO_SESSIONS;
777 
778 	switch (command) {
779 
780 	case TPM2_NV_DefineSpace:
781 		marshal_nv_define_space(&cmd_body, tpm_command_body, &body_size);
782 		break;
783 
784 	case TPM2_NV_UndefineSpace:
785 		marshal_nv_undefine_space(&cmd_body, tpm_command_body, &body_size);
786 		break;
787 
788 	case TPM2_NV_Read:
789 		marshal_nv_read(&cmd_body, tpm_command_body, &body_size);
790 		break;
791 
792 	case TPM2_NV_Write:
793 		marshal_nv_write(&cmd_body, tpm_command_body, &body_size);
794 		break;
795 
796 	case TPM2_NV_ReadLock:
797 		marshal_nv_read_lock(&cmd_body, tpm_command_body, &body_size);
798 		break;
799 
800 	case TPM2_NV_WriteLock:
801 		marshal_nv_write_lock(&cmd_body, tpm_command_body, &body_size);
802 		break;
803 
804 	case TPM2_NV_ReadPublic:
805 		marshal_nv_read_public(&cmd_body, tpm_command_body, &body_size);
806 		break;
807 
808 	case TPM2_Hierarchy_Control:
809 		marshal_hierarchy_control(&cmd_body,
810 					  tpm_command_body, &body_size);
811 		break;
812 
813 	case TPM2_GetCapability:
814 		marshal_get_capability(&cmd_body, tpm_command_body, &body_size);
815 		break;
816 
817 	case TPM2_GetRandom:
818 		marshal_get_random(&cmd_body, tpm_command_body, &body_size);
819 		break;
820 
821 	case TPM2_Clear:
822 		marshal_clear(&cmd_body, tpm_command_body, &body_size);
823 		break;
824 
825 	case TPM2_SelfTest:
826 		marshal_self_test(&cmd_body, tpm_command_body, &body_size);
827 		break;
828 
829 	case TPM2_Startup:
830 		marshal_startup(&cmd_body, tpm_command_body, &body_size);
831 		break;
832 
833 	case TPM2_Shutdown:
834 		marshal_shutdown(&cmd_body, tpm_command_body, &body_size);
835 		break;
836 
837 	case TPM2_PCR_Extend:
838 		marshal_pcr_extend(&cmd_body, tpm_command_body, &body_size);
839 		break;
840 
841 	case TPM2_ReadPublic:
842 		marshal_read_public(&cmd_body, tpm_command_body, &body_size);
843 		break;
844 
845 	case TPM2_EvictControl:
846 		marshal_evict_control(&cmd_body, tpm_command_body, &body_size);
847 		break;
848 
849 	case TPM2_CreatePrimary:
850 		marshal_create_primary(&cmd_body, tpm_command_body, &body_size);
851 		break;
852 
853 	default:
854 		body_size = -1;
855 		VB2_DEBUG("Request to marshal unsupported command %#x\n",
856 			  command);
857 	}
858 
859 	if (body_size > 0) {
860 
861 		/* See how much room was taken by marshaling. */
862 		body_size = max_body_size - body_size;
863 
864 		body_size += sizeof(struct tpm_header);
865 
866 		marshal_u16(&buffer, tpm_tag, &max_body_size);
867 		marshal_u32(&buffer, body_size, &max_body_size);
868 		marshal_u32(&buffer, command, &max_body_size);
869 	}
870 
871 	return body_size;
872 }
873 
tpm_unmarshal_response(TPM_CC command,void * response_body,int cr_size,struct tpm2_response * response)874 int tpm_unmarshal_response(TPM_CC command,
875 			   void *response_body,
876 			   int cr_size,
877 			   struct tpm2_response *response)
878 {
879 	if (cr_size < sizeof(struct tpm_header))
880 		return -1;
881 
882 	response->hdr.tpm_tag = unmarshal_u16(&response_body, &cr_size);
883 	response->hdr.tpm_size = unmarshal_u32(&response_body, &cr_size);
884 	response->hdr.tpm_code = unmarshal_u32(&response_body, &cr_size);
885 
886 	if (!cr_size) {
887 		if (response->hdr.tpm_size != sizeof(response->hdr))
888 			VB2_DEBUG("size mismatch in response to command %#x\n",
889 				  command);
890 		return 0;
891 	}
892 
893 	switch (command) {
894 	case TPM2_NV_Read:
895 		unmarshal_nv_read(&response_body, &cr_size,
896 				  &response->nvr);
897 		break;
898 
899 	case TPM2_NV_ReadPublic:
900 		unmarshal_nv_read_public(&response_body, &cr_size,
901 				         &response->nv_read_public);
902 		break;
903 
904 	case TPM2_GetCapability:
905 		unmarshal_get_capability(&response_body, &cr_size,
906 					 &response->cap);
907 		break;
908 
909 	case TPM2_GetRandom:
910 		unmarshal_get_random(&response_body, &cr_size,
911 				     &response->random);
912 		break;
913 
914 	case TPM2_ReadPublic:
915 		unmarshal_read_public(&response_body, &cr_size,
916 				      &response->read_pub);
917 		break;
918 
919 	case TPM2_CreatePrimary:
920 		unmarshal_create_primary(&response_body, &cr_size,
921 					 &response->create_primary);
922 		break;
923 
924 	case TPM2_Hierarchy_Control:
925 	case TPM2_NV_Write:
926 	case TPM2_NV_WriteLock:
927 	case TPM2_NV_ReadLock:
928 	case TPM2_Clear:
929 	case TPM2_SelfTest:
930 	case TPM2_Startup:
931 	case TPM2_Shutdown:
932 	case TPM2_NV_DefineSpace:
933 	case TPM2_NV_UndefineSpace:
934 	case TPM2_PCR_Extend:
935 	case TPM2_EvictControl:
936 		/* Session data included in response can be safely ignored. */
937 		cr_size = 0;
938 		break;
939 
940 	default:
941 		{
942 			int i;
943 
944 			VB2_DEBUG("Request to unmarshal unexpected command %#x,"
945 				  " code %#x",
946 				  command,
947 				  response->hdr.tpm_code);
948 
949 			for (i = 0; i < cr_size; i++) {
950 				if (!(i % 16))
951 					VB2_DEBUG_RAW("\n");
952 				VB2_DEBUG_RAW("%2.2x ",
953 					      ((uint8_t *)response_body)[i]);
954 			}
955 		}
956 		VB2_DEBUG("\n");
957 		return -1;
958 	}
959 
960 	if (cr_size) {
961 		VB2_DEBUG("got %d bytes back in response to %#x,"
962 			  " failed to parse (%d)\n",
963 			  response->hdr.tpm_size,
964 			  command, cr_size);
965 		return -1;
966 	}
967 
968 	/* The entire message have been parsed. */
969 	return 0;
970 }
971 
tpm_get_packet_size(const uint8_t * packet)972 uint32_t tpm_get_packet_size(const uint8_t *packet)
973 {
974 	/* 0: tag (16 bit)
975 	 * 2: size (32 bit)
976 	 */
977 	return read_be32(packet + 2);
978 }
979 
tpm_get_packet_response_code(const uint8_t * packet)980 uint32_t tpm_get_packet_response_code(const uint8_t *packet)
981 {
982 	/* 0: tag (16 bit)
983 	 * 2: size (32 bit)
984 	 * 6: resp code (32 bit)
985 	 */
986 	return read_be32(packet + 6);
987 }
988 
tpm_set_ph_disabled(int flag)989 void tpm_set_ph_disabled(int flag)
990 {
991 	ph_disabled = flag;
992 }
993 
tpm_is_ph_disabled(void)994 int tpm_is_ph_disabled(void)
995 {
996 	return ph_disabled;
997 }
998