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