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