]> Git Repo - J-u-boot.git/blame - lib/tpm.c
tpm: remove redundant blank line
[J-u-boot.git] / lib / tpm.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
8732b070
CC
2/*
3 * Copyright (c) 2013 The Chromium OS Authors.
be6c1529 4 * Coypright (c) 2013 Guntermann & Drunck GmbH
8732b070
CC
5 */
6
7#include <common.h>
c8a8c510 8#include <dm.h>
8732b070
CC
9#include <tpm.h>
10#include <asm/unaligned.h>
c8a8c510 11#include <u-boot/sha1.h>
8732b070
CC
12
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,
8732b070
CC
19 TPM_REQUEST_HEADER_LENGTH = 10,
20 TPM_RESPONSE_HEADER_LENGTH = 10,
21 PCR_DIGEST_LENGTH = 20,
be6c1529
RP
22 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,
8732b070
CC
28};
29
be6c1529
RP
30#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
8732b070
CC
47/**
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");
9d0c5fee 94 va_end(args);
8732b070
CC
95 return -1;
96 }
97
36d35345
HS
98 if (offset + length > size) {
99 va_end(args);
8732b070 100 return -1;
36d35345 101 }
8732b070
CC
102
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:
36d35345 168 va_end(args);
8732b070
CC
169 debug("Couldn't recognize format string\n");
170 return -1;
171 }
172
9d0c5fee
AD
173 if (offset + length > size) {
174 va_end(args);
8732b070 175 return -1;
9d0c5fee 176 }
8732b070
CC
177
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{
c2b0f600 237 struct udevice *dev;
667d6856 238 int err, ret;
8732b070
CC
239 uint8_t response_buffer[COMMAND_BUFFER_SIZE];
240 size_t response_length;
8732b070
CC
241
242 if (response) {
243 response_length = *size_ptr;
244 } else {
245 response = response_buffer;
246 response_length = sizeof(response_buffer);
247 }
c8a8c510 248
3f603cbb 249 ret = uclass_first_device_err(UCLASS_TPM, &dev);
c8a8c510
SG
250 if (ret)
251 return ret;
252 err = tpm_xfer(dev, command, tpm_command_size(command),
253 response, &response_length);
c2b0f600 254
c8a8c510 255 if (err < 0)
8732b070 256 return TPM_LIB_ERROR;
be6c1529 257 if (size_ptr)
8732b070
CC
258 *size_ptr = response_length;
259
260 return tpm_return_code(response);
261}
262
c8a8c510 263int tpm_init(void)
8732b070 264{
c8a8c510 265 int err;
c8a8c510
SG
266 struct udevice *dev;
267
3f603cbb
SG
268 err = uclass_first_device_err(UCLASS_TPM, &dev);
269 if (err)
c8a8c510
SG
270 return err;
271 return tpm_open(dev);
8732b070
CC
272}
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}
be6c1529 601
2132f971
SG
602uint32_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 };
e8155dfe
AD
612 const size_t data_size_offset = TPM_HEADER_SIZE;
613 const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
2132f971
SG
614 uint8_t response[COMMAND_BUFFER_SIZE];
615 size_t response_length = sizeof(response);
616 uint32_t err;
e8155dfe 617 uint32_t data_size;
2132f971
SG
618
619 err = tpm_sendrecv_command(command, response, &response_length);
620 if (err)
621 return err;
e8155dfe
AD
622 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;
2132f971
SG
630
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
7690be35
MS
662#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
be6c1529
RP
691#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
be6c1529
RP
823uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
824{
825 const uint8_t command[18] = {
826 0x00, 0xc1, /* TPM_TAG */
827 0x00, 0x00, 0x00, 0x00, /* parameter size */
828 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
829 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
830 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
831 };
832 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
833 uint8_t request[COMMAND_BUFFER_SIZE];
834
835 if (pack_byte_string(request, sizeof(request), "sd",
836 0, command, sizeof(command),
837 req_handle_offset, auth_handle))
838 return TPM_LIB_ERROR;
839 if (oiap_session.valid && oiap_session.handle == auth_handle)
840 oiap_session.valid = 0;
841
842 return tpm_sendrecv_command(request, NULL, NULL);
843}
844
845uint32_t tpm_end_oiap(void)
846{
847 uint32_t err = TPM_SUCCESS;
848 if (oiap_session.valid)
849 err = tpm_terminate_auth_session(oiap_session.handle);
850 return err;
851}
852
853uint32_t tpm_oiap(uint32_t *auth_handle)
854{
855 const uint8_t command[10] = {
856 0x00, 0xc1, /* TPM_TAG */
857 0x00, 0x00, 0x00, 0x0a, /* parameter size */
858 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
859 };
860 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
861 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
862 uint8_t response[COMMAND_BUFFER_SIZE];
863 size_t response_length = sizeof(response);
864 uint32_t err;
865
866 if (oiap_session.valid)
867 tpm_terminate_auth_session(oiap_session.handle);
868
869 err = tpm_sendrecv_command(command, response, &response_length);
870 if (err)
871 return err;
872 if (unpack_byte_string(response, response_length, "ds",
873 res_auth_handle_offset, &oiap_session.handle,
874 res_nonce_even_offset, &oiap_session.nonce_even,
875 (uint32_t)DIGEST_LENGTH))
876 return TPM_LIB_ERROR;
877 oiap_session.valid = 1;
878 if (auth_handle)
879 *auth_handle = oiap_session.handle;
880 return 0;
881}
882
883uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
884 const void *key, size_t key_length,
885 const void *parent_key_usage_auth,
886 uint32_t *key_handle)
887{
888 const uint8_t command[14] = {
889 0x00, 0xc2, /* TPM_TAG */
890 0x00, 0x00, 0x00, 0x00, /* parameter size */
891 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
892 0x00, 0x00, 0x00, 0x00, /* parent handle */
893 };
894 const size_t req_size_offset = 2;
895 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
896 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
897 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
898 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
899 + TPM_REQUEST_AUTH_LENGTH];
900 uint8_t response[COMMAND_BUFFER_SIZE];
901 size_t response_length = sizeof(response);
902 uint32_t err;
903
904 if (!oiap_session.valid) {
905 err = tpm_oiap(NULL);
906 if (err)
907 return err;
908 }
909 if (pack_byte_string(request, sizeof(request), "sdds",
910 0, command, sizeof(command),
911 req_size_offset,
912 sizeof(command) + key_length
913 + TPM_REQUEST_AUTH_LENGTH,
914 req_parent_handle_offset, parent_handle,
915 req_key_offset, key, key_length
916 ))
917 return TPM_LIB_ERROR;
918
919 err = create_request_auth(request, sizeof(command) + key_length, 4,
920 &oiap_session,
921 request + sizeof(command) + key_length,
922 parent_key_usage_auth);
923 if (err)
924 return err;
925 err = tpm_sendrecv_command(request, response, &response_length);
926 if (err) {
927 if (err == TPM_AUTHFAIL)
928 oiap_session.valid = 0;
929 return err;
930 }
931
932 err = verify_response_auth(0x00000041, response,
933 response_length - TPM_RESPONSE_AUTH_LENGTH,
934 4, &oiap_session,
935 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
936 parent_key_usage_auth);
937 if (err)
938 return err;
939
940 if (key_handle) {
941 if (unpack_byte_string(response, response_length, "d",
942 res_handle_offset, key_handle))
943 return TPM_LIB_ERROR;
944 }
945
946 return 0;
947}
948
949uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
950 void *pubkey, size_t *pubkey_len)
951{
952 const uint8_t command[14] = {
953 0x00, 0xc2, /* TPM_TAG */
954 0x00, 0x00, 0x00, 0x00, /* parameter size */
955 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
956 0x00, 0x00, 0x00, 0x00, /* key handle */
957 };
958 const size_t req_size_offset = 2;
959 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
960 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
961 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
962 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
963 + TPM_RESPONSE_AUTH_LENGTH];
964 size_t response_length = sizeof(response);
965 uint32_t err;
966
967 if (!oiap_session.valid) {
968 err = tpm_oiap(NULL);
969 if (err)
970 return err;
971 }
972 if (pack_byte_string(request, sizeof(request), "sdd",
973 0, command, sizeof(command),
974 req_size_offset,
975 (uint32_t)(sizeof(command)
976 + TPM_REQUEST_AUTH_LENGTH),
977 req_key_handle_offset, key_handle
978 ))
979 return TPM_LIB_ERROR;
980 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
981 request + sizeof(command), usage_auth);
982 if (err)
983 return err;
984 err = tpm_sendrecv_command(request, response, &response_length);
985 if (err) {
986 if (err == TPM_AUTHFAIL)
987 oiap_session.valid = 0;
988 return err;
989 }
990 err = verify_response_auth(0x00000021, response,
991 response_length - TPM_RESPONSE_AUTH_LENGTH,
992 0, &oiap_session,
993 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
994 usage_auth);
995 if (err)
996 return err;
997
998 if (pubkey) {
999 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
1000 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1001 return TPM_LIB_ERROR;
1002 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1003 - TPM_RESPONSE_AUTH_LENGTH;
1004 memcpy(pubkey, response + res_pubkey_offset,
1005 response_length - TPM_RESPONSE_HEADER_LENGTH
1006 - TPM_RESPONSE_AUTH_LENGTH);
1007 }
1008
1009 return 0;
1010}
1011
0f4b2ba1 1012#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1013uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1014 pubkey_digest[20], uint32_t *handle)
1015{
1016 uint16_t key_count;
1017 uint32_t key_handles[10];
1018 uint8_t buf[288];
1019 uint8_t *ptr;
1020 uint32_t err;
1021 uint8_t digest[20];
1022 size_t buf_len;
1023 unsigned int i;
1024
1025 /* fetch list of already loaded keys in the TPM */
1026 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1027 if (err)
1028 return -1;
1029 key_count = get_unaligned_be16(buf);
1030 ptr = buf + 2;
1031 for (i = 0; i < key_count; ++i, ptr += 4)
1032 key_handles[i] = get_unaligned_be32(ptr);
1033
1034 /* now search a(/ the) key which we can access with the given auth */
1035 for (i = 0; i < key_count; ++i) {
1036 buf_len = sizeof(buf);
1037 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1038 if (err && err != TPM_AUTHFAIL)
1039 return -1;
1040 if (err)
1041 continue;
1042 sha1_csum(buf, buf_len, digest);
1043 if (!memcmp(digest, pubkey_digest, 20)) {
1044 *handle = key_handles[i];
1045 return 0;
1046 }
1047 }
1048 return 1;
1049}
1050#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1051
be6c1529 1052#endif /* CONFIG_TPM_AUTH_SESSIONS */
3c605027
AD
1053
1054uint32_t tpm_get_random(void *data, uint32_t count)
1055{
1056 const uint8_t command[14] = {
1057 0x0, 0xc1, /* TPM_TAG */
1058 0x0, 0x0, 0x0, 0xe, /* parameter size */
1059 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
1060 };
1061 const size_t length_offset = 10;
1062 const size_t data_size_offset = 10;
1063 const size_t data_offset = 14;
1064 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1065 size_t response_length = sizeof(response);
1066 uint32_t data_size;
1067 uint8_t *out = data;
1068
1069 while (count > 0) {
1070 uint32_t this_bytes = min((size_t)count,
1071 sizeof (response) - data_offset);
1072 uint32_t err;
1073
1074 if (pack_byte_string(buf, sizeof(buf), "sd",
1075 0, command, sizeof(command),
1076 length_offset, this_bytes))
1077 return TPM_LIB_ERROR;
1078 err = tpm_sendrecv_command(buf, response, &response_length);
1079 if (err)
1080 return err;
1081 if (unpack_byte_string(response, response_length, "d",
1082 data_size_offset, &data_size))
1083 return TPM_LIB_ERROR;
1084 if (data_size > count)
1085 return TPM_LIB_ERROR;
1086 if (unpack_byte_string(response, response_length, "s",
1087 data_offset, out, data_size))
1088 return TPM_LIB_ERROR;
1089
1090 count -= data_size;
1091 out += data_size;
1092 }
1093
1094 return 0;
1095}
This page took 0.455298 seconds and 4 git commands to generate.