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