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