]> git.sur5r.net Git - u-boot/blob - lib/tpm.c
tpm: remove extra spaces between a function and its opening bracket
[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 uint32_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
845 uint32_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
853 uint32_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
883 uint32_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
949 uint32_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
1012 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1013 uint32_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
1052 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1053
1054 uint32_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 }