blob: d0e3ab1b21d1ab0109d1ddf00dadf9be83f665a9 [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
Che-liang Chiou8732b072013-02-28 09:34:57 +00009#include <common.h>
Simon Glassc8a8c512015-08-22 18:31:32 -060010#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Che-liang Chiou8732b072013-02-28 09:34:57 +000012#include <asm/unaligned.h>
Simon Glassc8a8c512015-08-22 18:31:32 -060013#include <u-boot/sha1.h>
Miquel Raynald677bfe2018-05-15 11:57:06 +020014#include <tpm-common.h>
15#include <tpm-v1.h>
16#include "tpm-utils.h"
Che-liang Chiou8732b072013-02-28 09:34:57 +000017
Reinhard Pfaube6c1522013-06-26 15:55:13 +020018#ifdef CONFIG_TPM_AUTH_SESSIONS
19
20#ifndef CONFIG_SHA1
21#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
22#endif /* !CONFIG_SHA1 */
23
24struct session_data {
25 int valid;
Miquel Raynalb9804e52018-05-15 11:56:59 +020026 u32 handle;
27 u8 nonce_even[DIGEST_LENGTH];
28 u8 nonce_odd[DIGEST_LENGTH];
Reinhard Pfaube6c1522013-06-26 15:55:13 +020029};
30
31static struct session_data oiap_session = {0, };
32
33#endif /* CONFIG_TPM_AUTH_SESSIONS */
34
Simon Glassd6a885f2021-02-06 14:23:36 -070035u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode)
Che-liang Chiou8732b072013-02-28 09:34:57 +000036{
Miquel Raynalb9804e52018-05-15 11:56:59 +020037 const u8 command[12] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +000038 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
39 };
40 const size_t mode_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +020041 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +000042
43 if (pack_byte_string(buf, sizeof(buf), "sw",
Miquel Raynalc6179182018-05-15 11:57:00 +020044 0, command, sizeof(command),
45 mode_offset, mode))
Che-liang Chiou8732b072013-02-28 09:34:57 +000046 return TPM_LIB_ERROR;
47
Simon Glassabdc7b82018-11-18 14:22:27 -070048 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +000049}
50
Simon Glassd6a885f2021-02-06 14:23:36 -070051u32 tpm1_resume(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -060052{
Simon Glassd6a885f2021-02-06 14:23:36 -070053 return tpm1_startup(dev, TPM_ST_STATE);
Simon Glass6e64ec12018-10-01 12:22:29 -060054}
55
Simon Glassd6a885f2021-02-06 14:23:36 -070056u32 tpm1_self_test_full(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +000057{
Miquel Raynalb9804e52018-05-15 11:56:59 +020058 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +000059 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
60 };
Simon Glassabdc7b82018-11-18 14:22:27 -070061 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +000062}
63
Simon Glassd6a885f2021-02-06 14:23:36 -070064u32 tpm1_continue_self_test(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +000065{
Miquel Raynalb9804e52018-05-15 11:56:59 +020066 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +000067 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
68 };
Simon Glassabdc7b82018-11-18 14:22:27 -070069 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +000070}
71
Simon Glassd6a885f2021-02-06 14:23:36 -070072u32 tpm1_clear_and_reenable(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -060073{
74 u32 ret;
75
76 log_info("TPM: Clear and re-enable\n");
Simon Glassd6a885f2021-02-06 14:23:36 -070077 ret = tpm1_force_clear(dev);
Simon Glass6e64ec12018-10-01 12:22:29 -060078 if (ret != TPM_SUCCESS) {
79 log_err("Can't initiate a force clear\n");
80 return ret;
81 }
82
Simon Glassd6a885f2021-02-06 14:23:36 -070083 ret = tpm1_physical_enable(dev);
84 if (ret != TPM_SUCCESS) {
85 log_err("TPM: Can't set enabled state\n");
86 return ret;
87 }
Simon Glass6e64ec12018-10-01 12:22:29 -060088
Simon Glassd6a885f2021-02-06 14:23:36 -070089 ret = tpm1_physical_set_deactivated(dev, 0);
90 if (ret != TPM_SUCCESS) {
91 log_err("TPM: Can't set deactivated state\n");
92 return ret;
Simon Glass6e64ec12018-10-01 12:22:29 -060093 }
Simon Glass6e64ec12018-10-01 12:22:29 -060094
95 return TPM_SUCCESS;
96}
97
Simon Glassd6a885f2021-02-06 14:23:36 -070098u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
Che-liang Chiou8732b072013-02-28 09:34:57 +000099{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200100 const u8 command[101] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000101 0x0, 0xc1, /* TPM_TAG */
102 0x0, 0x0, 0x0, 0x65, /* parameter size */
103 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
104 /* TPM_NV_DATA_PUBLIC->... */
105 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
106 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
107 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
108 0x0, 0x3,
109 0, 0, 0,
110 0x1f,
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
113 0x0, 0x3,
114 0, 0, 0,
115 0x1f,
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117 /* TPM_NV_ATTRIBUTES->... */
118 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
119 0, 0, 0, 0, /* ...->attributes */
120 /* End of TPM_NV_ATTRIBUTES */
121 0, /* bReadSTClear */
122 0, /* bWriteSTClear */
123 0, /* bWriteDefine */
124 0, 0, 0, 0, /* size */
125 };
126 const size_t index_offset = 12;
127 const size_t perm_offset = 70;
128 const size_t size_offset = 77;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200129 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000130
131 if (pack_byte_string(buf, sizeof(buf), "sddd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200132 0, command, sizeof(command),
133 index_offset, index,
134 perm_offset, perm,
135 size_offset, size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000136 return TPM_LIB_ERROR;
137
Simon Glassabdc7b82018-11-18 14:22:27 -0700138 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000139}
140
Simon Glassd6a885f2021-02-06 14:23:36 -0700141u32 tpm1_nv_set_locked(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -0600142{
Simon Glassd6a885f2021-02-06 14:23:36 -0700143 return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
Simon Glass6e64ec12018-10-01 12:22:29 -0600144}
145
Simon Glassd6a885f2021-02-06 14:23:36 -0700146u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000147{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200148 const u8 command[22] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000149 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
150 };
151 const size_t index_offset = 10;
152 const size_t length_offset = 18;
153 const size_t data_size_offset = 10;
154 const size_t data_offset = 14;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200155 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000156 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200157 u32 data_size;
158 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000159
160 if (pack_byte_string(buf, sizeof(buf), "sdd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200161 0, command, sizeof(command),
162 index_offset, index,
163 length_offset, count))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000164 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700165 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000166 if (err)
167 return err;
168 if (unpack_byte_string(response, response_length, "d",
Miquel Raynalc6179182018-05-15 11:57:00 +0200169 data_size_offset, &data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000170 return TPM_LIB_ERROR;
171 if (data_size > count)
172 return TPM_LIB_ERROR;
173 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200174 data_offset, data, data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000175 return TPM_LIB_ERROR;
176
177 return 0;
178}
179
Simon Glassd6a885f2021-02-06 14:23:36 -0700180u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
181 u32 length)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000182{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200183 const u8 command[256] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000184 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
185 };
186 const size_t command_size_offset = 2;
187 const size_t index_offset = 10;
188 const size_t length_offset = 18;
189 const size_t data_offset = 22;
190 const size_t write_info_size = 12;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200191 const u32 total_length =
Che-liang Chiou8732b072013-02-28 09:34:57 +0000192 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200193 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000194 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200195 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000196
197 if (pack_byte_string(buf, sizeof(buf), "sddds",
Miquel Raynalc6179182018-05-15 11:57:00 +0200198 0, command, sizeof(command),
199 command_size_offset, total_length,
200 index_offset, index,
201 length_offset, length,
202 data_offset, data, length))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000203 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700204 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000205 if (err)
206 return err;
207
208 return 0;
209}
210
Simon Glassd6a885f2021-02-06 14:23:36 -0700211u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
212 void *out_digest)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000213{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200214 const u8 command[34] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000215 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
216 };
217 const size_t index_offset = 10;
218 const size_t in_digest_offset = 14;
219 const size_t out_digest_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200220 u8 buf[COMMAND_BUFFER_SIZE];
221 u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000222 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200223 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000224
225 if (pack_byte_string(buf, sizeof(buf), "sds",
Miquel Raynalc6179182018-05-15 11:57:00 +0200226 0, command, sizeof(command),
227 index_offset, index,
228 in_digest_offset, in_digest,
229 PCR_DIGEST_LENGTH))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000230 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700231 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000232 if (err)
233 return err;
234
235 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200236 out_digest_offset, out_digest,
237 PCR_DIGEST_LENGTH))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000238 return TPM_LIB_ERROR;
239
240 return 0;
241}
242
Simon Glassd6a885f2021-02-06 14:23:36 -0700243u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000244{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200245 const u8 command[14] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000246 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
247 };
248 const size_t index_offset = 10;
249 const size_t out_digest_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200250 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000251 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200252 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000253
254 if (count < PCR_DIGEST_LENGTH)
255 return TPM_LIB_ERROR;
256
257 if (pack_byte_string(buf, sizeof(buf), "sd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200258 0, command, sizeof(command),
259 index_offset, index))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000260 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700261 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000262 if (err)
263 return err;
264 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200265 out_digest_offset, data, PCR_DIGEST_LENGTH))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000266 return TPM_LIB_ERROR;
267
268 return 0;
269}
270
Simon Glassd6a885f2021-02-06 14:23:36 -0700271u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000272{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200273 const u8 command[12] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000274 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
275 };
276 const size_t presence_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200277 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000278
279 if (pack_byte_string(buf, sizeof(buf), "sw",
Miquel Raynalc6179182018-05-15 11:57:00 +0200280 0, command, sizeof(command),
281 presence_offset, presence))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000282 return TPM_LIB_ERROR;
283
Simon Glassabdc7b82018-11-18 14:22:27 -0700284 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000285}
286
Simon Glassd6a885f2021-02-06 14:23:36 -0700287u32 tpm1_finalise_physical_presence(struct udevice *dev)
Simon Glass6e64ec12018-10-01 12:22:29 -0600288{
289 const u8 command[12] = {
290 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
291 };
292
Simon Glassabdc7b82018-11-18 14:22:27 -0700293 return tpm_sendrecv_command(dev, command, NULL, NULL);
Simon Glass6e64ec12018-10-01 12:22:29 -0600294}
295
Simon Glassd6a885f2021-02-06 14:23:36 -0700296u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000297{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200298 const u8 command[30] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000299 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
300 };
301 const size_t response_size_offset = 2;
302 const size_t data_offset = 10;
303 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200304 u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000305 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200306 u32 data_size;
307 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000308
Simon Glassabdc7b82018-11-18 14:22:27 -0700309 err = tpm_sendrecv_command(dev, command, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000310 if (err)
311 return err;
312 if (unpack_byte_string(response, response_length, "d",
Miquel Raynalc6179182018-05-15 11:57:00 +0200313 response_size_offset, &data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000314 return TPM_LIB_ERROR;
315 if (data_size < header_and_checksum_size)
316 return TPM_LIB_ERROR;
317 data_size -= header_and_checksum_size;
318 if (data_size > count)
319 return TPM_LIB_ERROR;
320 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200321 data_offset, data, data_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000322 return TPM_LIB_ERROR;
323
324 return 0;
325}
326
Simon Glassd6a885f2021-02-06 14:23:36 -0700327u32 tpm1_force_clear(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000328{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200329 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000330 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
331 };
332
Simon Glassabdc7b82018-11-18 14:22:27 -0700333 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000334}
335
Simon Glassd6a885f2021-02-06 14:23:36 -0700336u32 tpm1_physical_enable(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000337{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200338 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000339 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
340 };
341
Simon Glassabdc7b82018-11-18 14:22:27 -0700342 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000343}
344
Simon Glassd6a885f2021-02-06 14:23:36 -0700345u32 tpm1_physical_disable(struct udevice *dev)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000346{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200347 const u8 command[10] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000348 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
349 };
350
Simon Glassabdc7b82018-11-18 14:22:27 -0700351 return tpm_sendrecv_command(dev, command, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000352}
353
Simon Glassd6a885f2021-02-06 14:23:36 -0700354u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000355{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200356 const u8 command[11] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000357 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
358 };
359 const size_t state_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200360 u8 buf[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000361
362 if (pack_byte_string(buf, sizeof(buf), "sb",
Miquel Raynalc6179182018-05-15 11:57:00 +0200363 0, command, sizeof(command),
364 state_offset, state))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000365 return TPM_LIB_ERROR;
366
Simon Glassabdc7b82018-11-18 14:22:27 -0700367 return tpm_sendrecv_command(dev, buf, NULL, NULL);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000368}
369
Simon Glassd6a885f2021-02-06 14:23:36 -0700370u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
371 void *cap, size_t count)
Che-liang Chiou8732b072013-02-28 09:34:57 +0000372{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200373 const u8 command[22] = {
Che-liang Chiou8732b072013-02-28 09:34:57 +0000374 0x0, 0xc1, /* TPM_TAG */
375 0x0, 0x0, 0x0, 0x16, /* parameter size */
376 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
377 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
378 0x0, 0x0, 0x0, 0x4, /* subcap size */
379 0x0, 0x0, 0x0, 0x0, /* subcap value */
380 };
381 const size_t cap_area_offset = 10;
382 const size_t sub_cap_offset = 18;
383 const size_t cap_offset = 14;
384 const size_t cap_size_offset = 10;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200385 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Che-liang Chiou8732b072013-02-28 09:34:57 +0000386 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200387 u32 cap_size;
388 u32 err;
Che-liang Chiou8732b072013-02-28 09:34:57 +0000389
390 if (pack_byte_string(buf, sizeof(buf), "sdd",
Miquel Raynalc6179182018-05-15 11:57:00 +0200391 0, command, sizeof(command),
392 cap_area_offset, cap_area,
393 sub_cap_offset, sub_cap))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000394 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700395 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Che-liang Chiou8732b072013-02-28 09:34:57 +0000396 if (err)
397 return err;
398 if (unpack_byte_string(response, response_length, "d",
Miquel Raynalc6179182018-05-15 11:57:00 +0200399 cap_size_offset, &cap_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000400 return TPM_LIB_ERROR;
401 if (cap_size > response_length || cap_size > count)
402 return TPM_LIB_ERROR;
403 if (unpack_byte_string(response, response_length, "s",
Miquel Raynalc6179182018-05-15 11:57:00 +0200404 cap_offset, cap, cap_size))
Che-liang Chiou8732b072013-02-28 09:34:57 +0000405 return TPM_LIB_ERROR;
406
407 return 0;
408}
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200409
Simon Glassd6a885f2021-02-06 14:23:36 -0700410u32 tpm1_get_permanent_flags(struct udevice *dev,
411 struct tpm_permanent_flags *pflags)
Simon Glass2132f972015-08-22 18:31:41 -0600412{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200413 const u8 command[22] = {
Simon Glass2132f972015-08-22 18:31:41 -0600414 0x0, 0xc1, /* TPM_TAG */
415 0x0, 0x0, 0x0, 0x16, /* parameter size */
416 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
417 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
418 0x0, 0x0, 0x0, 0x4, /* subcap size */
419 0x0, 0x0, 0x1, 0x8, /* subcap value */
420 };
André Draszike8155df2017-10-03 16:55:51 +0100421 const size_t data_size_offset = TPM_HEADER_SIZE;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200422 const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
423 u8 response[COMMAND_BUFFER_SIZE];
Simon Glass2132f972015-08-22 18:31:41 -0600424 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200425 u32 err;
426 u32 data_size;
Simon Glass2132f972015-08-22 18:31:41 -0600427
Simon Glassabdc7b82018-11-18 14:22:27 -0700428 err = tpm_sendrecv_command(dev, command, response, &response_length);
Simon Glass2132f972015-08-22 18:31:41 -0600429 if (err)
430 return err;
André Draszike8155df2017-10-03 16:55:51 +0100431 if (unpack_byte_string(response, response_length, "d",
Simon Glass6e64ec12018-10-01 12:22:29 -0600432 data_size_offset, &data_size)) {
433 log_err("Cannot unpack data size\n");
André Draszike8155df2017-10-03 16:55:51 +0100434 return TPM_LIB_ERROR;
Simon Glass6e64ec12018-10-01 12:22:29 -0600435 }
436 if (data_size < sizeof(*pflags)) {
437 log_err("Data size too small\n");
André Draszike8155df2017-10-03 16:55:51 +0100438 return TPM_LIB_ERROR;
Simon Glass6e64ec12018-10-01 12:22:29 -0600439 }
André Draszike8155df2017-10-03 16:55:51 +0100440 if (unpack_byte_string(response, response_length, "s",
Simon Glass6e64ec12018-10-01 12:22:29 -0600441 data_offset, pflags, sizeof(*pflags))) {
442 log_err("Cannot unpack pflags\n");
André Draszike8155df2017-10-03 16:55:51 +0100443 return TPM_LIB_ERROR;
Simon Glass6e64ec12018-10-01 12:22:29 -0600444 }
Simon Glass2132f972015-08-22 18:31:41 -0600445
446 return 0;
447}
448
Simon Glassd6a885f2021-02-06 14:23:36 -0700449u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
Simon Glass2132f972015-08-22 18:31:41 -0600450{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200451 const u8 command[22] = {
Simon Glass2132f972015-08-22 18:31:41 -0600452 0x0, 0xc1, /* TPM_TAG */
453 0x0, 0x0, 0x0, 0x16, /* parameter size */
454 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
455 0x0, 0x0, 0x0, 0x11,
456 0x0, 0x0, 0x0, 0x4,
457 };
458 const size_t index_offset = 18;
Simon Glassa0f38042022-08-30 21:05:33 -0600459 const size_t perm_offset = 74;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200460 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Simon Glass2132f972015-08-22 18:31:41 -0600461 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200462 u32 err;
Simon Glass2132f972015-08-22 18:31:41 -0600463
Simon Glassa0f38042022-08-30 21:05:33 -0600464 if (pack_byte_string(buf, sizeof(buf), "sd",
465 0, command, sizeof(command),
Simon Glass2132f972015-08-22 18:31:41 -0600466 index_offset, index))
467 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700468 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Simon Glass2132f972015-08-22 18:31:41 -0600469 if (err)
470 return err;
471 if (unpack_byte_string(response, response_length, "d",
472 perm_offset, perm))
473 return TPM_LIB_ERROR;
474
475 return 0;
476}
477
Mario Six7690be32017-01-11 16:00:50 +0100478#ifdef CONFIG_TPM_FLUSH_RESOURCES
Simon Glassd6a885f2021-02-06 14:23:36 -0700479u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
Mario Six7690be32017-01-11 16:00:50 +0100480{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200481 const u8 command[18] = {
Mario Six7690be32017-01-11 16:00:50 +0100482 0x00, 0xc1, /* TPM_TAG */
483 0x00, 0x00, 0x00, 0x12, /* parameter size */
484 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
485 0x00, 0x00, 0x00, 0x00, /* key handle */
486 0x00, 0x00, 0x00, 0x00, /* resource type */
487 };
488 const size_t key_handle_offset = 10;
489 const size_t resource_type_offset = 14;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200490 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
Mario Six7690be32017-01-11 16:00:50 +0100491 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200492 u32 err;
Mario Six7690be32017-01-11 16:00:50 +0100493
494 if (pack_byte_string(buf, sizeof(buf), "sdd",
495 0, command, sizeof(command),
496 key_handle_offset, key_handle,
497 resource_type_offset, resource_type))
498 return TPM_LIB_ERROR;
499
Simon Glassabdc7b82018-11-18 14:22:27 -0700500 err = tpm_sendrecv_command(dev, buf, response, &response_length);
Mario Six7690be32017-01-11 16:00:50 +0100501 if (err)
502 return err;
503 return 0;
504}
505#endif /* CONFIG_TPM_FLUSH_RESOURCES */
506
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200507#ifdef CONFIG_TPM_AUTH_SESSIONS
508
509/**
510 * Fill an authentication block in a request.
511 * This func can create the first as well as the second auth block (for
512 * double authorized commands).
513 *
514 * @param request pointer to the request (w/ uninitialised auth data)
515 * @param request_len0 length of the request without auth data
516 * @param handles_len length of the handles area in request
517 * @param auth_session pointer to the (valid) auth session to be used
518 * @param request_auth pointer to the auth block of the request to be filled
519 * @param auth authentication data (HMAC key)
520 */
Miquel Raynalb9804e52018-05-15 11:56:59 +0200521static u32 create_request_auth(const void *request, size_t request_len0,
522 size_t handles_len,
523 struct session_data *auth_session,
524 void *request_auth, const void *auth)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200525{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200526 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200527 sha1_context hash_ctx;
528 const size_t command_code_offset = 6;
529 const size_t auth_nonce_odd_offset = 4;
530 const size_t auth_continue_offset = 24;
531 const size_t auth_auth_offset = 25;
532
533 if (!auth_session || !auth_session->valid)
534 return TPM_LIB_ERROR;
535
536 sha1_starts(&hash_ctx);
537 sha1_update(&hash_ctx, request + command_code_offset, 4);
538 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
539 sha1_update(&hash_ctx,
540 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
541 request_len0 - TPM_REQUEST_HEADER_LENGTH
542 - handles_len);
543 sha1_finish(&hash_ctx, hmac_data);
544
545 sha1_starts(&hash_ctx);
546 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
547 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
548 sha1_finish(&hash_ctx, auth_session->nonce_odd);
549
550 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
551 0, auth_session->handle,
552 auth_nonce_odd_offset, auth_session->nonce_odd,
553 DIGEST_LENGTH,
554 auth_continue_offset, 1))
555 return TPM_LIB_ERROR;
556 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
557 DIGEST_LENGTH,
558 auth_session->nonce_even,
559 DIGEST_LENGTH,
560 2 * DIGEST_LENGTH,
561 request_auth + auth_nonce_odd_offset,
562 DIGEST_LENGTH + 1))
563 return TPM_LIB_ERROR;
564 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
565 request_auth + auth_auth_offset);
566
567 return TPM_SUCCESS;
568}
569
570/**
571 * Verify an authentication block in a response.
572 * Since this func updates the nonce_even in the session data it has to be
573 * called when receiving a succesfull AUTH response.
574 * This func can verify the first as well as the second auth block (for
575 * double authorized commands).
576 *
577 * @param command_code command code of the request
578 * @param response pointer to the request (w/ uninitialised auth data)
579 * @param handles_len length of the handles area in response
580 * @param auth_session pointer to the (valid) auth session to be used
581 * @param response_auth pointer to the auth block of the response to be verified
582 * @param auth authentication data (HMAC key)
583 */
Miquel Raynalb9804e52018-05-15 11:56:59 +0200584static u32 verify_response_auth(u32 command_code, const void *response,
585 size_t response_len0, size_t handles_len,
586 struct session_data *auth_session,
587 const void *response_auth, const void *auth)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200588{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200589 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
590 u8 computed_auth[DIGEST_LENGTH];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200591 sha1_context hash_ctx;
592 const size_t return_code_offset = 6;
593 const size_t auth_continue_offset = 20;
594 const size_t auth_auth_offset = 21;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200595 u8 auth_continue;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200596
597 if (!auth_session || !auth_session->valid)
598 return TPM_AUTHFAIL;
599 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
600 0, command_code))
601 return TPM_LIB_ERROR;
602 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
603 return TPM_LIB_ERROR;
604
605 sha1_starts(&hash_ctx);
606 sha1_update(&hash_ctx, response + return_code_offset, 4);
607 sha1_update(&hash_ctx, hmac_data, 4);
608 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
609 sha1_update(&hash_ctx,
610 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
611 response_len0 - TPM_RESPONSE_HEADER_LENGTH
612 - handles_len);
613 sha1_finish(&hash_ctx, hmac_data);
614
615 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200616 auth_continue = ((u8 *)response_auth)[auth_continue_offset];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200617 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
618 DIGEST_LENGTH,
619 response_auth,
620 DIGEST_LENGTH,
621 2 * DIGEST_LENGTH,
622 auth_session->nonce_odd,
623 DIGEST_LENGTH,
624 3 * DIGEST_LENGTH,
625 auth_continue))
626 return TPM_LIB_ERROR;
627
628 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
629 computed_auth);
630
631 if (memcmp(computed_auth, response_auth + auth_auth_offset,
632 DIGEST_LENGTH))
633 return TPM_AUTHFAIL;
634
635 return TPM_SUCCESS;
636}
637
Simon Glassd6a885f2021-02-06 14:23:36 -0700638u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200639{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200640 const u8 command[18] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200641 0x00, 0xc1, /* TPM_TAG */
642 0x00, 0x00, 0x00, 0x00, /* parameter size */
643 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
644 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
Miquel Raynal52da18a2018-05-15 11:57:02 +0200645 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200646 };
647 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200648 u8 request[COMMAND_BUFFER_SIZE];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200649
650 if (pack_byte_string(request, sizeof(request), "sd",
651 0, command, sizeof(command),
652 req_handle_offset, auth_handle))
653 return TPM_LIB_ERROR;
654 if (oiap_session.valid && oiap_session.handle == auth_handle)
655 oiap_session.valid = 0;
656
Simon Glassabdc7b82018-11-18 14:22:27 -0700657 return tpm_sendrecv_command(dev, request, NULL, NULL);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200658}
659
Simon Glassd6a885f2021-02-06 14:23:36 -0700660u32 tpm1_end_oiap(struct udevice *dev)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200661{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200662 u32 err = TPM_SUCCESS;
Miquel Raynal96cc4e32018-05-15 11:57:03 +0200663
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200664 if (oiap_session.valid)
Simon Glassd6a885f2021-02-06 14:23:36 -0700665 err = tpm1_terminate_auth_session(dev, oiap_session.handle);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200666 return err;
667}
668
Simon Glassd6a885f2021-02-06 14:23:36 -0700669u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200670{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200671 const u8 command[10] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200672 0x00, 0xc1, /* TPM_TAG */
673 0x00, 0x00, 0x00, 0x0a, /* parameter size */
674 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
675 };
676 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
677 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200678 u8 response[COMMAND_BUFFER_SIZE];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200679 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200680 u32 err;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200681
682 if (oiap_session.valid)
Simon Glassd6a885f2021-02-06 14:23:36 -0700683 tpm1_terminate_auth_session(dev, oiap_session.handle);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200684
Simon Glassabdc7b82018-11-18 14:22:27 -0700685 err = tpm_sendrecv_command(dev, command, response, &response_length);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200686 if (err)
687 return err;
688 if (unpack_byte_string(response, response_length, "ds",
689 res_auth_handle_offset, &oiap_session.handle,
690 res_nonce_even_offset, &oiap_session.nonce_even,
Miquel Raynalb9804e52018-05-15 11:56:59 +0200691 (u32)DIGEST_LENGTH))
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200692 return TPM_LIB_ERROR;
693 oiap_session.valid = 1;
694 if (auth_handle)
695 *auth_handle = oiap_session.handle;
696 return 0;
697}
698
Simon Glassd6a885f2021-02-06 14:23:36 -0700699u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
700 size_t key_length, const void *parent_key_usage_auth,
701 u32 *key_handle)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200702{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200703 const u8 command[14] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200704 0x00, 0xc2, /* TPM_TAG */
705 0x00, 0x00, 0x00, 0x00, /* parameter size */
706 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
707 0x00, 0x00, 0x00, 0x00, /* parent handle */
708 };
709 const size_t req_size_offset = 2;
710 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
711 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
712 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200713 u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
714 TPM_REQUEST_AUTH_LENGTH];
715 u8 response[COMMAND_BUFFER_SIZE];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200716 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200717 u32 err;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200718
719 if (!oiap_session.valid) {
Simon Glassd6a885f2021-02-06 14:23:36 -0700720 err = tpm1_oiap(dev, NULL);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200721 if (err)
722 return err;
723 }
724 if (pack_byte_string(request, sizeof(request), "sdds",
725 0, command, sizeof(command),
726 req_size_offset,
727 sizeof(command) + key_length
728 + TPM_REQUEST_AUTH_LENGTH,
729 req_parent_handle_offset, parent_handle,
730 req_key_offset, key, key_length
731 ))
732 return TPM_LIB_ERROR;
733
734 err = create_request_auth(request, sizeof(command) + key_length, 4,
Miquel Raynalc6179182018-05-15 11:57:00 +0200735 &oiap_session,
736 request + sizeof(command) + key_length,
737 parent_key_usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200738 if (err)
739 return err;
Simon Glassabdc7b82018-11-18 14:22:27 -0700740 err = tpm_sendrecv_command(dev, request, response, &response_length);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200741 if (err) {
742 if (err == TPM_AUTHFAIL)
743 oiap_session.valid = 0;
744 return err;
745 }
746
747 err = verify_response_auth(0x00000041, response,
Miquel Raynalc6179182018-05-15 11:57:00 +0200748 response_length - TPM_RESPONSE_AUTH_LENGTH,
749 4, &oiap_session,
750 response + response_length -
751 TPM_RESPONSE_AUTH_LENGTH,
752 parent_key_usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200753 if (err)
754 return err;
755
756 if (key_handle) {
757 if (unpack_byte_string(response, response_length, "d",
758 res_handle_offset, key_handle))
759 return TPM_LIB_ERROR;
760 }
761
762 return 0;
763}
764
Simon Glassd6a885f2021-02-06 14:23:36 -0700765u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
766 const void *usage_auth, void *pubkey,
767 size_t *pubkey_len)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200768{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200769 const u8 command[14] = {
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200770 0x00, 0xc2, /* TPM_TAG */
771 0x00, 0x00, 0x00, 0x00, /* parameter size */
772 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
773 0x00, 0x00, 0x00, 0x00, /* key handle */
774 };
775 const size_t req_size_offset = 2;
776 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
777 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200778 u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
779 u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
780 TPM_RESPONSE_AUTH_LENGTH];
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200781 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200782 u32 err;
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200783
784 if (!oiap_session.valid) {
Simon Glassd6a885f2021-02-06 14:23:36 -0700785 err = tpm1_oiap(dev, NULL);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200786 if (err)
787 return err;
788 }
789 if (pack_byte_string(request, sizeof(request), "sdd",
790 0, command, sizeof(command),
791 req_size_offset,
Miquel Raynalb9804e52018-05-15 11:56:59 +0200792 (u32)(sizeof(command)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200793 + TPM_REQUEST_AUTH_LENGTH),
794 req_key_handle_offset, key_handle
795 ))
796 return TPM_LIB_ERROR;
797 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
Miquel Raynalc6179182018-05-15 11:57:00 +0200798 request + sizeof(command), usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200799 if (err)
800 return err;
Simon Glassabdc7b82018-11-18 14:22:27 -0700801 err = tpm_sendrecv_command(dev, request, response, &response_length);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200802 if (err) {
803 if (err == TPM_AUTHFAIL)
804 oiap_session.valid = 0;
805 return err;
806 }
807 err = verify_response_auth(0x00000021, response,
Miquel Raynalc6179182018-05-15 11:57:00 +0200808 response_length - TPM_RESPONSE_AUTH_LENGTH,
809 0, &oiap_session,
810 response + response_length -
811 TPM_RESPONSE_AUTH_LENGTH,
812 usage_auth);
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200813 if (err)
814 return err;
815
816 if (pubkey) {
817 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
Miquel Raynalc6179182018-05-15 11:57:00 +0200818 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200819 return TPM_LIB_ERROR;
820 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
821 - TPM_RESPONSE_AUTH_LENGTH;
822 memcpy(pubkey, response + res_pubkey_offset,
823 response_length - TPM_RESPONSE_HEADER_LENGTH
824 - TPM_RESPONSE_AUTH_LENGTH);
825 }
826
827 return 0;
828}
829
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100830#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
Simon Glassd6a885f2021-02-06 14:23:36 -0700831u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
832 const u8 pubkey_digest[20], u32 *handle)
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100833{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200834 u16 key_count;
835 u32 key_handles[10];
836 u8 buf[288];
837 u8 *ptr;
838 u32 err;
839 u8 digest[20];
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100840 size_t buf_len;
841 unsigned int i;
842
843 /* fetch list of already loaded keys in the TPM */
Mathew McBridee845dd72021-11-11 04:06:27 +0000844 err = tpm1_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
Simon Glassabdc7b82018-11-18 14:22:27 -0700845 sizeof(buf));
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100846 if (err)
847 return -1;
848 key_count = get_unaligned_be16(buf);
849 ptr = buf + 2;
850 for (i = 0; i < key_count; ++i, ptr += 4)
851 key_handles[i] = get_unaligned_be32(ptr);
852
853 /* now search a(/ the) key which we can access with the given auth */
854 for (i = 0; i < key_count; ++i) {
855 buf_len = sizeof(buf);
Mathew McBridee845dd72021-11-11 04:06:27 +0000856 err = tpm1_get_pub_key_oiap(dev, key_handles[i], auth, buf, &buf_len);
mario.six@gdsys.cc0f4b2ba2017-03-20 10:28:28 +0100857 if (err && err != TPM_AUTHFAIL)
858 return -1;
859 if (err)
860 continue;
861 sha1_csum(buf, buf_len, digest);
862 if (!memcmp(digest, pubkey_digest, 20)) {
863 *handle = key_handles[i];
864 return 0;
865 }
866 }
867 return 1;
868}
869#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
870
Reinhard Pfaube6c1522013-06-26 15:55:13 +0200871#endif /* CONFIG_TPM_AUTH_SESSIONS */
André Draszik3c605022017-10-03 16:55:52 +0100872
Simon Glassd6a885f2021-02-06 14:23:36 -0700873u32 tpm1_get_random(struct udevice *dev, void *data, u32 count)
André Draszik3c605022017-10-03 16:55:52 +0100874{
Miquel Raynalb9804e52018-05-15 11:56:59 +0200875 const u8 command[14] = {
André Draszik3c605022017-10-03 16:55:52 +0100876 0x0, 0xc1, /* TPM_TAG */
877 0x0, 0x0, 0x0, 0xe, /* parameter size */
878 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
879 };
880 const size_t length_offset = 10;
881 const size_t data_size_offset = 10;
882 const size_t data_offset = 14;
Miquel Raynalb9804e52018-05-15 11:56:59 +0200883 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
André Draszik3c605022017-10-03 16:55:52 +0100884 size_t response_length = sizeof(response);
Miquel Raynalb9804e52018-05-15 11:56:59 +0200885 u32 data_size;
886 u8 *out = data;
André Draszik3c605022017-10-03 16:55:52 +0100887
888 while (count > 0) {
Miquel Raynalb9804e52018-05-15 11:56:59 +0200889 u32 this_bytes = min((size_t)count,
890 sizeof(response) - data_offset);
891 u32 err;
André Draszik3c605022017-10-03 16:55:52 +0100892
893 if (pack_byte_string(buf, sizeof(buf), "sd",
894 0, command, sizeof(command),
895 length_offset, this_bytes))
896 return TPM_LIB_ERROR;
Simon Glassabdc7b82018-11-18 14:22:27 -0700897 err = tpm_sendrecv_command(dev, buf, response,
898 &response_length);
André Draszik3c605022017-10-03 16:55:52 +0100899 if (err)
900 return err;
901 if (unpack_byte_string(response, response_length, "d",
902 data_size_offset, &data_size))
903 return TPM_LIB_ERROR;
904 if (data_size > count)
905 return TPM_LIB_ERROR;
906 if (unpack_byte_string(response, response_length, "s",
907 data_offset, out, data_size))
908 return TPM_LIB_ERROR;
909
910 count -= data_size;
911 out += data_size;
912 }
913
914 return 0;
915}