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