Merge tag 'ti-v2021.01-next' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti...
[platform/kernel/u-boot.git] / lib / tpm-v1.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 #define LOG_CATEGORY UCLASS_TPM
8
9 #include <common.h>
10 #include <dm.h>
11 #include <log.h>
12 #include <asm/unaligned.h>
13 #include <u-boot/sha1.h>
14 #include <tpm-common.h>
15 #include <tpm-v1.h>
16 #include "tpm-utils.h"
17
18 #ifdef CONFIG_TPM_AUTH_SESSIONS
19
20 #ifndef CONFIG_SHA1
21 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
22 #endif /* !CONFIG_SHA1 */
23
24 struct session_data {
25         int             valid;
26         u32     handle;
27         u8              nonce_even[DIGEST_LENGTH];
28         u8              nonce_odd[DIGEST_LENGTH];
29 };
30
31 static struct session_data oiap_session = {0, };
32
33 #endif /* CONFIG_TPM_AUTH_SESSIONS */
34
35 u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
36 {
37         const u8 command[12] = {
38                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
39         };
40         const size_t mode_offset = 10;
41         u8 buf[COMMAND_BUFFER_SIZE];
42
43         if (pack_byte_string(buf, sizeof(buf), "sw",
44                              0, command, sizeof(command),
45                              mode_offset, mode))
46                 return TPM_LIB_ERROR;
47
48         return tpm_sendrecv_command(dev, buf, NULL, NULL);
49 }
50
51 u32 tpm_resume(struct udevice *dev)
52 {
53         return tpm_startup(dev, TPM_ST_STATE);
54 }
55
56 u32 tpm_self_test_full(struct udevice *dev)
57 {
58         const u8 command[10] = {
59                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
60         };
61         return tpm_sendrecv_command(dev, command, NULL, NULL);
62 }
63
64 u32 tpm_continue_self_test(struct udevice *dev)
65 {
66         const u8 command[10] = {
67                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
68         };
69         return tpm_sendrecv_command(dev, command, NULL, NULL);
70 }
71
72 u32 tpm_clear_and_reenable(struct udevice *dev)
73 {
74         u32 ret;
75
76         log_info("TPM: Clear and re-enable\n");
77         ret = tpm_force_clear(dev);
78         if (ret != TPM_SUCCESS) {
79                 log_err("Can't initiate a force clear\n");
80                 return ret;
81         }
82
83         if (tpm_get_version(dev) == TPM_V1) {
84                 ret = tpm_physical_enable(dev);
85                 if (ret != TPM_SUCCESS) {
86                         log_err("TPM: Can't set enabled state\n");
87                         return ret;
88                 }
89
90                 ret = tpm_physical_set_deactivated(dev, 0);
91                 if (ret != TPM_SUCCESS) {
92                         log_err("TPM: Can't set deactivated state\n");
93                         return ret;
94                 }
95         }
96
97         return TPM_SUCCESS;
98 }
99
100 u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
101 {
102         const u8 command[101] = {
103                 0x0, 0xc1,              /* TPM_TAG */
104                 0x0, 0x0, 0x0, 0x65,    /* parameter size */
105                 0x0, 0x0, 0x0, 0xcc,    /* TPM_COMMAND_CODE */
106                 /* TPM_NV_DATA_PUBLIC->... */
107                 0x0, 0x18,              /* ...->TPM_STRUCTURE_TAG */
108                 0, 0, 0, 0,             /* ...->TPM_NV_INDEX */
109                 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
110                 0x0, 0x3,
111                 0, 0, 0,
112                 0x1f,
113                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114                 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
115                 0x0, 0x3,
116                 0, 0, 0,
117                 0x1f,
118                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119                 /* TPM_NV_ATTRIBUTES->... */
120                 0x0, 0x17,              /* ...->TPM_STRUCTURE_TAG */
121                 0, 0, 0, 0,             /* ...->attributes */
122                 /* End of TPM_NV_ATTRIBUTES */
123                 0,                      /* bReadSTClear */
124                 0,                      /* bWriteSTClear */
125                 0,                      /* bWriteDefine */
126                 0, 0, 0, 0,             /* size */
127         };
128         const size_t index_offset = 12;
129         const size_t perm_offset = 70;
130         const size_t size_offset = 77;
131         u8 buf[COMMAND_BUFFER_SIZE];
132
133         if (pack_byte_string(buf, sizeof(buf), "sddd",
134                              0, command, sizeof(command),
135                              index_offset, index,
136                              perm_offset, perm,
137                              size_offset, size))
138                 return TPM_LIB_ERROR;
139
140         return tpm_sendrecv_command(dev, buf, NULL, NULL);
141 }
142
143 u32 tpm_nv_set_locked(struct udevice *dev)
144 {
145         return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
146 }
147
148 u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
149 {
150         const u8 command[22] = {
151                 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
152         };
153         const size_t index_offset = 10;
154         const size_t length_offset = 18;
155         const size_t data_size_offset = 10;
156         const size_t data_offset = 14;
157         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
158         size_t response_length = sizeof(response);
159         u32 data_size;
160         u32 err;
161
162         if (pack_byte_string(buf, sizeof(buf), "sdd",
163                              0, command, sizeof(command),
164                              index_offset, index,
165                              length_offset, count))
166                 return TPM_LIB_ERROR;
167         err = tpm_sendrecv_command(dev, buf, response, &response_length);
168         if (err)
169                 return err;
170         if (unpack_byte_string(response, response_length, "d",
171                                data_size_offset, &data_size))
172                 return TPM_LIB_ERROR;
173         if (data_size > count)
174                 return TPM_LIB_ERROR;
175         if (unpack_byte_string(response, response_length, "s",
176                                data_offset, data, data_size))
177                 return TPM_LIB_ERROR;
178
179         return 0;
180 }
181
182 u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
183                        u32 length)
184 {
185         const u8 command[256] = {
186                 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
187         };
188         const size_t command_size_offset = 2;
189         const size_t index_offset = 10;
190         const size_t length_offset = 18;
191         const size_t data_offset = 22;
192         const size_t write_info_size = 12;
193         const u32 total_length =
194                 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
195         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
196         size_t response_length = sizeof(response);
197         u32 err;
198
199         if (pack_byte_string(buf, sizeof(buf), "sddds",
200                              0, command, sizeof(command),
201                              command_size_offset, total_length,
202                              index_offset, index,
203                              length_offset, length,
204                              data_offset, data, length))
205                 return TPM_LIB_ERROR;
206         err = tpm_sendrecv_command(dev, buf, response, &response_length);
207         if (err)
208                 return err;
209
210         return 0;
211 }
212
213 uint32_t tpm_set_global_lock(struct udevice *dev)
214 {
215         return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
216 }
217
218 u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
219                void *out_digest)
220 {
221         const u8 command[34] = {
222                 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
223         };
224         const size_t index_offset = 10;
225         const size_t in_digest_offset = 14;
226         const size_t out_digest_offset = 10;
227         u8 buf[COMMAND_BUFFER_SIZE];
228         u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
229         size_t response_length = sizeof(response);
230         u32 err;
231
232         if (pack_byte_string(buf, sizeof(buf), "sds",
233                              0, command, sizeof(command),
234                              index_offset, index,
235                              in_digest_offset, in_digest,
236                              PCR_DIGEST_LENGTH))
237                 return TPM_LIB_ERROR;
238         err = tpm_sendrecv_command(dev, buf, response, &response_length);
239         if (err)
240                 return err;
241
242         if (unpack_byte_string(response, response_length, "s",
243                                out_digest_offset, out_digest,
244                                PCR_DIGEST_LENGTH))
245                 return TPM_LIB_ERROR;
246
247         return 0;
248 }
249
250 u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
251 {
252         const u8 command[14] = {
253                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
254         };
255         const size_t index_offset = 10;
256         const size_t out_digest_offset = 10;
257         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
258         size_t response_length = sizeof(response);
259         u32 err;
260
261         if (count < PCR_DIGEST_LENGTH)
262                 return TPM_LIB_ERROR;
263
264         if (pack_byte_string(buf, sizeof(buf), "sd",
265                              0, command, sizeof(command),
266                              index_offset, index))
267                 return TPM_LIB_ERROR;
268         err = tpm_sendrecv_command(dev, buf, response, &response_length);
269         if (err)
270                 return err;
271         if (unpack_byte_string(response, response_length, "s",
272                                out_digest_offset, data, PCR_DIGEST_LENGTH))
273                 return TPM_LIB_ERROR;
274
275         return 0;
276 }
277
278 u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
279 {
280         const u8 command[12] = {
281                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
282         };
283         const size_t presence_offset = 10;
284         u8 buf[COMMAND_BUFFER_SIZE];
285
286         if (pack_byte_string(buf, sizeof(buf), "sw",
287                              0, command, sizeof(command),
288                              presence_offset, presence))
289                 return TPM_LIB_ERROR;
290
291         return tpm_sendrecv_command(dev, buf, NULL, NULL);
292 }
293
294 u32 tpm_finalise_physical_presence(struct udevice *dev)
295 {
296         const u8 command[12] = {
297                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
298         };
299
300         return tpm_sendrecv_command(dev, command, NULL, NULL);
301 }
302
303 u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
304 {
305         const u8 command[30] = {
306                 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
307         };
308         const size_t response_size_offset = 2;
309         const size_t data_offset = 10;
310         const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
311         u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
312         size_t response_length = sizeof(response);
313         u32 data_size;
314         u32 err;
315
316         err = tpm_sendrecv_command(dev, command, response, &response_length);
317         if (err)
318                 return err;
319         if (unpack_byte_string(response, response_length, "d",
320                                response_size_offset, &data_size))
321                 return TPM_LIB_ERROR;
322         if (data_size < header_and_checksum_size)
323                 return TPM_LIB_ERROR;
324         data_size -= header_and_checksum_size;
325         if (data_size > count)
326                 return TPM_LIB_ERROR;
327         if (unpack_byte_string(response, response_length, "s",
328                                data_offset, data, data_size))
329                 return TPM_LIB_ERROR;
330
331         return 0;
332 }
333
334 u32 tpm_force_clear(struct udevice *dev)
335 {
336         const u8 command[10] = {
337                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
338         };
339
340         return tpm_sendrecv_command(dev, command, NULL, NULL);
341 }
342
343 u32 tpm_physical_enable(struct udevice *dev)
344 {
345         const u8 command[10] = {
346                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
347         };
348
349         return tpm_sendrecv_command(dev, command, NULL, NULL);
350 }
351
352 u32 tpm_physical_disable(struct udevice *dev)
353 {
354         const u8 command[10] = {
355                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
356         };
357
358         return tpm_sendrecv_command(dev, command, NULL, NULL);
359 }
360
361 u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
362 {
363         const u8 command[11] = {
364                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
365         };
366         const size_t state_offset = 10;
367         u8 buf[COMMAND_BUFFER_SIZE];
368
369         if (pack_byte_string(buf, sizeof(buf), "sb",
370                              0, command, sizeof(command),
371                              state_offset, state))
372                 return TPM_LIB_ERROR;
373
374         return tpm_sendrecv_command(dev, buf, NULL, NULL);
375 }
376
377 u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
378                        void *cap, size_t count)
379 {
380         const u8 command[22] = {
381                 0x0, 0xc1,              /* TPM_TAG */
382                 0x0, 0x0, 0x0, 0x16,    /* parameter size */
383                 0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
384                 0x0, 0x0, 0x0, 0x0,     /* TPM_CAPABILITY_AREA */
385                 0x0, 0x0, 0x0, 0x4,     /* subcap size */
386                 0x0, 0x0, 0x0, 0x0,     /* subcap value */
387         };
388         const size_t cap_area_offset = 10;
389         const size_t sub_cap_offset = 18;
390         const size_t cap_offset = 14;
391         const size_t cap_size_offset = 10;
392         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
393         size_t response_length = sizeof(response);
394         u32 cap_size;
395         u32 err;
396
397         if (pack_byte_string(buf, sizeof(buf), "sdd",
398                              0, command, sizeof(command),
399                              cap_area_offset, cap_area,
400                              sub_cap_offset, sub_cap))
401                 return TPM_LIB_ERROR;
402         err = tpm_sendrecv_command(dev, buf, response, &response_length);
403         if (err)
404                 return err;
405         if (unpack_byte_string(response, response_length, "d",
406                                cap_size_offset, &cap_size))
407                 return TPM_LIB_ERROR;
408         if (cap_size > response_length || cap_size > count)
409                 return TPM_LIB_ERROR;
410         if (unpack_byte_string(response, response_length, "s",
411                                cap_offset, cap, cap_size))
412                 return TPM_LIB_ERROR;
413
414         return 0;
415 }
416
417 u32 tpm_get_permanent_flags(struct udevice *dev,
418                             struct tpm_permanent_flags *pflags)
419 {
420         const u8 command[22] = {
421                 0x0, 0xc1,              /* TPM_TAG */
422                 0x0, 0x0, 0x0, 0x16,    /* parameter size */
423                 0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
424                 0x0, 0x0, 0x0, 0x4,     /* TPM_CAP_FLAG_PERM */
425                 0x0, 0x0, 0x0, 0x4,     /* subcap size */
426                 0x0, 0x0, 0x1, 0x8,     /* subcap value */
427         };
428         const size_t data_size_offset = TPM_HEADER_SIZE;
429         const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
430         u8 response[COMMAND_BUFFER_SIZE];
431         size_t response_length = sizeof(response);
432         u32 err;
433         u32 data_size;
434
435         err = tpm_sendrecv_command(dev, command, response, &response_length);
436         if (err)
437                 return err;
438         if (unpack_byte_string(response, response_length, "d",
439                                data_size_offset, &data_size)) {
440                 log_err("Cannot unpack data size\n");
441                 return TPM_LIB_ERROR;
442         }
443         if (data_size < sizeof(*pflags)) {
444                 log_err("Data size too small\n");
445                 return TPM_LIB_ERROR;
446         }
447         if (unpack_byte_string(response, response_length, "s",
448                                data_offset, pflags, sizeof(*pflags))) {
449                 log_err("Cannot unpack pflags\n");
450                 return TPM_LIB_ERROR;
451         }
452
453         return 0;
454 }
455
456 u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
457 {
458         const u8 command[22] = {
459                 0x0, 0xc1,              /* TPM_TAG */
460                 0x0, 0x0, 0x0, 0x16,    /* parameter size */
461                 0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
462                 0x0, 0x0, 0x0, 0x11,
463                 0x0, 0x0, 0x0, 0x4,
464         };
465         const size_t index_offset = 18;
466         const size_t perm_offset = 60;
467         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
468         size_t response_length = sizeof(response);
469         u32 err;
470
471         if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
472                              index_offset, index))
473                 return TPM_LIB_ERROR;
474         err = tpm_sendrecv_command(dev, buf, response, &response_length);
475         if (err)
476                 return err;
477         if (unpack_byte_string(response, response_length, "d",
478                                perm_offset, perm))
479                 return TPM_LIB_ERROR;
480
481         return 0;
482 }
483
484 #ifdef CONFIG_TPM_FLUSH_RESOURCES
485 u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
486 {
487         const u8 command[18] = {
488                 0x00, 0xc1,             /* TPM_TAG */
489                 0x00, 0x00, 0x00, 0x12, /* parameter size */
490                 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
491                 0x00, 0x00, 0x00, 0x00, /* key handle */
492                 0x00, 0x00, 0x00, 0x00, /* resource type */
493         };
494         const size_t key_handle_offset = 10;
495         const size_t resource_type_offset = 14;
496         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
497         size_t response_length = sizeof(response);
498         u32 err;
499
500         if (pack_byte_string(buf, sizeof(buf), "sdd",
501                              0, command, sizeof(command),
502                              key_handle_offset, key_handle,
503                              resource_type_offset, resource_type))
504                 return TPM_LIB_ERROR;
505
506         err = tpm_sendrecv_command(dev, buf, response, &response_length);
507         if (err)
508                 return err;
509         return 0;
510 }
511 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
512
513 #ifdef CONFIG_TPM_AUTH_SESSIONS
514
515 /**
516  * Fill an authentication block in a request.
517  * This func can create the first as well as the second auth block (for
518  * double authorized commands).
519  *
520  * @param request       pointer to the request (w/ uninitialised auth data)
521  * @param request_len0  length of the request without auth data
522  * @param handles_len   length of the handles area in request
523  * @param auth_session  pointer to the (valid) auth session to be used
524  * @param request_auth  pointer to the auth block of the request to be filled
525  * @param auth          authentication data (HMAC key)
526  */
527 static u32 create_request_auth(const void *request, size_t request_len0,
528                                size_t handles_len,
529                                struct session_data *auth_session,
530                                void *request_auth, const void *auth)
531 {
532         u8 hmac_data[DIGEST_LENGTH * 3 + 1];
533         sha1_context hash_ctx;
534         const size_t command_code_offset = 6;
535         const size_t auth_nonce_odd_offset = 4;
536         const size_t auth_continue_offset = 24;
537         const size_t auth_auth_offset = 25;
538
539         if (!auth_session || !auth_session->valid)
540                 return TPM_LIB_ERROR;
541
542         sha1_starts(&hash_ctx);
543         sha1_update(&hash_ctx, request + command_code_offset, 4);
544         if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
545                 sha1_update(&hash_ctx,
546                             request + TPM_REQUEST_HEADER_LENGTH + handles_len,
547                             request_len0 - TPM_REQUEST_HEADER_LENGTH
548                             - handles_len);
549         sha1_finish(&hash_ctx, hmac_data);
550
551         sha1_starts(&hash_ctx);
552         sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
553         sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
554         sha1_finish(&hash_ctx, auth_session->nonce_odd);
555
556         if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
557                              0, auth_session->handle,
558                              auth_nonce_odd_offset, auth_session->nonce_odd,
559                              DIGEST_LENGTH,
560                              auth_continue_offset, 1))
561                 return TPM_LIB_ERROR;
562         if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
563                              DIGEST_LENGTH,
564                              auth_session->nonce_even,
565                              DIGEST_LENGTH,
566                              2 * DIGEST_LENGTH,
567                              request_auth + auth_nonce_odd_offset,
568                              DIGEST_LENGTH + 1))
569                 return TPM_LIB_ERROR;
570         sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
571                   request_auth + auth_auth_offset);
572
573         return TPM_SUCCESS;
574 }
575
576 /**
577  * Verify an authentication block in a response.
578  * Since this func updates the nonce_even in the session data it has to be
579  * called when receiving a succesfull AUTH response.
580  * This func can verify the first as well as the second auth block (for
581  * double authorized commands).
582  *
583  * @param command_code  command code of the request
584  * @param response      pointer to the request (w/ uninitialised auth data)
585  * @param handles_len   length of the handles area in response
586  * @param auth_session  pointer to the (valid) auth session to be used
587  * @param response_auth pointer to the auth block of the response to be verified
588  * @param auth          authentication data (HMAC key)
589  */
590 static u32 verify_response_auth(u32 command_code, const void *response,
591                                 size_t response_len0, size_t handles_len,
592                                 struct session_data *auth_session,
593                                 const void *response_auth, const void *auth)
594 {
595         u8 hmac_data[DIGEST_LENGTH * 3 + 1];
596         u8 computed_auth[DIGEST_LENGTH];
597         sha1_context hash_ctx;
598         const size_t return_code_offset = 6;
599         const size_t auth_continue_offset = 20;
600         const size_t auth_auth_offset = 21;
601         u8 auth_continue;
602
603         if (!auth_session || !auth_session->valid)
604                 return TPM_AUTHFAIL;
605         if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
606                              0, command_code))
607                 return TPM_LIB_ERROR;
608         if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
609                 return TPM_LIB_ERROR;
610
611         sha1_starts(&hash_ctx);
612         sha1_update(&hash_ctx, response + return_code_offset, 4);
613         sha1_update(&hash_ctx, hmac_data, 4);
614         if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
615                 sha1_update(&hash_ctx,
616                             response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
617                             response_len0 - TPM_RESPONSE_HEADER_LENGTH
618                             - handles_len);
619         sha1_finish(&hash_ctx, hmac_data);
620
621         memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
622         auth_continue = ((u8 *)response_auth)[auth_continue_offset];
623         if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
624                              DIGEST_LENGTH,
625                              response_auth,
626                              DIGEST_LENGTH,
627                              2 * DIGEST_LENGTH,
628                              auth_session->nonce_odd,
629                              DIGEST_LENGTH,
630                              3 * DIGEST_LENGTH,
631                              auth_continue))
632                 return TPM_LIB_ERROR;
633
634         sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
635                   computed_auth);
636
637         if (memcmp(computed_auth, response_auth + auth_auth_offset,
638                    DIGEST_LENGTH))
639                 return TPM_AUTHFAIL;
640
641         return TPM_SUCCESS;
642 }
643
644 u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
645 {
646         const u8 command[18] = {
647                 0x00, 0xc1,             /* TPM_TAG */
648                 0x00, 0x00, 0x00, 0x00, /* parameter size */
649                 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
650                 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
651                 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
652         };
653         const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
654         u8 request[COMMAND_BUFFER_SIZE];
655
656         if (pack_byte_string(request, sizeof(request), "sd",
657                              0, command, sizeof(command),
658                              req_handle_offset, auth_handle))
659                 return TPM_LIB_ERROR;
660         if (oiap_session.valid && oiap_session.handle == auth_handle)
661                 oiap_session.valid = 0;
662
663         return tpm_sendrecv_command(dev, request, NULL, NULL);
664 }
665
666 u32 tpm_end_oiap(struct udevice *dev)
667 {
668         u32 err = TPM_SUCCESS;
669
670         if (oiap_session.valid)
671                 err = tpm_terminate_auth_session(dev, oiap_session.handle);
672         return err;
673 }
674
675 u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
676 {
677         const u8 command[10] = {
678                 0x00, 0xc1,             /* TPM_TAG */
679                 0x00, 0x00, 0x00, 0x0a, /* parameter size */
680                 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
681         };
682         const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
683         const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
684         u8 response[COMMAND_BUFFER_SIZE];
685         size_t response_length = sizeof(response);
686         u32 err;
687
688         if (oiap_session.valid)
689                 tpm_terminate_auth_session(dev, oiap_session.handle);
690
691         err = tpm_sendrecv_command(dev, command, response, &response_length);
692         if (err)
693                 return err;
694         if (unpack_byte_string(response, response_length, "ds",
695                                res_auth_handle_offset, &oiap_session.handle,
696                                res_nonce_even_offset, &oiap_session.nonce_even,
697                                (u32)DIGEST_LENGTH))
698                 return TPM_LIB_ERROR;
699         oiap_session.valid = 1;
700         if (auth_handle)
701                 *auth_handle = oiap_session.handle;
702         return 0;
703 }
704
705 u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
706                        size_t key_length, const void *parent_key_usage_auth,
707                        u32 *key_handle)
708 {
709         const u8 command[14] = {
710                 0x00, 0xc2,             /* TPM_TAG */
711                 0x00, 0x00, 0x00, 0x00, /* parameter size */
712                 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
713                 0x00, 0x00, 0x00, 0x00, /* parent handle */
714         };
715         const size_t req_size_offset = 2;
716         const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
717         const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
718         const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
719         u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
720                    TPM_REQUEST_AUTH_LENGTH];
721         u8 response[COMMAND_BUFFER_SIZE];
722         size_t response_length = sizeof(response);
723         u32 err;
724
725         if (!oiap_session.valid) {
726                 err = tpm_oiap(dev, NULL);
727                 if (err)
728                         return err;
729         }
730         if (pack_byte_string(request, sizeof(request), "sdds",
731                              0, command, sizeof(command),
732                              req_size_offset,
733                              sizeof(command) + key_length
734                              + TPM_REQUEST_AUTH_LENGTH,
735                              req_parent_handle_offset, parent_handle,
736                              req_key_offset, key, key_length
737                 ))
738                 return TPM_LIB_ERROR;
739
740         err = create_request_auth(request, sizeof(command) + key_length, 4,
741                                   &oiap_session,
742                                   request + sizeof(command) + key_length,
743                                   parent_key_usage_auth);
744         if (err)
745                 return err;
746         err = tpm_sendrecv_command(dev, request, response, &response_length);
747         if (err) {
748                 if (err == TPM_AUTHFAIL)
749                         oiap_session.valid = 0;
750                 return err;
751         }
752
753         err = verify_response_auth(0x00000041, response,
754                                    response_length - TPM_RESPONSE_AUTH_LENGTH,
755                                    4, &oiap_session,
756                                    response + response_length -
757                                    TPM_RESPONSE_AUTH_LENGTH,
758                                    parent_key_usage_auth);
759         if (err)
760                 return err;
761
762         if (key_handle) {
763                 if (unpack_byte_string(response, response_length, "d",
764                                        res_handle_offset, key_handle))
765                         return TPM_LIB_ERROR;
766         }
767
768         return 0;
769 }
770
771 u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
772                          const void *usage_auth, void *pubkey,
773                          size_t *pubkey_len)
774 {
775         const u8 command[14] = {
776                 0x00, 0xc2,             /* TPM_TAG */
777                 0x00, 0x00, 0x00, 0x00, /* parameter size */
778                 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
779                 0x00, 0x00, 0x00, 0x00, /* key handle */
780         };
781         const size_t req_size_offset = 2;
782         const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
783         const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
784         u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
785         u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
786                     TPM_RESPONSE_AUTH_LENGTH];
787         size_t response_length = sizeof(response);
788         u32 err;
789
790         if (!oiap_session.valid) {
791                 err = tpm_oiap(dev, NULL);
792                 if (err)
793                         return err;
794         }
795         if (pack_byte_string(request, sizeof(request), "sdd",
796                              0, command, sizeof(command),
797                              req_size_offset,
798                              (u32)(sizeof(command)
799                              + TPM_REQUEST_AUTH_LENGTH),
800                              req_key_handle_offset, key_handle
801                 ))
802                 return TPM_LIB_ERROR;
803         err = create_request_auth(request, sizeof(command), 4, &oiap_session,
804                                   request + sizeof(command), usage_auth);
805         if (err)
806                 return err;
807         err = tpm_sendrecv_command(dev, request, response, &response_length);
808         if (err) {
809                 if (err == TPM_AUTHFAIL)
810                         oiap_session.valid = 0;
811                 return err;
812         }
813         err = verify_response_auth(0x00000021, response,
814                                    response_length - TPM_RESPONSE_AUTH_LENGTH,
815                                    0, &oiap_session,
816                                    response + response_length -
817                                    TPM_RESPONSE_AUTH_LENGTH,
818                                    usage_auth);
819         if (err)
820                 return err;
821
822         if (pubkey) {
823                 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
824                      - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
825                         return TPM_LIB_ERROR;
826                 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
827                         - TPM_RESPONSE_AUTH_LENGTH;
828                 memcpy(pubkey, response + res_pubkey_offset,
829                        response_length - TPM_RESPONSE_HEADER_LENGTH
830                        - TPM_RESPONSE_AUTH_LENGTH);
831         }
832
833         return 0;
834 }
835
836 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
837 u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
838                       const u8 pubkey_digest[20], u32 *handle)
839 {
840         u16 key_count;
841         u32 key_handles[10];
842         u8 buf[288];
843         u8 *ptr;
844         u32 err;
845         u8 digest[20];
846         size_t buf_len;
847         unsigned int i;
848
849         /* fetch list of already loaded keys in the TPM */
850         err = tpm_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
851                                  sizeof(buf));
852         if (err)
853                 return -1;
854         key_count = get_unaligned_be16(buf);
855         ptr = buf + 2;
856         for (i = 0; i < key_count; ++i, ptr += 4)
857                 key_handles[i] = get_unaligned_be32(ptr);
858
859         /* now search a(/ the) key which we can access with the given auth */
860         for (i = 0; i < key_count; ++i) {
861                 buf_len = sizeof(buf);
862                 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
863                 if (err && err != TPM_AUTHFAIL)
864                         return -1;
865                 if (err)
866                         continue;
867                 sha1_csum(buf, buf_len, digest);
868                 if (!memcmp(digest, pubkey_digest, 20)) {
869                         *handle = key_handles[i];
870                         return 0;
871                 }
872         }
873         return 1;
874 }
875 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
876
877 #endif /* CONFIG_TPM_AUTH_SESSIONS */
878
879 u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
880 {
881         const u8 command[14] = {
882                 0x0, 0xc1,              /* TPM_TAG */
883                 0x0, 0x0, 0x0, 0xe,     /* parameter size */
884                 0x0, 0x0, 0x0, 0x46,    /* TPM_COMMAND_CODE */
885         };
886         const size_t length_offset = 10;
887         const size_t data_size_offset = 10;
888         const size_t data_offset = 14;
889         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
890         size_t response_length = sizeof(response);
891         u32 data_size;
892         u8 *out = data;
893
894         while (count > 0) {
895                 u32 this_bytes = min((size_t)count,
896                                      sizeof(response) - data_offset);
897                 u32 err;
898
899                 if (pack_byte_string(buf, sizeof(buf), "sd",
900                                      0, command, sizeof(command),
901                                      length_offset, this_bytes))
902                         return TPM_LIB_ERROR;
903                 err = tpm_sendrecv_command(dev, buf, response,
904                                            &response_length);
905                 if (err)
906                         return err;
907                 if (unpack_byte_string(response, response_length, "d",
908                                        data_size_offset, &data_size))
909                         return TPM_LIB_ERROR;
910                 if (data_size > count)
911                         return TPM_LIB_ERROR;
912                 if (unpack_byte_string(response, response_length, "s",
913                                        data_offset, out, data_size))
914                         return TPM_LIB_ERROR;
915
916                 count -= data_size;
917                 out += data_size;
918         }
919
920         return 0;
921 }