]> git.sur5r.net Git - u-boot/blob - lib/tpm.c
tools/file2include: avoid incorrect comments
[u-boot] / lib / tpm.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 The Chromium OS Authors.
4  * Coypright (c) 2013 Guntermann & Drunck GmbH
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <tpm.h>
10 #include <asm/unaligned.h>
11 #include <u-boot/sha1.h>
12
13 /* Internal error of TPM command library */
14 #define TPM_LIB_ERROR   ((uint32_t)~0u)
15
16 /* Useful constants */
17 enum {
18         COMMAND_BUFFER_SIZE             = 256,
19         TPM_REQUEST_HEADER_LENGTH       = 10,
20         TPM_RESPONSE_HEADER_LENGTH      = 10,
21         PCR_DIGEST_LENGTH               = 20,
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,
28 };
29
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
36 struct 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
43 static struct session_data oiap_session = {0, };
44
45 #endif /* CONFIG_TPM_AUTH_SESSIONS */
46
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  */
62 int 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");
94                         va_end(args);
95                         return -1;
96                 }
97
98                 if (offset + length > size) {
99                         va_end(args);
100                         return -1;
101                 }
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  */
136 int 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:
168                         va_end(args);
169                         debug("Couldn't recognize format string\n");
170                         return -1;
171                 }
172
173                 if (offset + length > size) {
174                         va_end(args);
175                         return -1;
176                 }
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  */
204 static 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  */
216 static 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  */
234 static uint32_t tpm_sendrecv_command(const void *command,
235                 void *response, size_t *size_ptr)
236 {
237         struct udevice *dev;
238         int err, ret;
239         uint8_t response_buffer[COMMAND_BUFFER_SIZE];
240         size_t response_length;
241
242         if (response) {
243                 response_length = *size_ptr;
244         } else {
245                 response = response_buffer;
246                 response_length = sizeof(response_buffer);
247         }
248
249         ret = uclass_first_device_err(UCLASS_TPM, &dev);
250         if (ret)
251                 return ret;
252         err = tpm_xfer(dev, command, tpm_command_size(command),
253                        response, &response_length);
254
255         if (err < 0)
256                 return TPM_LIB_ERROR;
257         if (size_ptr)
258                 *size_ptr = response_length;
259
260         return tpm_return_code(response);
261 }
262
263 int tpm_init(void)
264 {
265         int err;
266         struct udevice *dev;
267
268         err = uclass_first_device_err(UCLASS_TPM, &dev);
269         if (err)
270                 return err;
271         return tpm_open(dev);
272 }
273
274 uint32_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
290 uint32_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
298 uint32_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
306 uint32_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
349 uint32_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
383 uint32_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
413 uint32_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
444 uint32_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
472 uint32_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
488 uint32_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
519 uint32_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
528 uint32_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
537 uint32_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
546 uint32_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
562 uint32_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 }
601
602 uint32_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         };
612         const size_t data_size_offset = TPM_HEADER_SIZE;
613         const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
614         uint8_t response[COMMAND_BUFFER_SIZE];
615         size_t response_length = sizeof(response);
616         uint32_t err;
617         uint32_t data_size;
618
619         err = tpm_sendrecv_command(command, response, &response_length);
620         if (err)
621                 return err;
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;
630
631         return 0;
632 }
633
634 uint32_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
662 #ifdef CONFIG_TPM_FLUSH_RESOURCES
663 uint32_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
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  */
705 static 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  */
768 static uint32_t verify_response_auth(uint32_t command_code,
769         const void *response, size_t response_len0,
770         size_t handles_len,
771         struct session_data *auth_session,
772         const void *response_auth, const void *auth)
773 {
774         uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
775         uint8_t computed_auth[DIGEST_LENGTH];
776         sha1_context hash_ctx;
777         const size_t return_code_offset = 6;
778         const size_t auth_continue_offset = 20;
779         const size_t auth_auth_offset = 21;
780         uint8_t auth_continue;
781
782         if (!auth_session || !auth_session->valid)
783                 return TPM_AUTHFAIL;
784         if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
785                              0, command_code))
786                 return TPM_LIB_ERROR;
787         if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
788                 return TPM_LIB_ERROR;
789
790         sha1_starts(&hash_ctx);
791         sha1_update(&hash_ctx, response + return_code_offset, 4);
792         sha1_update(&hash_ctx, hmac_data, 4);
793         if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
794                 sha1_update(&hash_ctx,
795                             response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
796                             response_len0 - TPM_RESPONSE_HEADER_LENGTH
797                             - handles_len);
798         sha1_finish(&hash_ctx, hmac_data);
799
800         memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
801         auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
802         if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
803                              DIGEST_LENGTH,
804                              response_auth,
805                              DIGEST_LENGTH,
806                              2 * DIGEST_LENGTH,
807                              auth_session->nonce_odd,
808                              DIGEST_LENGTH,
809                              3 * DIGEST_LENGTH,
810                              auth_continue))
811                 return TPM_LIB_ERROR;
812
813         sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
814                   computed_auth);
815
816         if (memcmp(computed_auth, response_auth + auth_auth_offset,
817                    DIGEST_LENGTH))
818                 return TPM_AUTHFAIL;
819
820         return TPM_SUCCESS;
821 }
822
823
824 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
825 {
826         const uint8_t command[18] = {
827                 0x00, 0xc1,             /* TPM_TAG */
828                 0x00, 0x00, 0x00, 0x00, /* parameter size */
829                 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
830                 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
831                 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
832         };
833         const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
834         uint8_t request[COMMAND_BUFFER_SIZE];
835
836         if (pack_byte_string(request, sizeof(request), "sd",
837                              0, command, sizeof(command),
838                              req_handle_offset, auth_handle))
839                 return TPM_LIB_ERROR;
840         if (oiap_session.valid && oiap_session.handle == auth_handle)
841                 oiap_session.valid = 0;
842
843         return tpm_sendrecv_command(request, NULL, NULL);
844 }
845
846 uint32_t tpm_end_oiap(void)
847 {
848         uint32_t err = TPM_SUCCESS;
849         if (oiap_session.valid)
850                 err = tpm_terminate_auth_session(oiap_session.handle);
851         return err;
852 }
853
854 uint32_t tpm_oiap(uint32_t *auth_handle)
855 {
856         const uint8_t command[10] = {
857                 0x00, 0xc1,             /* TPM_TAG */
858                 0x00, 0x00, 0x00, 0x0a, /* parameter size */
859                 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
860         };
861         const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
862         const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
863         uint8_t response[COMMAND_BUFFER_SIZE];
864         size_t response_length = sizeof(response);
865         uint32_t err;
866
867         if (oiap_session.valid)
868                 tpm_terminate_auth_session(oiap_session.handle);
869
870         err = tpm_sendrecv_command(command, response, &response_length);
871         if (err)
872                 return err;
873         if (unpack_byte_string(response, response_length, "ds",
874                                res_auth_handle_offset, &oiap_session.handle,
875                                res_nonce_even_offset, &oiap_session.nonce_even,
876                                (uint32_t)DIGEST_LENGTH))
877                 return TPM_LIB_ERROR;
878         oiap_session.valid = 1;
879         if (auth_handle)
880                 *auth_handle = oiap_session.handle;
881         return 0;
882 }
883
884 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
885                 const void *key, size_t key_length,
886                 const void *parent_key_usage_auth,
887                 uint32_t *key_handle)
888 {
889         const uint8_t command[14] = {
890                 0x00, 0xc2,             /* TPM_TAG */
891                 0x00, 0x00, 0x00, 0x00, /* parameter size */
892                 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
893                 0x00, 0x00, 0x00, 0x00, /* parent handle */
894         };
895         const size_t req_size_offset = 2;
896         const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
897         const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
898         const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
899         uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
900                         + TPM_REQUEST_AUTH_LENGTH];
901         uint8_t response[COMMAND_BUFFER_SIZE];
902         size_t response_length = sizeof(response);
903         uint32_t err;
904
905         if (!oiap_session.valid) {
906                 err = tpm_oiap(NULL);
907                 if (err)
908                         return err;
909         }
910         if (pack_byte_string(request, sizeof(request), "sdds",
911                              0, command, sizeof(command),
912                              req_size_offset,
913                              sizeof(command) + key_length
914                              + TPM_REQUEST_AUTH_LENGTH,
915                              req_parent_handle_offset, parent_handle,
916                              req_key_offset, key, key_length
917                 ))
918                 return TPM_LIB_ERROR;
919
920         err = create_request_auth(request, sizeof(command) + key_length, 4,
921                                 &oiap_session,
922                                 request + sizeof(command) + key_length,
923                                 parent_key_usage_auth);
924         if (err)
925                 return err;
926         err = tpm_sendrecv_command(request, response, &response_length);
927         if (err) {
928                 if (err == TPM_AUTHFAIL)
929                         oiap_session.valid = 0;
930                 return err;
931         }
932
933         err = verify_response_auth(0x00000041, response,
934                         response_length - TPM_RESPONSE_AUTH_LENGTH,
935                         4, &oiap_session,
936                         response + response_length - TPM_RESPONSE_AUTH_LENGTH,
937                         parent_key_usage_auth);
938         if (err)
939                 return err;
940
941         if (key_handle) {
942                 if (unpack_byte_string(response, response_length, "d",
943                                        res_handle_offset, key_handle))
944                         return TPM_LIB_ERROR;
945         }
946
947         return 0;
948 }
949
950 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
951                         void *pubkey, size_t *pubkey_len)
952 {
953         const uint8_t command[14] = {
954                 0x00, 0xc2,             /* TPM_TAG */
955                 0x00, 0x00, 0x00, 0x00, /* parameter size */
956                 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
957                 0x00, 0x00, 0x00, 0x00, /* key handle */
958         };
959         const size_t req_size_offset = 2;
960         const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
961         const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
962         uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
963         uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
964                         + TPM_RESPONSE_AUTH_LENGTH];
965         size_t response_length = sizeof(response);
966         uint32_t err;
967
968         if (!oiap_session.valid) {
969                 err = tpm_oiap(NULL);
970                 if (err)
971                         return err;
972         }
973         if (pack_byte_string(request, sizeof(request), "sdd",
974                              0, command, sizeof(command),
975                              req_size_offset,
976                              (uint32_t)(sizeof(command)
977                              + TPM_REQUEST_AUTH_LENGTH),
978                              req_key_handle_offset, key_handle
979                 ))
980                 return TPM_LIB_ERROR;
981         err = create_request_auth(request, sizeof(command), 4, &oiap_session,
982                         request + sizeof(command), usage_auth);
983         if (err)
984                 return err;
985         err = tpm_sendrecv_command(request, response, &response_length);
986         if (err) {
987                 if (err == TPM_AUTHFAIL)
988                         oiap_session.valid = 0;
989                 return err;
990         }
991         err = verify_response_auth(0x00000021, response,
992                         response_length - TPM_RESPONSE_AUTH_LENGTH,
993                         0, &oiap_session,
994                         response + response_length - TPM_RESPONSE_AUTH_LENGTH,
995                         usage_auth);
996         if (err)
997                 return err;
998
999         if (pubkey) {
1000                 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
1001                         - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1002                         return TPM_LIB_ERROR;
1003                 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1004                         - TPM_RESPONSE_AUTH_LENGTH;
1005                 memcpy(pubkey, response + res_pubkey_offset,
1006                        response_length - TPM_RESPONSE_HEADER_LENGTH
1007                        - TPM_RESPONSE_AUTH_LENGTH);
1008         }
1009
1010         return 0;
1011 }
1012
1013 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1014 uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1015                            pubkey_digest[20], uint32_t *handle)
1016 {
1017         uint16_t key_count;
1018         uint32_t key_handles[10];
1019         uint8_t buf[288];
1020         uint8_t *ptr;
1021         uint32_t err;
1022         uint8_t digest[20];
1023         size_t buf_len;
1024         unsigned int i;
1025
1026         /* fetch list of already loaded keys in the TPM */
1027         err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1028         if (err)
1029                 return -1;
1030         key_count = get_unaligned_be16(buf);
1031         ptr = buf + 2;
1032         for (i = 0; i < key_count; ++i, ptr += 4)
1033                 key_handles[i] = get_unaligned_be32(ptr);
1034
1035         /* now search a(/ the) key which we can access with the given auth */
1036         for (i = 0; i < key_count; ++i) {
1037                 buf_len = sizeof(buf);
1038                 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1039                 if (err && err != TPM_AUTHFAIL)
1040                         return -1;
1041                 if (err)
1042                         continue;
1043                 sha1_csum(buf, buf_len, digest);
1044                 if (!memcmp(digest, pubkey_digest, 20)) {
1045                         *handle = key_handles[i];
1046                         return 0;
1047                 }
1048         }
1049         return 1;
1050 }
1051 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1052
1053 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1054
1055 uint32_t tpm_get_random(void *data, uint32_t count)
1056 {
1057         const uint8_t command[14] = {
1058                 0x0, 0xc1,              /* TPM_TAG */
1059                 0x0, 0x0, 0x0, 0xe,     /* parameter size */
1060                 0x0, 0x0, 0x0, 0x46,    /* TPM_COMMAND_CODE */
1061         };
1062         const size_t length_offset = 10;
1063         const size_t data_size_offset = 10;
1064         const size_t data_offset = 14;
1065         uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1066         size_t response_length = sizeof(response);
1067         uint32_t data_size;
1068         uint8_t *out = data;
1069
1070         while (count > 0) {
1071                 uint32_t this_bytes = min((size_t)count,
1072                                           sizeof (response) - data_offset);
1073                 uint32_t err;
1074
1075                 if (pack_byte_string(buf, sizeof(buf), "sd",
1076                                      0, command, sizeof(command),
1077                                      length_offset, this_bytes))
1078                         return TPM_LIB_ERROR;
1079                 err = tpm_sendrecv_command(buf, response, &response_length);
1080                 if (err)
1081                         return err;
1082                 if (unpack_byte_string(response, response_length, "d",
1083                                        data_size_offset, &data_size))
1084                         return TPM_LIB_ERROR;
1085                 if (data_size > count)
1086                         return TPM_LIB_ERROR;
1087                 if (unpack_byte_string(response, response_length, "s",
1088                                        data_offset, out, data_size))
1089                         return TPM_LIB_ERROR;
1090
1091                 count -= data_size;
1092                 out += data_size;
1093         }
1094
1095         return 0;
1096 }