blob: bc9652d8e4eeecc7dcc85bfc941e4efdd5919716 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Che-liang Chiouc18f9012013-02-28 09:34:57 +00002/*
3 * Copyright (c) 2013 The Chromium OS Authors.
Reinhard Pfau4fece432013-06-26 15:55:13 +02004 * Coypright (c) 2013 Guntermann & Drunck GmbH
Che-liang Chiouc18f9012013-02-28 09:34:57 +00005 */
6
7#include <common.h>
Simon Glass3e4f2fd2015-08-22 18:31:32 -06008#include <dm.h>
Che-liang Chiouc18f9012013-02-28 09:34:57 +00009#include <tpm.h>
10#include <asm/unaligned.h>
Simon Glass3e4f2fd2015-08-22 18:31:32 -060011#include <u-boot/sha1.h>
Che-liang Chiouc18f9012013-02-28 09:34:57 +000012
13/* Internal error of TPM command library */
14#define TPM_LIB_ERROR ((uint32_t)~0u)
15
16/* Useful constants */
17enum {
18 COMMAND_BUFFER_SIZE = 256,
Che-liang Chiouc18f9012013-02-28 09:34:57 +000019 TPM_REQUEST_HEADER_LENGTH = 10,
20 TPM_RESPONSE_HEADER_LENGTH = 10,
21 PCR_DIGEST_LENGTH = 20,
Reinhard Pfau4fece432013-06-26 15:55:13 +020022 DIGEST_LENGTH = 20,
23 TPM_REQUEST_AUTH_LENGTH = 45,
24 TPM_RESPONSE_AUTH_LENGTH = 41,
25 /* some max lengths, valid for RSA keys <= 2048 bits */
26 TPM_KEY12_MAX_LENGTH = 618,
27 TPM_PUBKEY_MAX_LENGTH = 288,
Che-liang Chiouc18f9012013-02-28 09:34:57 +000028};
29
Reinhard Pfau4fece432013-06-26 15:55:13 +020030#ifdef CONFIG_TPM_AUTH_SESSIONS
31
32#ifndef CONFIG_SHA1
33#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
34#endif /* !CONFIG_SHA1 */
35
36struct session_data {
37 int valid;
38 uint32_t handle;
39 uint8_t nonce_even[DIGEST_LENGTH];
40 uint8_t nonce_odd[DIGEST_LENGTH];
41};
42
43static struct session_data oiap_session = {0, };
44
45#endif /* CONFIG_TPM_AUTH_SESSIONS */
46
Che-liang Chiouc18f9012013-02-28 09:34:57 +000047/**
48 * Pack data into a byte string. The data types are specified in
49 * the format string: 'b' means unsigned byte, 'w' unsigned word,
50 * 'd' unsigned double word, and 's' byte string. The data are a
51 * series of offsets and values (for type byte string there are also
52 * lengths). The data values are packed into the byte string
53 * sequentially, and so a latter value could over-write a former
54 * value.
55 *
56 * @param str output string
57 * @param size size of output string
58 * @param format format string
59 * @param ... data points
60 * @return 0 on success, non-0 on error
61 */
62int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
63{
64 va_list args;
65 size_t offset = 0, length = 0;
66 uint8_t *data = NULL;
67 uint32_t value = 0;
68
69 va_start(args, format);
70 for (; *format; format++) {
71 switch (*format) {
72 case 'b':
73 offset = va_arg(args, size_t);
74 value = va_arg(args, int);
75 length = 1;
76 break;
77 case 'w':
78 offset = va_arg(args, size_t);
79 value = va_arg(args, int);
80 length = 2;
81 break;
82 case 'd':
83 offset = va_arg(args, size_t);
84 value = va_arg(args, uint32_t);
85 length = 4;
86 break;
87 case 's':
88 offset = va_arg(args, size_t);
89 data = va_arg(args, uint8_t *);
90 length = va_arg(args, uint32_t);
91 break;
92 default:
93 debug("Couldn't recognize format string\n");
André Draszik3e490f62017-10-03 16:55:54 +010094 va_end(args);
Che-liang Chiouc18f9012013-02-28 09:34:57 +000095 return -1;
96 }
97
xypron.glpk@gmx.deb7af1572017-07-30 21:40:37 +020098 if (offset + length > size) {
99 va_end(args);
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000100 return -1;
xypron.glpk@gmx.deb7af1572017-07-30 21:40:37 +0200101 }
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000102
103 switch (*format) {
104 case 'b':
105 str[offset] = value;
106 break;
107 case 'w':
108 put_unaligned_be16(value, str + offset);
109 break;
110 case 'd':
111 put_unaligned_be32(value, str + offset);
112 break;
113 case 's':
114 memcpy(str + offset, data, length);
115 break;
116 }
117 }
118 va_end(args);
119
120 return 0;
121}
122
123/**
124 * Unpack data from a byte string. The data types are specified in
125 * the format string: 'b' means unsigned byte, 'w' unsigned word,
126 * 'd' unsigned double word, and 's' byte string. The data are a
127 * series of offsets and pointers (for type byte string there are also
128 * lengths).
129 *
130 * @param str output string
131 * @param size size of output string
132 * @param format format string
133 * @param ... data points
134 * @return 0 on success, non-0 on error
135 */
136int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
137{
138 va_list args;
139 size_t offset = 0, length = 0;
140 uint8_t *ptr8 = NULL;
141 uint16_t *ptr16 = NULL;
142 uint32_t *ptr32 = NULL;
143
144 va_start(args, format);
145 for (; *format; format++) {
146 switch (*format) {
147 case 'b':
148 offset = va_arg(args, size_t);
149 ptr8 = va_arg(args, uint8_t *);
150 length = 1;
151 break;
152 case 'w':
153 offset = va_arg(args, size_t);
154 ptr16 = va_arg(args, uint16_t *);
155 length = 2;
156 break;
157 case 'd':
158 offset = va_arg(args, size_t);
159 ptr32 = va_arg(args, uint32_t *);
160 length = 4;
161 break;
162 case 's':
163 offset = va_arg(args, size_t);
164 ptr8 = va_arg(args, uint8_t *);
165 length = va_arg(args, uint32_t);
166 break;
167 default:
xypron.glpk@gmx.deb7af1572017-07-30 21:40:37 +0200168 va_end(args);
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000169 debug("Couldn't recognize format string\n");
170 return -1;
171 }
172
André Draszik3e490f62017-10-03 16:55:54 +0100173 if (offset + length > size) {
174 va_end(args);
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000175 return -1;
André Draszik3e490f62017-10-03 16:55:54 +0100176 }
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000177
178 switch (*format) {
179 case 'b':
180 *ptr8 = str[offset];
181 break;
182 case 'w':
183 *ptr16 = get_unaligned_be16(str + offset);
184 break;
185 case 'd':
186 *ptr32 = get_unaligned_be32(str + offset);
187 break;
188 case 's':
189 memcpy(ptr8, str + offset, length);
190 break;
191 }
192 }
193 va_end(args);
194
195 return 0;
196}
197
198/**
199 * Get TPM command size.
200 *
201 * @param command byte string of TPM command
202 * @return command size of the TPM command
203 */
204static uint32_t tpm_command_size(const void *command)
205{
206 const size_t command_size_offset = 2;
207 return get_unaligned_be32(command + command_size_offset);
208}
209
210/**
211 * Get TPM response return code, which is one of TPM_RESULT values.
212 *
213 * @param response byte string of TPM response
214 * @return return code of the TPM response
215 */
216static uint32_t tpm_return_code(const void *response)
217{
218 const size_t return_code_offset = 6;
219 return get_unaligned_be32(response + return_code_offset);
220}
221
222/**
223 * Send a TPM command and return response's return code, and optionally
224 * return response to caller.
225 *
226 * @param command byte string of TPM command
227 * @param response output buffer for TPM response, or NULL if the
228 * caller does not care about it
229 * @param size_ptr output buffer size (input parameter) and TPM
230 * response length (output parameter); this parameter
231 * is a bidirectional
232 * @return return code of the TPM response
233 */
234static uint32_t tpm_sendrecv_command(const void *command,
235 void *response, size_t *size_ptr)
236{
Christophe Ricard52d309b2015-10-06 22:54:43 +0200237 struct udevice *dev;
Tom Rini6b2d40c2017-05-10 15:20:18 -0400238 int err, ret;
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000239 uint8_t response_buffer[COMMAND_BUFFER_SIZE];
240 size_t response_length;
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000241
242 if (response) {
243 response_length = *size_ptr;
244 } else {
245 response = response_buffer;
246 response_length = sizeof(response_buffer);
247 }
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600248
Simon Glassc7298e72016-02-11 13:23:26 -0700249 ret = uclass_first_device_err(UCLASS_TPM, &dev);
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600250 if (ret)
251 return ret;
252 err = tpm_xfer(dev, command, tpm_command_size(command),
253 response, &response_length);
Christophe Ricard52d309b2015-10-06 22:54:43 +0200254
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600255 if (err < 0)
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000256 return TPM_LIB_ERROR;
Reinhard Pfau4fece432013-06-26 15:55:13 +0200257 if (size_ptr)
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000258 *size_ptr = response_length;
259
260 return tpm_return_code(response);
261}
262
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600263int tpm_init(void)
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000264{
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600265 int err;
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600266 struct udevice *dev;
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000267
Simon Glassc7298e72016-02-11 13:23:26 -0700268 err = uclass_first_device_err(UCLASS_TPM, &dev);
269 if (err)
Simon Glass3e4f2fd2015-08-22 18:31:32 -0600270 return err;
271 return tpm_open(dev);
Che-liang Chiouc18f9012013-02-28 09:34:57 +0000272}
273
274uint32_t tpm_startup(enum tpm_startup_type mode)
275{
276 const uint8_t command[12] = {
277 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
278 };
279 const size_t mode_offset = 10;
280 uint8_t buf[COMMAND_BUFFER_SIZE];
281
282 if (pack_byte_string(buf, sizeof(buf), "sw",
283 0, command, sizeof(command),
284 mode_offset, mode))
285 return TPM_LIB_ERROR;
286
287 return tpm_sendrecv_command(buf, NULL, NULL);
288}
289
290uint32_t tpm_self_test_full(void)
291{
292 const uint8_t command[10] = {
293 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
294 };
295 return tpm_sendrecv_command(command, NULL, NULL);
296}
297
298uint32_t tpm_continue_self_test(void)
299{
300 const uint8_t command[10] = {
301 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
302 };
303 return tpm_sendrecv_command(command, NULL, NULL);
304}
305
306uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
307{
308 const uint8_t command[101] = {
309 0x0, 0xc1, /* TPM_TAG */
310 0x0, 0x0, 0x0, 0x65, /* parameter size */
311 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
312 /* TPM_NV_DATA_PUBLIC->... */
313 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
314 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
315 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
316 0x0, 0x3,
317 0, 0, 0,
318 0x1f,
319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
321 0x0, 0x3,
322 0, 0, 0,
323 0x1f,
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
325 /* TPM_NV_ATTRIBUTES->... */
326 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
327 0, 0, 0, 0, /* ...->attributes */
328 /* End of TPM_NV_ATTRIBUTES */
329 0, /* bReadSTClear */
330 0, /* bWriteSTClear */
331 0, /* bWriteDefine */
332 0, 0, 0, 0, /* size */
333 };
334 const size_t index_offset = 12;
335 const size_t perm_offset = 70;
336 const size_t size_offset = 77;
337 uint8_t buf[COMMAND_BUFFER_SIZE];
338
339 if (pack_byte_string(buf, sizeof(buf), "sddd",
340 0, command, sizeof(command),
341 index_offset, index,
342 perm_offset, perm,
343 size_offset, size))
344 return TPM_LIB_ERROR;
345
346 return tpm_sendrecv_command(buf, NULL, NULL);
347}
348
349uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
350{
351 const uint8_t command[22] = {
352 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
353 };
354 const size_t index_offset = 10;
355 const size_t length_offset = 18;
356 const size_t data_size_offset = 10;
357 const size_t data_offset = 14;
358 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
359 size_t response_length = sizeof(response);
360 uint32_t data_size;
361 uint32_t err;
362
363 if (pack_byte_string(buf, sizeof(buf), "sdd",
364 0, command, sizeof(command),
365 index_offset, index,
366 length_offset, count))
367 return TPM_LIB_ERROR;
368 err = tpm_sendrecv_command(buf, response, &response_length);
369 if (err)
370 return err;
371 if (unpack_byte_string(response, response_length, "d",
372 data_size_offset, &data_size))
373 return TPM_LIB_ERROR;
374 if (data_size > count)
375 return TPM_LIB_ERROR;
376 if (unpack_byte_string(response, response_length, "s",
377 data_offset, data, data_size))
378 return TPM_LIB_ERROR;
379
380 return 0;
381}
382
383uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
384{
385 const uint8_t command[256] = {
386 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
387 };
388 const size_t command_size_offset = 2;
389 const size_t index_offset = 10;
390 const size_t length_offset = 18;
391 const size_t data_offset = 22;
392 const size_t write_info_size = 12;
393 const uint32_t total_length =
394 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
395 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
396 size_t response_length = sizeof(response);
397 uint32_t err;
398
399 if (pack_byte_string(buf, sizeof(buf), "sddds",
400 0, command, sizeof(command),
401 command_size_offset, total_length,
402 index_offset, index,
403 length_offset, length,
404 data_offset, data, length))
405 return TPM_LIB_ERROR;
406 err = tpm_sendrecv_command(buf, response, &response_length);
407 if (err)
408 return err;
409
410 return 0;
411}
412
413uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
414{
415 const uint8_t command[34] = {
416 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
417 };
418 const size_t index_offset = 10;
419 const size_t in_digest_offset = 14;
420 const size_t out_digest_offset = 10;
421 uint8_t buf[COMMAND_BUFFER_SIZE];
422 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
423 size_t response_length = sizeof(response);
424 uint32_t err;
425
426 if (pack_byte_string(buf, sizeof(buf), "sds",
427 0, command, sizeof(command),
428 index_offset, index,
429 in_digest_offset, in_digest,
430 PCR_DIGEST_LENGTH))
431 return TPM_LIB_ERROR;
432 err = tpm_sendrecv_command(buf, response, &response_length);
433 if (err)
434 return err;
435
436 if (unpack_byte_string(response, response_length, "s",
437 out_digest_offset, out_digest,
438 PCR_DIGEST_LENGTH))
439 return TPM_LIB_ERROR;
440
441 return 0;
442}
443
444uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
445{
446 const uint8_t command[14] = {
447 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
448 };
449 const size_t index_offset = 10;
450 const size_t out_digest_offset = 10;
451 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
452 size_t response_length = sizeof(response);
453 uint32_t err;
454
455 if (count < PCR_DIGEST_LENGTH)
456 return TPM_LIB_ERROR;
457
458 if (pack_byte_string(buf, sizeof(buf), "sd",
459 0, command, sizeof(command),
460 index_offset, index))
461 return TPM_LIB_ERROR;
462 err = tpm_sendrecv_command(buf, response, &response_length);
463 if (err)
464 return err;
465 if (unpack_byte_string(response, response_length, "s",
466 out_digest_offset, data, PCR_DIGEST_LENGTH))
467 return TPM_LIB_ERROR;
468
469 return 0;
470}
471
472uint32_t tpm_tsc_physical_presence(uint16_t presence)
473{
474 const uint8_t command[12] = {
475 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
476 };
477 const size_t presence_offset = 10;
478 uint8_t buf[COMMAND_BUFFER_SIZE];
479
480 if (pack_byte_string(buf, sizeof(buf), "sw",
481 0, command, sizeof(command),
482 presence_offset, presence))
483 return TPM_LIB_ERROR;
484
485 return tpm_sendrecv_command(buf, NULL, NULL);
486}
487
488uint32_t tpm_read_pubek(void *data, size_t count)
489{
490 const uint8_t command[30] = {
491 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
492 };
493 const size_t response_size_offset = 2;
494 const size_t data_offset = 10;
495 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
496 uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
497 size_t response_length = sizeof(response);
498 uint32_t data_size;
499 uint32_t err;
500
501 err = tpm_sendrecv_command(command, response, &response_length);
502 if (err)
503 return err;
504 if (unpack_byte_string(response, response_length, "d",
505 response_size_offset, &data_size))
506 return TPM_LIB_ERROR;
507 if (data_size < header_and_checksum_size)
508 return TPM_LIB_ERROR;
509 data_size -= header_and_checksum_size;
510 if (data_size > count)
511 return TPM_LIB_ERROR;
512 if (unpack_byte_string(response, response_length, "s",
513 data_offset, data, data_size))
514 return TPM_LIB_ERROR;
515
516 return 0;
517}
518
519uint32_t tpm_force_clear(void)
520{
521 const uint8_t command[10] = {
522 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
523 };
524
525 return tpm_sendrecv_command(command, NULL, NULL);
526}
527
528uint32_t tpm_physical_enable(void)
529{
530 const uint8_t command[10] = {
531 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
532 };
533
534 return tpm_sendrecv_command(command, NULL, NULL);
535}
536
537uint32_t tpm_physical_disable(void)
538{
539 const uint8_t command[10] = {
540 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
541 };
542
543 return tpm_sendrecv_command(command, NULL, NULL);
544}
545
546uint32_t tpm_physical_set_deactivated(uint8_t state)
547{
548 const uint8_t command[11] = {
549 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
550 };
551 const size_t state_offset = 10;
552 uint8_t buf[COMMAND_BUFFER_SIZE];
553
554 if (pack_byte_string(buf, sizeof(buf), "sb",
555 0, command, sizeof(command),
556 state_offset, state))
557 return TPM_LIB_ERROR;
558
559 return tpm_sendrecv_command(buf, NULL, NULL);
560}
561
562uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
563 void *cap, size_t count)
564{
565 const uint8_t command[22] = {
566 0x0, 0xc1, /* TPM_TAG */
567 0x0, 0x0, 0x0, 0x16, /* parameter size */
568 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
569 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
570 0x0, 0x0, 0x0, 0x4, /* subcap size */
571 0x0, 0x0, 0x0, 0x0, /* subcap value */
572 };
573 const size_t cap_area_offset = 10;
574 const size_t sub_cap_offset = 18;
575 const size_t cap_offset = 14;
576 const size_t cap_size_offset = 10;
577 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
578 size_t response_length = sizeof(response);
579 uint32_t cap_size;
580 uint32_t err;
581
582 if (pack_byte_string(buf, sizeof(buf), "sdd",
583 0, command, sizeof(command),
584 cap_area_offset, cap_area,
585 sub_cap_offset, sub_cap))
586 return TPM_LIB_ERROR;
587 err = tpm_sendrecv_command(buf, response, &response_length);
588 if (err)
589 return err;
590 if (unpack_byte_string(response, response_length, "d",
591 cap_size_offset, &cap_size))
592 return TPM_LIB_ERROR;
593 if (cap_size > response_length || cap_size > count)
594 return TPM_LIB_ERROR;
595 if (unpack_byte_string(response, response_length, "s",
596 cap_offset, cap, cap_size))
597 return TPM_LIB_ERROR;
598
599 return 0;
600}
Reinhard Pfau4fece432013-06-26 15:55:13 +0200601
Simon Glassff9f04a2015-08-22 18:31:41 -0600602uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
603{
604 const uint8_t command[22] = {
605 0x0, 0xc1, /* TPM_TAG */
606 0x0, 0x0, 0x0, 0x16, /* parameter size */
607 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
608 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
609 0x0, 0x0, 0x0, 0x4, /* subcap size */
610 0x0, 0x0, 0x1, 0x8, /* subcap value */
611 };
André Draszik1361fbc2017-10-03 16:55:51 +0100612 const size_t data_size_offset = TPM_HEADER_SIZE;
613 const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
Simon Glassff9f04a2015-08-22 18:31:41 -0600614 uint8_t response[COMMAND_BUFFER_SIZE];
615 size_t response_length = sizeof(response);
616 uint32_t err;
André Draszik1361fbc2017-10-03 16:55:51 +0100617 uint32_t data_size;
Simon Glassff9f04a2015-08-22 18:31:41 -0600618
619 err = tpm_sendrecv_command(command, response, &response_length);
620 if (err)
621 return err;
André Draszik1361fbc2017-10-03 16:55:51 +0100622 if (unpack_byte_string(response, response_length, "d",
623 data_size_offset, &data_size))
624 return TPM_LIB_ERROR;
625 if (data_size < sizeof(*pflags))
626 return TPM_LIB_ERROR;
627 if (unpack_byte_string(response, response_length, "s",
628 data_offset, pflags, sizeof(*pflags)))
629 return TPM_LIB_ERROR;
Simon Glassff9f04a2015-08-22 18:31:41 -0600630
631 return 0;
632}
633
634uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
635{
636 const uint8_t command[22] = {
637 0x0, 0xc1, /* TPM_TAG */
638 0x0, 0x0, 0x0, 0x16, /* parameter size */
639 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
640 0x0, 0x0, 0x0, 0x11,
641 0x0, 0x0, 0x0, 0x4,
642 };
643 const size_t index_offset = 18;
644 const size_t perm_offset = 60;
645 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
646 size_t response_length = sizeof(response);
647 uint32_t err;
648
649 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
650 index_offset, index))
651 return TPM_LIB_ERROR;
652 err = tpm_sendrecv_command(buf, response, &response_length);
653 if (err)
654 return err;
655 if (unpack_byte_string(response, response_length, "d",
656 perm_offset, perm))
657 return TPM_LIB_ERROR;
658
659 return 0;
660}
661
Mario Six4eceb6c2017-01-11 16:00:50 +0100662#ifdef CONFIG_TPM_FLUSH_RESOURCES
663uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
664{
665 const uint8_t command[18] = {
666 0x00, 0xc1, /* TPM_TAG */
667 0x00, 0x00, 0x00, 0x12, /* parameter size */
668 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
669 0x00, 0x00, 0x00, 0x00, /* key handle */
670 0x00, 0x00, 0x00, 0x00, /* resource type */
671 };
672 const size_t key_handle_offset = 10;
673 const size_t resource_type_offset = 14;
674 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
675 size_t response_length = sizeof(response);
676 uint32_t err;
677
678 if (pack_byte_string(buf, sizeof(buf), "sdd",
679 0, command, sizeof(command),
680 key_handle_offset, key_handle,
681 resource_type_offset, resource_type))
682 return TPM_LIB_ERROR;
683
684 err = tpm_sendrecv_command(buf, response, &response_length);
685 if (err)
686 return err;
687 return 0;
688}
689#endif /* CONFIG_TPM_FLUSH_RESOURCES */
690
Reinhard Pfau4fece432013-06-26 15:55:13 +0200691#ifdef CONFIG_TPM_AUTH_SESSIONS
692
693/**
694 * Fill an authentication block in a request.
695 * This func can create the first as well as the second auth block (for
696 * double authorized commands).
697 *
698 * @param request pointer to the request (w/ uninitialised auth data)
699 * @param request_len0 length of the request without auth data
700 * @param handles_len length of the handles area in request
701 * @param auth_session pointer to the (valid) auth session to be used
702 * @param request_auth pointer to the auth block of the request to be filled
703 * @param auth authentication data (HMAC key)
704 */
705static uint32_t create_request_auth(const void *request, size_t request_len0,
706 size_t handles_len,
707 struct session_data *auth_session,
708 void *request_auth, const void *auth)
709{
710 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
711 sha1_context hash_ctx;
712 const size_t command_code_offset = 6;
713 const size_t auth_nonce_odd_offset = 4;
714 const size_t auth_continue_offset = 24;
715 const size_t auth_auth_offset = 25;
716
717 if (!auth_session || !auth_session->valid)
718 return TPM_LIB_ERROR;
719
720 sha1_starts(&hash_ctx);
721 sha1_update(&hash_ctx, request + command_code_offset, 4);
722 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
723 sha1_update(&hash_ctx,
724 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
725 request_len0 - TPM_REQUEST_HEADER_LENGTH
726 - handles_len);
727 sha1_finish(&hash_ctx, hmac_data);
728
729 sha1_starts(&hash_ctx);
730 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
731 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
732 sha1_finish(&hash_ctx, auth_session->nonce_odd);
733
734 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
735 0, auth_session->handle,
736 auth_nonce_odd_offset, auth_session->nonce_odd,
737 DIGEST_LENGTH,
738 auth_continue_offset, 1))
739 return TPM_LIB_ERROR;
740 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
741 DIGEST_LENGTH,
742 auth_session->nonce_even,
743 DIGEST_LENGTH,
744 2 * DIGEST_LENGTH,
745 request_auth + auth_nonce_odd_offset,
746 DIGEST_LENGTH + 1))
747 return TPM_LIB_ERROR;
748 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
749 request_auth + auth_auth_offset);
750
751 return TPM_SUCCESS;
752}
753
754/**
755 * Verify an authentication block in a response.
756 * Since this func updates the nonce_even in the session data it has to be
757 * called when receiving a succesfull AUTH response.
758 * This func can verify the first as well as the second auth block (for
759 * double authorized commands).
760 *
761 * @param command_code command code of the request
762 * @param response pointer to the request (w/ uninitialised auth data)
763 * @param handles_len length of the handles area in response
764 * @param auth_session pointer to the (valid) auth session to be used
765 * @param response_auth pointer to the auth block of the response to be verified
766 * @param auth authentication data (HMAC key)
767 */
768static uint32_t verify_response_auth(uint32_t command_code,
769 const void *response, size_t response_len0,
770 size_t handles_len,
771 struct session_data *auth_session,
772 const void *response_auth, const void *auth)
773{
774 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
775 uint8_t computed_auth[DIGEST_LENGTH];
776 sha1_context hash_ctx;
777 const size_t return_code_offset = 6;
778 const size_t auth_continue_offset = 20;
779 const size_t auth_auth_offset = 21;
780 uint8_t auth_continue;
781
782 if (!auth_session || !auth_session->valid)
783 return TPM_AUTHFAIL;
784 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
785 0, command_code))
786 return TPM_LIB_ERROR;
787 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
788 return TPM_LIB_ERROR;
789
790 sha1_starts(&hash_ctx);
791 sha1_update(&hash_ctx, response + return_code_offset, 4);
792 sha1_update(&hash_ctx, hmac_data, 4);
793 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
794 sha1_update(&hash_ctx,
795 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
796 response_len0 - TPM_RESPONSE_HEADER_LENGTH
797 - handles_len);
798 sha1_finish(&hash_ctx, hmac_data);
799
800 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
801 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
802 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
803 DIGEST_LENGTH,
804 response_auth,
805 DIGEST_LENGTH,
806 2 * DIGEST_LENGTH,
807 auth_session->nonce_odd,
808 DIGEST_LENGTH,
809 3 * DIGEST_LENGTH,
810 auth_continue))
811 return TPM_LIB_ERROR;
812
813 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
814 computed_auth);
815
816 if (memcmp(computed_auth, response_auth + auth_auth_offset,
817 DIGEST_LENGTH))
818 return TPM_AUTHFAIL;
819
820 return TPM_SUCCESS;
821}
822
823
824uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
825{
826 const uint8_t command[18] = {
827 0x00, 0xc1, /* TPM_TAG */
828 0x00, 0x00, 0x00, 0x00, /* parameter size */
829 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
830 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
831 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
832 };
833 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
834 uint8_t request[COMMAND_BUFFER_SIZE];
835
836 if (pack_byte_string(request, sizeof(request), "sd",
837 0, command, sizeof(command),
838 req_handle_offset, auth_handle))
839 return TPM_LIB_ERROR;
840 if (oiap_session.valid && oiap_session.handle == auth_handle)
841 oiap_session.valid = 0;
842
843 return tpm_sendrecv_command(request, NULL, NULL);
844}
845
846uint32_t tpm_end_oiap(void)
847{
848 uint32_t err = TPM_SUCCESS;
849 if (oiap_session.valid)
850 err = tpm_terminate_auth_session(oiap_session.handle);
851 return err;
852}
853
854uint32_t tpm_oiap(uint32_t *auth_handle)
855{
856 const uint8_t command[10] = {
857 0x00, 0xc1, /* TPM_TAG */
858 0x00, 0x00, 0x00, 0x0a, /* parameter size */
859 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
860 };
861 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
862 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
863 uint8_t response[COMMAND_BUFFER_SIZE];
864 size_t response_length = sizeof(response);
865 uint32_t err;
866
867 if (oiap_session.valid)
868 tpm_terminate_auth_session(oiap_session.handle);
869
870 err = tpm_sendrecv_command(command, response, &response_length);
871 if (err)
872 return err;
873 if (unpack_byte_string(response, response_length, "ds",
874 res_auth_handle_offset, &oiap_session.handle,
875 res_nonce_even_offset, &oiap_session.nonce_even,
876 (uint32_t)DIGEST_LENGTH))
877 return TPM_LIB_ERROR;
878 oiap_session.valid = 1;
879 if (auth_handle)
880 *auth_handle = oiap_session.handle;
881 return 0;
882}
883
884uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
885 const void *key, size_t key_length,
886 const void *parent_key_usage_auth,
887 uint32_t *key_handle)
888{
889 const uint8_t command[14] = {
890 0x00, 0xc2, /* TPM_TAG */
891 0x00, 0x00, 0x00, 0x00, /* parameter size */
892 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
893 0x00, 0x00, 0x00, 0x00, /* parent handle */
894 };
895 const size_t req_size_offset = 2;
896 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
897 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
898 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
899 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
900 + TPM_REQUEST_AUTH_LENGTH];
901 uint8_t response[COMMAND_BUFFER_SIZE];
902 size_t response_length = sizeof(response);
903 uint32_t err;
904
905 if (!oiap_session.valid) {
906 err = tpm_oiap(NULL);
907 if (err)
908 return err;
909 }
910 if (pack_byte_string(request, sizeof(request), "sdds",
911 0, command, sizeof(command),
912 req_size_offset,
913 sizeof(command) + key_length
914 + TPM_REQUEST_AUTH_LENGTH,
915 req_parent_handle_offset, parent_handle,
916 req_key_offset, key, key_length
917 ))
918 return TPM_LIB_ERROR;
919
920 err = create_request_auth(request, sizeof(command) + key_length, 4,
921 &oiap_session,
922 request + sizeof(command) + key_length,
923 parent_key_usage_auth);
924 if (err)
925 return err;
926 err = tpm_sendrecv_command(request, response, &response_length);
927 if (err) {
928 if (err == TPM_AUTHFAIL)
929 oiap_session.valid = 0;
930 return err;
931 }
932
933 err = verify_response_auth(0x00000041, response,
934 response_length - TPM_RESPONSE_AUTH_LENGTH,
935 4, &oiap_session,
936 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
937 parent_key_usage_auth);
938 if (err)
939 return err;
940
941 if (key_handle) {
942 if (unpack_byte_string(response, response_length, "d",
943 res_handle_offset, key_handle))
944 return TPM_LIB_ERROR;
945 }
946
947 return 0;
948}
949
950uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
951 void *pubkey, size_t *pubkey_len)
952{
953 const uint8_t command[14] = {
954 0x00, 0xc2, /* TPM_TAG */
955 0x00, 0x00, 0x00, 0x00, /* parameter size */
956 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
957 0x00, 0x00, 0x00, 0x00, /* key handle */
958 };
959 const size_t req_size_offset = 2;
960 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
961 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
962 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
963 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
964 + TPM_RESPONSE_AUTH_LENGTH];
965 size_t response_length = sizeof(response);
966 uint32_t err;
967
968 if (!oiap_session.valid) {
969 err = tpm_oiap(NULL);
970 if (err)
971 return err;
972 }
973 if (pack_byte_string(request, sizeof(request), "sdd",
974 0, command, sizeof(command),
975 req_size_offset,
976 (uint32_t)(sizeof(command)
977 + TPM_REQUEST_AUTH_LENGTH),
978 req_key_handle_offset, key_handle
979 ))
980 return TPM_LIB_ERROR;
981 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
982 request + sizeof(command), usage_auth);
983 if (err)
984 return err;
985 err = tpm_sendrecv_command(request, response, &response_length);
986 if (err) {
987 if (err == TPM_AUTHFAIL)
988 oiap_session.valid = 0;
989 return err;
990 }
991 err = verify_response_auth(0x00000021, response,
992 response_length - TPM_RESPONSE_AUTH_LENGTH,
993 0, &oiap_session,
994 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
995 usage_auth);
996 if (err)
997 return err;
998
999 if (pubkey) {
1000 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
1001 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1002 return TPM_LIB_ERROR;
1003 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1004 - TPM_RESPONSE_AUTH_LENGTH;
1005 memcpy(pubkey, response + res_pubkey_offset,
1006 response_length - TPM_RESPONSE_HEADER_LENGTH
1007 - TPM_RESPONSE_AUTH_LENGTH);
1008 }
1009
1010 return 0;
1011}
1012
mario.six@gdsys.cca5a7ea22017-03-20 10:28:28 +01001013#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1014uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1015 pubkey_digest[20], uint32_t *handle)
1016{
1017 uint16_t key_count;
1018 uint32_t key_handles[10];
1019 uint8_t buf[288];
1020 uint8_t *ptr;
1021 uint32_t err;
1022 uint8_t digest[20];
1023 size_t buf_len;
1024 unsigned int i;
1025
1026 /* fetch list of already loaded keys in the TPM */
1027 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1028 if (err)
1029 return -1;
1030 key_count = get_unaligned_be16(buf);
1031 ptr = buf + 2;
1032 for (i = 0; i < key_count; ++i, ptr += 4)
1033 key_handles[i] = get_unaligned_be32(ptr);
1034
1035 /* now search a(/ the) key which we can access with the given auth */
1036 for (i = 0; i < key_count; ++i) {
1037 buf_len = sizeof(buf);
1038 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1039 if (err && err != TPM_AUTHFAIL)
1040 return -1;
1041 if (err)
1042 continue;
1043 sha1_csum(buf, buf_len, digest);
1044 if (!memcmp(digest, pubkey_digest, 20)) {
1045 *handle = key_handles[i];
1046 return 0;
1047 }
1048 }
1049 return 1;
1050}
1051#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1052
Reinhard Pfau4fece432013-06-26 15:55:13 +02001053#endif /* CONFIG_TPM_AUTH_SESSIONS */
André Draszik2c6e5ff2017-10-03 16:55:52 +01001054
1055uint32_t tpm_get_random(void *data, uint32_t count)
1056{
1057 const uint8_t command[14] = {
1058 0x0, 0xc1, /* TPM_TAG */
1059 0x0, 0x0, 0x0, 0xe, /* parameter size */
1060 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
1061 };
1062 const size_t length_offset = 10;
1063 const size_t data_size_offset = 10;
1064 const size_t data_offset = 14;
1065 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1066 size_t response_length = sizeof(response);
1067 uint32_t data_size;
1068 uint8_t *out = data;
1069
1070 while (count > 0) {
1071 uint32_t this_bytes = min((size_t)count,
1072 sizeof (response) - data_offset);
1073 uint32_t err;
1074
1075 if (pack_byte_string(buf, sizeof(buf), "sd",
1076 0, command, sizeof(command),
1077 length_offset, this_bytes))
1078 return TPM_LIB_ERROR;
1079 err = tpm_sendrecv_command(buf, response, &response_length);
1080 if (err)
1081 return err;
1082 if (unpack_byte_string(response, response_length, "d",
1083 data_size_offset, &data_size))
1084 return TPM_LIB_ERROR;
1085 if (data_size > count)
1086 return TPM_LIB_ERROR;
1087 if (unpack_byte_string(response, response_length, "s",
1088 data_offset, out, data_size))
1089 return TPM_LIB_ERROR;
1090
1091 count -= data_size;
1092 out += data_size;
1093 }
1094
1095 return 0;
1096}