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