Merge git://git.denx.de/u-boot-sunxi
[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(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(buf, NULL, NULL);
48 }
49
50 u32 tpm_resume(void)
51 {
52         return tpm_startup(TPM_ST_STATE);
53 }
54
55 u32 tpm_self_test_full(void)
56 {
57         const u8 command[10] = {
58                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
59         };
60         return tpm_sendrecv_command(command, NULL, NULL);
61 }
62
63 u32 tpm_continue_self_test(void)
64 {
65         const u8 command[10] = {
66                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
67         };
68         return tpm_sendrecv_command(command, NULL, NULL);
69 }
70
71 u32 tpm_clear_and_reenable(void)
72 {
73         u32 ret;
74
75         log_info("TPM: Clear and re-enable\n");
76         ret = tpm_force_clear();
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();
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(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(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(buf, NULL, NULL);
140 }
141
142 u32 tpm_nv_set_locked(void)
143 {
144         return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
145 }
146
147 u32 tpm_nv_read_value(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(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(u32 index, const void *data, u32 length)
182 {
183         const u8 command[256] = {
184                 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
185         };
186         const size_t command_size_offset = 2;
187         const size_t index_offset = 10;
188         const size_t length_offset = 18;
189         const size_t data_offset = 22;
190         const size_t write_info_size = 12;
191         const u32 total_length =
192                 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
193         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
194         size_t response_length = sizeof(response);
195         u32 err;
196
197         if (pack_byte_string(buf, sizeof(buf), "sddds",
198                              0, command, sizeof(command),
199                              command_size_offset, total_length,
200                              index_offset, index,
201                              length_offset, length,
202                              data_offset, data, length))
203                 return TPM_LIB_ERROR;
204         err = tpm_sendrecv_command(buf, response, &response_length);
205         if (err)
206                 return err;
207
208         return 0;
209 }
210
211 uint32_t tpm_set_global_lock(void)
212 {
213         u32 x;
214
215         return tpm_nv_write_value(TPM_NV_INDEX_0, (uint8_t *)&x, 0);
216 }
217
218 u32 tpm_extend(u32 index, const void *in_digest, 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(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(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(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(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(buf, NULL, NULL);
291 }
292
293 u32 tpm_finalise_physical_presence(void)
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(command, NULL, NULL);
300 }
301
302 u32 tpm_read_pubek(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(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(void)
334 {
335         const u8 command[10] = {
336                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
337         };
338
339         return tpm_sendrecv_command(command, NULL, NULL);
340 }
341
342 u32 tpm_physical_enable(void)
343 {
344         const u8 command[10] = {
345                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
346         };
347
348         return tpm_sendrecv_command(command, NULL, NULL);
349 }
350
351 u32 tpm_physical_disable(void)
352 {
353         const u8 command[10] = {
354                 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
355         };
356
357         return tpm_sendrecv_command(command, NULL, NULL);
358 }
359
360 u32 tpm_physical_set_deactivated(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(buf, NULL, NULL);
374 }
375
376 u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
377 {
378         const u8 command[22] = {
379                 0x0, 0xc1,              /* TPM_TAG */
380                 0x0, 0x0, 0x0, 0x16,    /* parameter size */
381                 0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
382                 0x0, 0x0, 0x0, 0x0,     /* TPM_CAPABILITY_AREA */
383                 0x0, 0x0, 0x0, 0x4,     /* subcap size */
384                 0x0, 0x0, 0x0, 0x0,     /* subcap value */
385         };
386         const size_t cap_area_offset = 10;
387         const size_t sub_cap_offset = 18;
388         const size_t cap_offset = 14;
389         const size_t cap_size_offset = 10;
390         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
391         size_t response_length = sizeof(response);
392         u32 cap_size;
393         u32 err;
394
395         if (pack_byte_string(buf, sizeof(buf), "sdd",
396                              0, command, sizeof(command),
397                              cap_area_offset, cap_area,
398                              sub_cap_offset, sub_cap))
399                 return TPM_LIB_ERROR;
400         err = tpm_sendrecv_command(buf, response, &response_length);
401         if (err)
402                 return err;
403         if (unpack_byte_string(response, response_length, "d",
404                                cap_size_offset, &cap_size))
405                 return TPM_LIB_ERROR;
406         if (cap_size > response_length || cap_size > count)
407                 return TPM_LIB_ERROR;
408         if (unpack_byte_string(response, response_length, "s",
409                                cap_offset, cap, cap_size))
410                 return TPM_LIB_ERROR;
411
412         return 0;
413 }
414
415 u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
416 {
417         const u8 command[22] = {
418                 0x0, 0xc1,              /* TPM_TAG */
419                 0x0, 0x0, 0x0, 0x16,    /* parameter size */
420                 0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
421                 0x0, 0x0, 0x0, 0x4,     /* TPM_CAP_FLAG_PERM */
422                 0x0, 0x0, 0x0, 0x4,     /* subcap size */
423                 0x0, 0x0, 0x1, 0x8,     /* subcap value */
424         };
425         const size_t data_size_offset = TPM_HEADER_SIZE;
426         const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
427         u8 response[COMMAND_BUFFER_SIZE];
428         size_t response_length = sizeof(response);
429         u32 err;
430         u32 data_size;
431
432         err = tpm_sendrecv_command(command, response, &response_length);
433         if (err)
434                 return err;
435         if (unpack_byte_string(response, response_length, "d",
436                                data_size_offset, &data_size)) {
437                 log_err("Cannot unpack data size\n");
438                 return TPM_LIB_ERROR;
439         }
440         if (data_size < sizeof(*pflags)) {
441                 log_err("Data size too small\n");
442                 return TPM_LIB_ERROR;
443         }
444         if (unpack_byte_string(response, response_length, "s",
445                                data_offset, pflags, sizeof(*pflags))) {
446                 log_err("Cannot unpack pflags\n");
447                 return TPM_LIB_ERROR;
448         }
449
450         return 0;
451 }
452
453 u32 tpm_get_permissions(u32 index, u32 *perm)
454 {
455         const u8 command[22] = {
456                 0x0, 0xc1,              /* TPM_TAG */
457                 0x0, 0x0, 0x0, 0x16,    /* parameter size */
458                 0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
459                 0x0, 0x0, 0x0, 0x11,
460                 0x0, 0x0, 0x0, 0x4,
461         };
462         const size_t index_offset = 18;
463         const size_t perm_offset = 60;
464         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
465         size_t response_length = sizeof(response);
466         u32 err;
467
468         if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
469                              index_offset, index))
470                 return TPM_LIB_ERROR;
471         err = tpm_sendrecv_command(buf, response, &response_length);
472         if (err)
473                 return err;
474         if (unpack_byte_string(response, response_length, "d",
475                                perm_offset, perm))
476                 return TPM_LIB_ERROR;
477
478         return 0;
479 }
480
481 #ifdef CONFIG_TPM_FLUSH_RESOURCES
482 u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
483 {
484         const u8 command[18] = {
485                 0x00, 0xc1,             /* TPM_TAG */
486                 0x00, 0x00, 0x00, 0x12, /* parameter size */
487                 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
488                 0x00, 0x00, 0x00, 0x00, /* key handle */
489                 0x00, 0x00, 0x00, 0x00, /* resource type */
490         };
491         const size_t key_handle_offset = 10;
492         const size_t resource_type_offset = 14;
493         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
494         size_t response_length = sizeof(response);
495         u32 err;
496
497         if (pack_byte_string(buf, sizeof(buf), "sdd",
498                              0, command, sizeof(command),
499                              key_handle_offset, key_handle,
500                              resource_type_offset, resource_type))
501                 return TPM_LIB_ERROR;
502
503         err = tpm_sendrecv_command(buf, response, &response_length);
504         if (err)
505                 return err;
506         return 0;
507 }
508 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
509
510 #ifdef CONFIG_TPM_AUTH_SESSIONS
511
512 /**
513  * Fill an authentication block in a request.
514  * This func can create the first as well as the second auth block (for
515  * double authorized commands).
516  *
517  * @param request       pointer to the request (w/ uninitialised auth data)
518  * @param request_len0  length of the request without auth data
519  * @param handles_len   length of the handles area in request
520  * @param auth_session  pointer to the (valid) auth session to be used
521  * @param request_auth  pointer to the auth block of the request to be filled
522  * @param auth          authentication data (HMAC key)
523  */
524 static u32 create_request_auth(const void *request, size_t request_len0,
525                                size_t handles_len,
526                                struct session_data *auth_session,
527                                void *request_auth, const void *auth)
528 {
529         u8 hmac_data[DIGEST_LENGTH * 3 + 1];
530         sha1_context hash_ctx;
531         const size_t command_code_offset = 6;
532         const size_t auth_nonce_odd_offset = 4;
533         const size_t auth_continue_offset = 24;
534         const size_t auth_auth_offset = 25;
535
536         if (!auth_session || !auth_session->valid)
537                 return TPM_LIB_ERROR;
538
539         sha1_starts(&hash_ctx);
540         sha1_update(&hash_ctx, request + command_code_offset, 4);
541         if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
542                 sha1_update(&hash_ctx,
543                             request + TPM_REQUEST_HEADER_LENGTH + handles_len,
544                             request_len0 - TPM_REQUEST_HEADER_LENGTH
545                             - handles_len);
546         sha1_finish(&hash_ctx, hmac_data);
547
548         sha1_starts(&hash_ctx);
549         sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
550         sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
551         sha1_finish(&hash_ctx, auth_session->nonce_odd);
552
553         if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
554                              0, auth_session->handle,
555                              auth_nonce_odd_offset, auth_session->nonce_odd,
556                              DIGEST_LENGTH,
557                              auth_continue_offset, 1))
558                 return TPM_LIB_ERROR;
559         if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
560                              DIGEST_LENGTH,
561                              auth_session->nonce_even,
562                              DIGEST_LENGTH,
563                              2 * DIGEST_LENGTH,
564                              request_auth + auth_nonce_odd_offset,
565                              DIGEST_LENGTH + 1))
566                 return TPM_LIB_ERROR;
567         sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
568                   request_auth + auth_auth_offset);
569
570         return TPM_SUCCESS;
571 }
572
573 /**
574  * Verify an authentication block in a response.
575  * Since this func updates the nonce_even in the session data it has to be
576  * called when receiving a succesfull AUTH response.
577  * This func can verify the first as well as the second auth block (for
578  * double authorized commands).
579  *
580  * @param command_code  command code of the request
581  * @param response      pointer to the request (w/ uninitialised auth data)
582  * @param handles_len   length of the handles area in response
583  * @param auth_session  pointer to the (valid) auth session to be used
584  * @param response_auth pointer to the auth block of the response to be verified
585  * @param auth          authentication data (HMAC key)
586  */
587 static u32 verify_response_auth(u32 command_code, const void *response,
588                                 size_t response_len0, size_t handles_len,
589                                 struct session_data *auth_session,
590                                 const void *response_auth, const void *auth)
591 {
592         u8 hmac_data[DIGEST_LENGTH * 3 + 1];
593         u8 computed_auth[DIGEST_LENGTH];
594         sha1_context hash_ctx;
595         const size_t return_code_offset = 6;
596         const size_t auth_continue_offset = 20;
597         const size_t auth_auth_offset = 21;
598         u8 auth_continue;
599
600         if (!auth_session || !auth_session->valid)
601                 return TPM_AUTHFAIL;
602         if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
603                              0, command_code))
604                 return TPM_LIB_ERROR;
605         if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
606                 return TPM_LIB_ERROR;
607
608         sha1_starts(&hash_ctx);
609         sha1_update(&hash_ctx, response + return_code_offset, 4);
610         sha1_update(&hash_ctx, hmac_data, 4);
611         if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
612                 sha1_update(&hash_ctx,
613                             response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
614                             response_len0 - TPM_RESPONSE_HEADER_LENGTH
615                             - handles_len);
616         sha1_finish(&hash_ctx, hmac_data);
617
618         memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
619         auth_continue = ((u8 *)response_auth)[auth_continue_offset];
620         if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
621                              DIGEST_LENGTH,
622                              response_auth,
623                              DIGEST_LENGTH,
624                              2 * DIGEST_LENGTH,
625                              auth_session->nonce_odd,
626                              DIGEST_LENGTH,
627                              3 * DIGEST_LENGTH,
628                              auth_continue))
629                 return TPM_LIB_ERROR;
630
631         sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
632                   computed_auth);
633
634         if (memcmp(computed_auth, response_auth + auth_auth_offset,
635                    DIGEST_LENGTH))
636                 return TPM_AUTHFAIL;
637
638         return TPM_SUCCESS;
639 }
640
641 u32 tpm_terminate_auth_session(u32 auth_handle)
642 {
643         const u8 command[18] = {
644                 0x00, 0xc1,             /* TPM_TAG */
645                 0x00, 0x00, 0x00, 0x00, /* parameter size */
646                 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
647                 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
648                 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
649         };
650         const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
651         u8 request[COMMAND_BUFFER_SIZE];
652
653         if (pack_byte_string(request, sizeof(request), "sd",
654                              0, command, sizeof(command),
655                              req_handle_offset, auth_handle))
656                 return TPM_LIB_ERROR;
657         if (oiap_session.valid && oiap_session.handle == auth_handle)
658                 oiap_session.valid = 0;
659
660         return tpm_sendrecv_command(request, NULL, NULL);
661 }
662
663 u32 tpm_end_oiap(void)
664 {
665         u32 err = TPM_SUCCESS;
666
667         if (oiap_session.valid)
668                 err = tpm_terminate_auth_session(oiap_session.handle);
669         return err;
670 }
671
672 u32 tpm_oiap(u32 *auth_handle)
673 {
674         const u8 command[10] = {
675                 0x00, 0xc1,             /* TPM_TAG */
676                 0x00, 0x00, 0x00, 0x0a, /* parameter size */
677                 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
678         };
679         const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
680         const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
681         u8 response[COMMAND_BUFFER_SIZE];
682         size_t response_length = sizeof(response);
683         u32 err;
684
685         if (oiap_session.valid)
686                 tpm_terminate_auth_session(oiap_session.handle);
687
688         err = tpm_sendrecv_command(command, response, &response_length);
689         if (err)
690                 return err;
691         if (unpack_byte_string(response, response_length, "ds",
692                                res_auth_handle_offset, &oiap_session.handle,
693                                res_nonce_even_offset, &oiap_session.nonce_even,
694                                (u32)DIGEST_LENGTH))
695                 return TPM_LIB_ERROR;
696         oiap_session.valid = 1;
697         if (auth_handle)
698                 *auth_handle = oiap_session.handle;
699         return 0;
700 }
701
702 u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
703                        const void *parent_key_usage_auth, u32 *key_handle)
704 {
705         const u8 command[14] = {
706                 0x00, 0xc2,             /* TPM_TAG */
707                 0x00, 0x00, 0x00, 0x00, /* parameter size */
708                 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
709                 0x00, 0x00, 0x00, 0x00, /* parent handle */
710         };
711         const size_t req_size_offset = 2;
712         const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
713         const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
714         const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
715         u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
716                    TPM_REQUEST_AUTH_LENGTH];
717         u8 response[COMMAND_BUFFER_SIZE];
718         size_t response_length = sizeof(response);
719         u32 err;
720
721         if (!oiap_session.valid) {
722                 err = tpm_oiap(NULL);
723                 if (err)
724                         return err;
725         }
726         if (pack_byte_string(request, sizeof(request), "sdds",
727                              0, command, sizeof(command),
728                              req_size_offset,
729                              sizeof(command) + key_length
730                              + TPM_REQUEST_AUTH_LENGTH,
731                              req_parent_handle_offset, parent_handle,
732                              req_key_offset, key, key_length
733                 ))
734                 return TPM_LIB_ERROR;
735
736         err = create_request_auth(request, sizeof(command) + key_length, 4,
737                                   &oiap_session,
738                                   request + sizeof(command) + key_length,
739                                   parent_key_usage_auth);
740         if (err)
741                 return err;
742         err = tpm_sendrecv_command(request, response, &response_length);
743         if (err) {
744                 if (err == TPM_AUTHFAIL)
745                         oiap_session.valid = 0;
746                 return err;
747         }
748
749         err = verify_response_auth(0x00000041, response,
750                                    response_length - TPM_RESPONSE_AUTH_LENGTH,
751                                    4, &oiap_session,
752                                    response + response_length -
753                                    TPM_RESPONSE_AUTH_LENGTH,
754                                    parent_key_usage_auth);
755         if (err)
756                 return err;
757
758         if (key_handle) {
759                 if (unpack_byte_string(response, response_length, "d",
760                                        res_handle_offset, key_handle))
761                         return TPM_LIB_ERROR;
762         }
763
764         return 0;
765 }
766
767 u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
768                          size_t *pubkey_len)
769 {
770         const u8 command[14] = {
771                 0x00, 0xc2,             /* TPM_TAG */
772                 0x00, 0x00, 0x00, 0x00, /* parameter size */
773                 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
774                 0x00, 0x00, 0x00, 0x00, /* key handle */
775         };
776         const size_t req_size_offset = 2;
777         const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
778         const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
779         u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
780         u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
781                     TPM_RESPONSE_AUTH_LENGTH];
782         size_t response_length = sizeof(response);
783         u32 err;
784
785         if (!oiap_session.valid) {
786                 err = tpm_oiap(NULL);
787                 if (err)
788                         return err;
789         }
790         if (pack_byte_string(request, sizeof(request), "sdd",
791                              0, command, sizeof(command),
792                              req_size_offset,
793                              (u32)(sizeof(command)
794                              + TPM_REQUEST_AUTH_LENGTH),
795                              req_key_handle_offset, key_handle
796                 ))
797                 return TPM_LIB_ERROR;
798         err = create_request_auth(request, sizeof(command), 4, &oiap_session,
799                                   request + sizeof(command), usage_auth);
800         if (err)
801                 return err;
802         err = tpm_sendrecv_command(request, response, &response_length);
803         if (err) {
804                 if (err == TPM_AUTHFAIL)
805                         oiap_session.valid = 0;
806                 return err;
807         }
808         err = verify_response_auth(0x00000021, response,
809                                    response_length - TPM_RESPONSE_AUTH_LENGTH,
810                                    0, &oiap_session,
811                                    response + response_length -
812                                    TPM_RESPONSE_AUTH_LENGTH,
813                                    usage_auth);
814         if (err)
815                 return err;
816
817         if (pubkey) {
818                 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
819                      - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
820                         return TPM_LIB_ERROR;
821                 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
822                         - TPM_RESPONSE_AUTH_LENGTH;
823                 memcpy(pubkey, response + res_pubkey_offset,
824                        response_length - TPM_RESPONSE_HEADER_LENGTH
825                        - TPM_RESPONSE_AUTH_LENGTH);
826         }
827
828         return 0;
829 }
830
831 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
832 u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
833                       u32 *handle)
834 {
835         u16 key_count;
836         u32 key_handles[10];
837         u8 buf[288];
838         u8 *ptr;
839         u32 err;
840         u8 digest[20];
841         size_t buf_len;
842         unsigned int i;
843
844         /* fetch list of already loaded keys in the TPM */
845         err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
846         if (err)
847                 return -1;
848         key_count = get_unaligned_be16(buf);
849         ptr = buf + 2;
850         for (i = 0; i < key_count; ++i, ptr += 4)
851                 key_handles[i] = get_unaligned_be32(ptr);
852
853         /* now search a(/ the) key which we can access with the given auth */
854         for (i = 0; i < key_count; ++i) {
855                 buf_len = sizeof(buf);
856                 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
857                 if (err && err != TPM_AUTHFAIL)
858                         return -1;
859                 if (err)
860                         continue;
861                 sha1_csum(buf, buf_len, digest);
862                 if (!memcmp(digest, pubkey_digest, 20)) {
863                         *handle = key_handles[i];
864                         return 0;
865                 }
866         }
867         return 1;
868 }
869 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
870
871 #endif /* CONFIG_TPM_AUTH_SESSIONS */
872
873 u32 tpm_get_random(void *data, u32 count)
874 {
875         const u8 command[14] = {
876                 0x0, 0xc1,              /* TPM_TAG */
877                 0x0, 0x0, 0x0, 0xe,     /* parameter size */
878                 0x0, 0x0, 0x0, 0x46,    /* TPM_COMMAND_CODE */
879         };
880         const size_t length_offset = 10;
881         const size_t data_size_offset = 10;
882         const size_t data_offset = 14;
883         u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
884         size_t response_length = sizeof(response);
885         u32 data_size;
886         u8 *out = data;
887
888         while (count > 0) {
889                 u32 this_bytes = min((size_t)count,
890                                      sizeof(response) - data_offset);
891                 u32 err;
892
893                 if (pack_byte_string(buf, sizeof(buf), "sd",
894                                      0, command, sizeof(command),
895                                      length_offset, this_bytes))
896                         return TPM_LIB_ERROR;
897                 err = tpm_sendrecv_command(buf, response, &response_length);
898                 if (err)
899                         return err;
900                 if (unpack_byte_string(response, response_length, "d",
901                                        data_size_offset, &data_size))
902                         return TPM_LIB_ERROR;
903                 if (data_size > count)
904                         return TPM_LIB_ERROR;
905                 if (unpack_byte_string(response, response_length, "s",
906                                        data_offset, out, data_size))
907                         return TPM_LIB_ERROR;
908
909                 count -= data_size;
910                 out += data_size;
911         }
912
913         return 0;
914 }