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