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