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