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