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