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