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