blob: e66023da5e67e6ee1faea5909b147d06b46a9e9d [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Che-liang Chiou8732b072013-02-28 09:34:57 +00002/*
3 * Copyright (c) 2013 The Chromium OS Authors.
Reinhard Pfaube6c1522013-06-26 15:55:13 +02004 * Coypright (c) 2013 Guntermann & Drunck GmbH
Che-liang Chiou8732b072013-02-28 09:34:57 +00005 */
6
Simon Glass6e64ec12018-10-01 12:22:29 -06007#define LOG_CATEGORY UCLASS_TPM
8
Simon Glassc8a8c512015-08-22 18:31:32 -06009#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Che-liang Chiou8732b072013-02-28 09:34:57 +000011#include <asm/unaligned.h>
Simon Glassc8a8c512015-08-22 18:31:32 -060012#include <u-boot/sha1.h>
Miquel Raynald677bfe2018-05-15 11:57:06 +020013#include <tpm-common.h>
14#include <tpm-v1.h>
15#include "tpm-utils.h"
Che-liang Chiou8732b072013-02-28 09:34:57 +000016
Reinhard Pfaube6c1522013-06-26 15:55:13 +020017#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;
Miquel Raynalb9804e52018-05-15 11:56:59 +020025 u32 handle;
26 u8 nonce_even[DIGEST_LENGTH];
27 u8 nonce_odd[DIGEST_LENGTH];
Reinhard Pfaube6c1522013-06-26 15:55:13 +020028};
29
30static struct session_data oiap_session = {0, };
31
32#endif /* CONFIG_TPM_AUTH_SESSIONS */
33
Simon Glassd6a885f2021-02-06 14:23:36 -070034u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode)
Che-liang Chiou8732b072013-02-28 09:34:57 +000035{
Miquel Raynalb9804e52018-05-15 11:56:59 +020036 const u8 command[12] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +000037 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
38 };
39 const size_t mode_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +020040 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +000041
42 if (pack_byte_string(buf, sizeof(buf), "sw",
Miquel Raynalc6179182018-05-15 11:57:00 +020043 0, command, sizeof(command),
44 mode_offset, mode))
Che-liang Chiou8732b072013-02-28 09:34:57 +000045 return TPM_LIB_ERROR;
46
Simon Glassabdc7b82018-11-18 14:22:27 -070047 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +000048}
49
Simon Glassd6a885f2021-02-06 14:23:36 -070050u32 tpm1_resume(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -060051{
Simon Glassd6a885f2021-02-06 14:23:36 -070052 return tpm1_startup(dev, TPM_ST_STATE);
Simon Glass6e64ec12018-10-01 12:22:29 -060053}
54
Simon Glassd6a885f2021-02-06 14:23:36 -070055u32 tpm1_self_test_full(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +000056{
Miquel Raynalb9804e52018-05-15 11:56:59 +020057 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +000058 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
59 };
Simon Glassabdc7b82018-11-18 14:22:27 -070060 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +000061}
62
Simon Glassd6a885f2021-02-06 14:23:36 -070063u32 tpm1_continue_self_test(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +000064{
Miquel Raynalb9804e52018-05-15 11:56:59 +020065 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +000066 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
67 };
Simon Glassabdc7b82018-11-18 14:22:27 -070068 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +000069}
70
Simon Glassa11be4c2023-02-21 06:24:52 -070071u32 tpm1_auto_start(struct udevice *dev)
72{
73 u32 rc;
74
75 rc = tpm1_startup(dev, TPM_ST_CLEAR);
76 /* continue on if the TPM is already inited */
77 if (rc && rc != TPM_INVALID_POSTINIT)
78 return rc;
79
80 rc = tpm1_self_test_full(dev);
81
82 return rc;
83}
84
Simon Glassd6a885f2021-02-06 14:23:36 -070085u32 tpm1_clear_and_reenable(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -060086{
87 u32 ret;
88
89 log_info("TPM: Clear and re-enable\n");
Simon Glassd6a885f2021-02-06 14:23:36 -070090 ret = tpm1_force_clear(dev);
Simon Glass6e64ec12018-10-01 12:22:29 -060091 if (ret != TPM_SUCCESS) {
92 log_err("Can't initiate a force clear\n");
93 return ret;
94 }
95
Simon Glassd6a885f2021-02-06 14:23:36 -070096 ret = tpm1_physical_enable(dev);
97 if (ret != TPM_SUCCESS) {
98 log_err("TPM: Can't set enabled state\n");
99 return ret;
100 }
Simon Glass6e64ec12018-10-01 12:22:29 -0600101
Simon Glassd6a885f2021-02-06 14:23:36 -0700102 ret = tpm1_physical_set_deactivated(dev, 0);
103 if (ret != TPM_SUCCESS) {
104 log_err("TPM: Can't set deactivated state\n");
105 return ret;
Simon Glass6e64ec12018-10-01 12:22:29 -0600106 }
Simon Glass6e64ec12018-10-01 12:22:29 -0600107
108 return TPM_SUCCESS;
109}
110
Simon Glassd6a885f2021-02-06 14:23:36 -0700111u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000112{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200113 const u8 command[101] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000114 0x0, 0xc1, /* TPM_TAG */
115 0x0, 0x0, 0x0, 0x65, /* parameter size */
116 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
117 /* TPM_NV_DATA_PUBLIC->... */
118 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
119 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
120 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
121 0x0, 0x3,
122 0, 0, 0,
123 0x1f,
124 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
126 0x0, 0x3,
127 0, 0, 0,
128 0x1f,
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 /* TPM_NV_ATTRIBUTES->... */
131 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
132 0, 0, 0, 0, /* ...->attributes */
133 /* End of TPM_NV_ATTRIBUTES */
134 0, /* bReadSTClear */
135 0, /* bWriteSTClear */
136 0, /* bWriteDefine */
137 0, 0, 0, 0, /* size */
138 };
139 const size_t index_offset = 12;
140 const size_t perm_offset = 70;
141 const size_t size_offset = 77;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200142 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000143
144 if (pack_byte_string(buf, sizeof(buf), "sddd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200145 0, command, sizeof(command),
146 index_offset, index,
147 perm_offset, perm,
148 size_offset, size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000149 return TPM_LIB_ERROR;
150
Simon Glassabdc7b82018-11-18 14:22:27 -0700151 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000152}
153
Simon Glassd6a885f2021-02-06 14:23:36 -0700154u32 tpm1_nv_set_locked(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -0600155{
Simon Glassd6a885f2021-02-06 14:23:36 -0700156 return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
Simon Glass6e64ec12018-10-01 12:22:29 -0600157}
158
Simon Glassd6a885f2021-02-06 14:23:36 -0700159u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000160{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200161 const u8 command[22] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000162 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
163 };
164 const size_t index_offset = 10;
165 const size_t length_offset = 18;
166 const size_t data_size_offset = 10;
167 const size_t data_offset = 14;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200168 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000169 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200170 u32 data_size;
171 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000172
173 if (pack_byte_string(buf, sizeof(buf), "sdd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200174 0, command, sizeof(command),
175 index_offset, index,
176 length_offset, count))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000177 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700178 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000179 if (err)
180 return err;
181 if (unpack_byte_string(response, response_length, "d",
Miquel Raynalc6179182018-05-15 11:57:00 +0200182 data_size_offset, &data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000183 return TPM_LIB_ERROR;
184 if (data_size > count)
185 return TPM_LIB_ERROR;
186 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200187 data_offset, data, data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000188 return TPM_LIB_ERROR;
189
190 return 0;
191}
192
Simon Glassd6a885f2021-02-06 14:23:36 -0700193u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
194 u32 length)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000195{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200196 const u8 command[256] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000197 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
198 };
199 const size_t command_size_offset = 2;
200 const size_t index_offset = 10;
201 const size_t length_offset = 18;
202 const size_t data_offset = 22;
203 const size_t write_info_size = 12;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200204 const u32 total_length =
Che-liang Chiou8732b072013-02-28 09:34:57 +0000205 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200206 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000207 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200208 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000209
210 if (pack_byte_string(buf, sizeof(buf), "sddds",
Miquel Raynalc6179182018-05-15 11:57:00 +0200211 0, command, sizeof(command),
212 command_size_offset, total_length,
213 index_offset, index,
214 length_offset, length,
215 data_offset, data, length))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000216 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700217 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000218 if (err)
219 return err;
220
221 return 0;
222}
223
Simon Glassd6a885f2021-02-06 14:23:36 -0700224u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
225 void *out_digest)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000226{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200227 const u8 command[34] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000228 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
229 };
230 const size_t index_offset = 10;
231 const size_t in_digest_offset = 14;
232 const size_t out_digest_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200233 u8 buf[COMMAND_BUFFER_SIZE];
234 u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000235 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200236 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000237
238 if (pack_byte_string(buf, sizeof(buf), "sds",
Miquel Raynalc6179182018-05-15 11:57:00 +0200239 0, command, sizeof(command),
240 index_offset, index,
241 in_digest_offset, in_digest,
242 PCR_DIGEST_LENGTH))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000243 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700244 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000245 if (err)
246 return err;
247
248 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200249 out_digest_offset, out_digest,
250 PCR_DIGEST_LENGTH))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000251 return TPM_LIB_ERROR;
252
253 return 0;
254}
255
Simon Glassd6a885f2021-02-06 14:23:36 -0700256u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000257{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200258 const u8 command[14] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000259 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
260 };
261 const size_t index_offset = 10;
262 const size_t out_digest_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200263 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000264 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200265 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000266
267 if (count < PCR_DIGEST_LENGTH)
268 return TPM_LIB_ERROR;
269
270 if (pack_byte_string(buf, sizeof(buf), "sd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200271 0, command, sizeof(command),
272 index_offset, index))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000273 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700274 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000275 if (err)
276 return err;
277 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200278 out_digest_offset, data, PCR_DIGEST_LENGTH))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000279 return TPM_LIB_ERROR;
280
281 return 0;
282}
283
Simon Glassd6a885f2021-02-06 14:23:36 -0700284u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000285{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200286 const u8 command[12] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000287 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
288 };
289 const size_t presence_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200290 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000291
292 if (pack_byte_string(buf, sizeof(buf), "sw",
Miquel Raynalc6179182018-05-15 11:57:00 +0200293 0, command, sizeof(command),
294 presence_offset, presence))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000295 return TPM_LIB_ERROR;
296
Simon Glassabdc7b82018-11-18 14:22:27 -0700297 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000298}
299
Simon Glassd6a885f2021-02-06 14:23:36 -0700300u32 tpm1_finalise_physical_presence(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -0600301{
302 const u8 command[12] = {
303 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
304 };
305
Simon Glassabdc7b82018-11-18 14:22:27 -0700306 return tpm_sendrecv_command(dev, command, NULL, NULL);
Simon Glass6e64ec12018-10-01 12:22:29 -0600307}
308
Simon Glassd6a885f2021-02-06 14:23:36 -0700309u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000310{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200311 const u8 command[30] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000312 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
313 };
314 const size_t response_size_offset = 2;
315 const size_t data_offset = 10;
316 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200317 u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000318 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200319 u32 data_size;
320 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000321
Simon Glassabdc7b82018-11-18 14:22:27 -0700322 err = tpm_sendrecv_command(dev, command, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000323 if (err)
324 return err;
325 if (unpack_byte_string(response, response_length, "d",
Miquel Raynalc6179182018-05-15 11:57:00 +0200326 response_size_offset, &data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000327 return TPM_LIB_ERROR;
328 if (data_size < header_and_checksum_size)
329 return TPM_LIB_ERROR;
330 data_size -= header_and_checksum_size;
331 if (data_size > count)
332 return TPM_LIB_ERROR;
333 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200334 data_offset, data, data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000335 return TPM_LIB_ERROR;
336
337 return 0;
338}
339
Simon Glassd6a885f2021-02-06 14:23:36 -0700340u32 tpm1_force_clear(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000341{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200342 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000343 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
344 };
345
Simon Glassabdc7b82018-11-18 14:22:27 -0700346 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000347}
348
Simon Glassd6a885f2021-02-06 14:23:36 -0700349u32 tpm1_physical_enable(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000350{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200351 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000352 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
353 };
354
Simon Glassabdc7b82018-11-18 14:22:27 -0700355 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000356}
357
Simon Glassd6a885f2021-02-06 14:23:36 -0700358u32 tpm1_physical_disable(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000359{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200360 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000361 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
362 };
363
Simon Glassabdc7b82018-11-18 14:22:27 -0700364 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000365}
366
Simon Glassd6a885f2021-02-06 14:23:36 -0700367u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000368{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200369 const u8 command[11] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000370 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
371 };
372 const size_t state_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200373 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000374
375 if (pack_byte_string(buf, sizeof(buf), "sb",
Miquel Raynalc6179182018-05-15 11:57:00 +0200376 0, command, sizeof(command),
377 state_offset, state))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000378 return TPM_LIB_ERROR;
379
Simon Glassabdc7b82018-11-18 14:22:27 -0700380 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000381}
382
Simon Glassd6a885f2021-02-06 14:23:36 -0700383u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
384 void *cap, size_t count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000385{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200386 const u8 command[22] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000387 0x0, 0xc1, /* TPM_TAG */
388 0x0, 0x0, 0x0, 0x16, /* parameter size */
389 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
390 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
391 0x0, 0x0, 0x0, 0x4, /* subcap size */
392 0x0, 0x0, 0x0, 0x0, /* subcap value */
393 };
394 const size_t cap_area_offset = 10;
395 const size_t sub_cap_offset = 18;
396 const size_t cap_offset = 14;
397 const size_t cap_size_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200398 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000399 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200400 u32 cap_size;
401 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000402
403 if (pack_byte_string(buf, sizeof(buf), "sdd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200404 0, command, sizeof(command),
405 cap_area_offset, cap_area,
406 sub_cap_offset, sub_cap))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000407 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700408 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000409 if (err)
410 return err;
411 if (unpack_byte_string(response, response_length, "d",
Miquel Raynalc6179182018-05-15 11:57:00 +0200412 cap_size_offset, &cap_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000413 return TPM_LIB_ERROR;
414 if (cap_size > response_length || cap_size > count)
415 return TPM_LIB_ERROR;
416 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200417 cap_offset, cap, cap_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000418 return TPM_LIB_ERROR;
419
420 return 0;
421}
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200422
Simon Glassd6a885f2021-02-06 14:23:36 -0700423u32 tpm1_get_permanent_flags(struct udevice *dev,
424 struct tpm_permanent_flags *pflags)
Simon Glass2132f972015-08-22 18:31:41 -0600425{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200426 const u8 command[22] = {
Simon Glass2132f972015-08-22 18:31:41 -0600427 0x0, 0xc1, /* TPM_TAG */
428 0x0, 0x0, 0x0, 0x16, /* parameter size */
429 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
430 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
431 0x0, 0x0, 0x0, 0x4, /* subcap size */
432 0x0, 0x0, 0x1, 0x8, /* subcap value */
433 };
André Draszike8155df2017-10-03 16:55:51 +0100434 const size_t data_size_offset = TPM_HEADER_SIZE;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200435 const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
436 u8 response[COMMAND_BUFFER_SIZE];
Simon Glass2132f972015-08-22 18:31:41 -0600437 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200438 u32 err;
439 u32 data_size;
Simon Glass2132f972015-08-22 18:31:41 -0600440
Simon Glassabdc7b82018-11-18 14:22:27 -0700441 err = tpm_sendrecv_command(dev, command, response, &response_length);
Simon Glass2132f972015-08-22 18:31:41 -0600442 if (err)
443 return err;
André Draszike8155df2017-10-03 16:55:51 +0100444 if (unpack_byte_string(response, response_length, "d",
Simon Glass6e64ec12018-10-01 12:22:29 -0600445 data_size_offset, &data_size)) {
446 log_err("Cannot unpack data size\n");
André Draszike8155df2017-10-03 16:55:51 +0100447 return TPM_LIB_ERROR;
Simon Glass6e64ec12018-10-01 12:22:29 -0600448 }
449 if (data_size < sizeof(*pflags)) {
450 log_err("Data size too small\n");
André Draszike8155df2017-10-03 16:55:51 +0100451 return TPM_LIB_ERROR;
Simon Glass6e64ec12018-10-01 12:22:29 -0600452 }
André Draszike8155df2017-10-03 16:55:51 +0100453 if (unpack_byte_string(response, response_length, "s",
Simon Glass6e64ec12018-10-01 12:22:29 -0600454 data_offset, pflags, sizeof(*pflags))) {
455 log_err("Cannot unpack pflags\n");
André Draszike8155df2017-10-03 16:55:51 +0100456 return TPM_LIB_ERROR;
Simon Glass6e64ec12018-10-01 12:22:29 -0600457 }
Simon Glass2132f972015-08-22 18:31:41 -0600458
459 return 0;
460}
461
Simon Glassd6a885f2021-02-06 14:23:36 -0700462u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
Simon Glass2132f972015-08-22 18:31:41 -0600463{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200464 const u8 command[22] = {
Simon Glass2132f972015-08-22 18:31:41 -0600465 0x0, 0xc1, /* TPM_TAG */
466 0x0, 0x0, 0x0, 0x16, /* parameter size */
467 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
468 0x0, 0x0, 0x0, 0x11,
469 0x0, 0x0, 0x0, 0x4,
470 };
471 const size_t index_offset = 18;
Simon Glassa0f38042022-08-30 21:05:33 -0600472 const size_t perm_offset = 74;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200473 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Simon Glass2132f972015-08-22 18:31:41 -0600474 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200475 u32 err;
Simon Glass2132f972015-08-22 18:31:41 -0600476
Simon Glassa0f38042022-08-30 21:05:33 -0600477 if (pack_byte_string(buf, sizeof(buf), "sd",
478 0, command, sizeof(command),
Simon Glass2132f972015-08-22 18:31:41 -0600479 index_offset, index))
480 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700481 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Simon Glass2132f972015-08-22 18:31:41 -0600482 if (err)
483 return err;
484 if (unpack_byte_string(response, response_length, "d",
485 perm_offset, perm))
486 return TPM_LIB_ERROR;
487
488 return 0;
489}
490
Mario Six7690be32017-01-11 16:00:50 +0100491#ifdef CONFIG_TPM_FLUSH_RESOURCES
Simon Glassd6a885f2021-02-06 14:23:36 -0700492u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
Mario Six7690be32017-01-11 16:00:50 +0100493{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200494 const u8 command[18] = {
Mario Six7690be32017-01-11 16:00:50 +0100495 0x00, 0xc1, /* TPM_TAG */
496 0x00, 0x00, 0x00, 0x12, /* parameter size */
497 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
498 0x00, 0x00, 0x00, 0x00, /* key handle */
499 0x00, 0x00, 0x00, 0x00, /* resource type */
500 };
501 const size_t key_handle_offset = 10;
502 const size_t resource_type_offset = 14;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200503 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Mario Six7690be32017-01-11 16:00:50 +0100504 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200505 u32 err;
Mario Six7690be32017-01-11 16:00:50 +0100506
507 if (pack_byte_string(buf, sizeof(buf), "sdd",
508 0, command, sizeof(command),
509 key_handle_offset, key_handle,
510 resource_type_offset, resource_type))
511 return TPM_LIB_ERROR;
512
Simon Glassabdc7b82018-11-18 14:22:27 -0700513 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Mario Six7690be32017-01-11 16:00:50 +0100514 if (err)
515 return err;
516 return 0;
517}
518#endif /* CONFIG_TPM_FLUSH_RESOURCES */
519
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200520#ifdef CONFIG_TPM_AUTH_SESSIONS
521
522/**
523 * Fill an authentication block in a request.
524 * This func can create the first as well as the second auth block (for
525 * double authorized commands).
526 *
527 * @param request pointer to the request (w/ uninitialised auth data)
528 * @param request_len0 length of the request without auth data
529 * @param handles_len length of the handles area in request
530 * @param auth_session pointer to the (valid) auth session to be used
531 * @param request_auth pointer to the auth block of the request to be filled
532 * @param auth authentication data (HMAC key)
533 */
Miquel Raynalb9804e52018-05-15 11:56:59 +0200534static u32 create_request_auth(const void *request, size_t request_len0,
535 size_t handles_len,
536 struct session_data *auth_session,
537 void *request_auth, const void *auth)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200538{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200539 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200540 sha1_context hash_ctx;
541 const size_t command_code_offset = 6;
542 const size_t auth_nonce_odd_offset = 4;
543 const size_t auth_continue_offset = 24;
544 const size_t auth_auth_offset = 25;
545
546 if (!auth_session || !auth_session->valid)
547 return TPM_LIB_ERROR;
548
549 sha1_starts(&hash_ctx);
550 sha1_update(&hash_ctx, request + command_code_offset, 4);
551 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
552 sha1_update(&hash_ctx,
553 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
554 request_len0 - TPM_REQUEST_HEADER_LENGTH
555 - handles_len);
556 sha1_finish(&hash_ctx, hmac_data);
557
558 sha1_starts(&hash_ctx);
559 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
560 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
561 sha1_finish(&hash_ctx, auth_session->nonce_odd);
562
563 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
564 0, auth_session->handle,
565 auth_nonce_odd_offset, auth_session->nonce_odd,
566 DIGEST_LENGTH,
567 auth_continue_offset, 1))
568 return TPM_LIB_ERROR;
569 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
570 DIGEST_LENGTH,
571 auth_session->nonce_even,
572 DIGEST_LENGTH,
573 2 * DIGEST_LENGTH,
574 request_auth + auth_nonce_odd_offset,
575 DIGEST_LENGTH + 1))
576 return TPM_LIB_ERROR;
577 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
578 request_auth + auth_auth_offset);
579
580 return TPM_SUCCESS;
581}
582
583/**
584 * Verify an authentication block in a response.
585 * Since this func updates the nonce_even in the session data it has to be
586 * called when receiving a succesfull AUTH response.
587 * This func can verify the first as well as the second auth block (for
588 * double authorized commands).
589 *
590 * @param command_code command code of the request
591 * @param response pointer to the request (w/ uninitialised auth data)
592 * @param handles_len length of the handles area in response
593 * @param auth_session pointer to the (valid) auth session to be used
594 * @param response_auth pointer to the auth block of the response to be verified
595 * @param auth authentication data (HMAC key)
596 */
Miquel Raynalb9804e52018-05-15 11:56:59 +0200597static u32 verify_response_auth(u32 command_code, const void *response,
598 size_t response_len0, size_t handles_len,
599 struct session_data *auth_session,
600 const void *response_auth, const void *auth)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200601{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200602 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
603 u8 computed_auth[DIGEST_LENGTH];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200604 sha1_context hash_ctx;
605 const size_t return_code_offset = 6;
606 const size_t auth_continue_offset = 20;
607 const size_t auth_auth_offset = 21;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200608 u8 auth_continue;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200609
610 if (!auth_session || !auth_session->valid)
611 return TPM_AUTHFAIL;
612 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
613 0, command_code))
614 return TPM_LIB_ERROR;
615 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
616 return TPM_LIB_ERROR;
617
618 sha1_starts(&hash_ctx);
619 sha1_update(&hash_ctx, response + return_code_offset, 4);
620 sha1_update(&hash_ctx, hmac_data, 4);
621 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
622 sha1_update(&hash_ctx,
623 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
624 response_len0 - TPM_RESPONSE_HEADER_LENGTH
625 - handles_len);
626 sha1_finish(&hash_ctx, hmac_data);
627
628 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200629 auth_continue = ((u8 *)response_auth)[auth_continue_offset];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200630 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
631 DIGEST_LENGTH,
632 response_auth,
633 DIGEST_LENGTH,
634 2 * DIGEST_LENGTH,
635 auth_session->nonce_odd,
636 DIGEST_LENGTH,
637 3 * DIGEST_LENGTH,
638 auth_continue))
639 return TPM_LIB_ERROR;
640
641 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
642 computed_auth);
643
644 if (memcmp(computed_auth, response_auth + auth_auth_offset,
645 DIGEST_LENGTH))
646 return TPM_AUTHFAIL;
647
648 return TPM_SUCCESS;
649}
650
Simon Glassd6a885f2021-02-06 14:23:36 -0700651u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200652{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200653 const u8 command[18] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200654 0x00, 0xc1, /* TPM_TAG */
655 0x00, 0x00, 0x00, 0x00, /* parameter size */
656 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
657 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
Miquel Raynal52da18a2018-05-15 11:57:02 +0200658 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200659 };
660 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200661 u8 request[COMMAND_BUFFER_SIZE];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200662
663 if (pack_byte_string(request, sizeof(request), "sd",
664 0, command, sizeof(command),
665 req_handle_offset, auth_handle))
666 return TPM_LIB_ERROR;
667 if (oiap_session.valid && oiap_session.handle == auth_handle)
668 oiap_session.valid = 0;
669
Simon Glassabdc7b82018-11-18 14:22:27 -0700670 return tpm_sendrecv_command(dev, request, NULL, NULL);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200671}
672
Simon Glassd6a885f2021-02-06 14:23:36 -0700673u32 tpm1_end_oiap(struct udevice *dev)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200674{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200675 u32 err = TPM_SUCCESS;
Miquel Raynal96cc4e32018-05-15 11:57:03 +0200676
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200677 if (oiap_session.valid)
Simon Glassd6a885f2021-02-06 14:23:36 -0700678 err = tpm1_terminate_auth_session(dev, oiap_session.handle);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200679 return err;
680}
681
Simon Glassd6a885f2021-02-06 14:23:36 -0700682u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200683{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200684 const u8 command[10] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200685 0x00, 0xc1, /* TPM_TAG */
686 0x00, 0x00, 0x00, 0x0a, /* parameter size */
687 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
688 };
689 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
690 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200691 u8 response[COMMAND_BUFFER_SIZE];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200692 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200693 u32 err;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200694
695 if (oiap_session.valid)
Simon Glassd6a885f2021-02-06 14:23:36 -0700696 tpm1_terminate_auth_session(dev, oiap_session.handle);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200697
Simon Glassabdc7b82018-11-18 14:22:27 -0700698 err = tpm_sendrecv_command(dev, command, response, &response_length);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200699 if (err)
700 return err;
701 if (unpack_byte_string(response, response_length, "ds",
702 res_auth_handle_offset, &oiap_session.handle,
703 res_nonce_even_offset, &oiap_session.nonce_even,
Miquel Raynalb9804e52018-05-15 11:56:59 +0200704 (u32)DIGEST_LENGTH))
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200705 return TPM_LIB_ERROR;
706 oiap_session.valid = 1;
707 if (auth_handle)
708 *auth_handle = oiap_session.handle;
709 return 0;
710}
711
Simon Glassd6a885f2021-02-06 14:23:36 -0700712u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
713 size_t key_length, const void *parent_key_usage_auth,
714 u32 *key_handle)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200715{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200716 const u8 command[14] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200717 0x00, 0xc2, /* TPM_TAG */
718 0x00, 0x00, 0x00, 0x00, /* parameter size */
719 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
720 0x00, 0x00, 0x00, 0x00, /* parent handle */
721 };
722 const size_t req_size_offset = 2;
723 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
724 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
725 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200726 u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
727 TPM_REQUEST_AUTH_LENGTH];
728 u8 response[COMMAND_BUFFER_SIZE];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200729 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200730 u32 err;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200731
732 if (!oiap_session.valid) {
Simon Glassd6a885f2021-02-06 14:23:36 -0700733 err = tpm1_oiap(dev, NULL);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200734 if (err)
735 return err;
736 }
737 if (pack_byte_string(request, sizeof(request), "sdds",
738 0, command, sizeof(command),
739 req_size_offset,
740 sizeof(command) + key_length
741 + TPM_REQUEST_AUTH_LENGTH,
742 req_parent_handle_offset, parent_handle,
743 req_key_offset, key, key_length
744 ))
745 return TPM_LIB_ERROR;
746
747 err = create_request_auth(request, sizeof(command) + key_length, 4,
Miquel Raynalc6179182018-05-15 11:57:00 +0200748 &oiap_session,
749 request + sizeof(command) + key_length,
750 parent_key_usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200751 if (err)
752 return err;
Simon Glassabdc7b82018-11-18 14:22:27 -0700753 err = tpm_sendrecv_command(dev, request, response, &response_length);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200754 if (err) {
755 if (err == TPM_AUTHFAIL)
756 oiap_session.valid = 0;
757 return err;
758 }
759
760 err = verify_response_auth(0x00000041, response,
Miquel Raynalc6179182018-05-15 11:57:00 +0200761 response_length - TPM_RESPONSE_AUTH_LENGTH,
762 4, &oiap_session,
763 response + response_length -
764 TPM_RESPONSE_AUTH_LENGTH,
765 parent_key_usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200766 if (err)
767 return err;
768
769 if (key_handle) {
770 if (unpack_byte_string(response, response_length, "d",
771 res_handle_offset, key_handle))
772 return TPM_LIB_ERROR;
773 }
774
775 return 0;
776}
777
Simon Glassd6a885f2021-02-06 14:23:36 -0700778u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
779 const void *usage_auth, void *pubkey,
780 size_t *pubkey_len)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200781{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200782 const u8 command[14] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200783 0x00, 0xc2, /* TPM_TAG */
784 0x00, 0x00, 0x00, 0x00, /* parameter size */
785 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
786 0x00, 0x00, 0x00, 0x00, /* key handle */
787 };
788 const size_t req_size_offset = 2;
789 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
790 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200791 u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
792 u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
793 TPM_RESPONSE_AUTH_LENGTH];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200794 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200795 u32 err;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200796
797 if (!oiap_session.valid) {
Simon Glassd6a885f2021-02-06 14:23:36 -0700798 err = tpm1_oiap(dev, NULL);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200799 if (err)
800 return err;
801 }
802 if (pack_byte_string(request, sizeof(request), "sdd",
803 0, command, sizeof(command),
804 req_size_offset,
Miquel Raynalb9804e52018-05-15 11:56:59 +0200805 (u32)(sizeof(command)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200806 + TPM_REQUEST_AUTH_LENGTH),
807 req_key_handle_offset, key_handle
808 ))
809 return TPM_LIB_ERROR;
810 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
Miquel Raynalc6179182018-05-15 11:57:00 +0200811 request + sizeof(command), usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200812 if (err)
813 return err;
Simon Glassabdc7b82018-11-18 14:22:27 -0700814 err = tpm_sendrecv_command(dev, request, response, &response_length);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200815 if (err) {
816 if (err == TPM_AUTHFAIL)
817 oiap_session.valid = 0;
818 return err;
819 }
820 err = verify_response_auth(0x00000021, response,
Miquel Raynalc6179182018-05-15 11:57:00 +0200821 response_length - TPM_RESPONSE_AUTH_LENGTH,
822 0, &oiap_session,
823 response + response_length -
824 TPM_RESPONSE_AUTH_LENGTH,
825 usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200826 if (err)
827 return err;
828
829 if (pubkey) {
830 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
Miquel Raynalc6179182018-05-15 11:57:00 +0200831 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200832 return TPM_LIB_ERROR;
833 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
834 - TPM_RESPONSE_AUTH_LENGTH;
835 memcpy(pubkey, response + res_pubkey_offset,
836 response_length - TPM_RESPONSE_HEADER_LENGTH
837 - TPM_RESPONSE_AUTH_LENGTH);
838 }
839
840 return 0;
841}
842
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100843#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
Simon Glassd6a885f2021-02-06 14:23:36 -0700844u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
845 const u8 pubkey_digest[20], u32 *handle)
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100846{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200847 u16 key_count;
848 u32 key_handles[10];
849 u8 buf[288];
850 u8 *ptr;
851 u32 err;
852 u8 digest[20];
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100853 size_t buf_len;
854 unsigned int i;
855
856 /* fetch list of already loaded keys in the TPM */
Mathew McBridee845dd72021-11-11 04:06:27 +0000857 err = tpm1_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
Simon Glassabdc7b82018-11-18 14:22:27 -0700858 sizeof(buf));
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100859 if (err)
860 return -1;
861 key_count = get_unaligned_be16(buf);
862 ptr = buf + 2;
863 for (i = 0; i < key_count; ++i, ptr += 4)
864 key_handles[i] = get_unaligned_be32(ptr);
865
866 /* now search a(/ the) key which we can access with the given auth */
867 for (i = 0; i < key_count; ++i) {
868 buf_len = sizeof(buf);
Mathew McBridee845dd72021-11-11 04:06:27 +0000869 err = tpm1_get_pub_key_oiap(dev, key_handles[i], auth, buf, &buf_len);
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100870 if (err && err != TPM_AUTHFAIL)
871 return -1;
872 if (err)
873 continue;
874 sha1_csum(buf, buf_len, digest);
875 if (!memcmp(digest, pubkey_digest, 20)) {
876 *handle = key_handles[i];
877 return 0;
878 }
879 }
880 return 1;
881}
882#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
883
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200884#endif /* CONFIG_TPM_AUTH_SESSIONS */
André Draszik3c605022017-10-03 16:55:52 +0100885
Simon Glassd6a885f2021-02-06 14:23:36 -0700886u32 tpm1_get_random(struct udevice *dev, void *data, u32 count)
André Draszik3c605022017-10-03 16:55:52 +0100887{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200888 const u8 command[14] = {
André Draszik3c605022017-10-03 16:55:52 +0100889 0x0, 0xc1, /* TPM_TAG */
890 0x0, 0x0, 0x0, 0xe, /* parameter size */
891 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
892 };
893 const size_t length_offset = 10;
894 const size_t data_size_offset = 10;
895 const size_t data_offset = 14;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200896 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
André Draszik3c605022017-10-03 16:55:52 +0100897 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200898 u32 data_size;
899 u8 *out = data;
André Draszik3c605022017-10-03 16:55:52 +0100900
901 while (count > 0) {
Miquel Raynalb9804e52018-05-15 11:56:59 +0200902 u32 this_bytes = min((size_t)count,
903 sizeof(response) - data_offset);
904 u32 err;
André Draszik3c605022017-10-03 16:55:52 +0100905
906 if (pack_byte_string(buf, sizeof(buf), "sd",
907 0, command, sizeof(command),
908 length_offset, this_bytes))
909 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700910 err = tpm_sendrecv_command(dev, buf, response,
911 &response_length);
André Draszik3c605022017-10-03 16:55:52 +0100912 if (err)
913 return err;
914 if (unpack_byte_string(response, response_length, "d",
915 data_size_offset, &data_size))
916 return TPM_LIB_ERROR;
917 if (data_size > count)
918 return TPM_LIB_ERROR;
919 if (unpack_byte_string(response, response_length, "s",
920 data_offset, out, data_size))
921 return TPM_LIB_ERROR;
922
923 count -= data_size;
924 out += data_size;
925 }
926
927 return 0;
928}