Blame view

lib/tpm-v1.c 25.7 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
2
3
  /*
   * Copyright (c) 2013 The Chromium OS Authors.
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
4
   * Coypright (c) 2013 Guntermann & Drunck GmbH
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
5
   */
6e64ec125   Simon Glass   tpm: Add a few ne...
6
  #define LOG_CATEGORY UCLASS_TPM
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
7
  #include <common.h>
c8a8c5103   Simon Glass   dm: tpm: Convert ...
8
  #include <dm.h>
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
9
  #include <asm/unaligned.h>
c8a8c5103   Simon Glass   dm: tpm: Convert ...
10
  #include <u-boot/sha1.h>
d677bfe2f   Miquel Raynal   tpm: disociate TP...
11
12
13
  #include <tpm-common.h>
  #include <tpm-v1.h>
  #include "tpm-utils.h"
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
14

be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
15
16
17
18
19
20
21
22
  #ifdef CONFIG_TPM_AUTH_SESSIONS
  
  #ifndef CONFIG_SHA1
  #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
  #endif /* !CONFIG_SHA1 */
  
  struct session_data {
  	int		valid;
b9804e5bf   Miquel Raynal   tpm: substitute d...
23
24
25
  	u32	handle;
  	u8		nonce_even[DIGEST_LENGTH];
  	u8		nonce_odd[DIGEST_LENGTH];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
26
27
28
29
30
  };
  
  static struct session_data oiap_session = {0, };
  
  #endif /* CONFIG_TPM_AUTH_SESSIONS */
abdc7b8a2   Simon Glass   tpm: Convert to u...
31
  u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
32
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
33
  	const u8 command[12] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
34
35
36
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
  	};
  	const size_t mode_offset = 10;
b9804e5bf   Miquel Raynal   tpm: substitute d...
37
  	u8 buf[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
38
39
  
  	if (pack_byte_string(buf, sizeof(buf), "sw",
c61791876   Miquel Raynal   tpm: align argume...
40
41
  			     0, command, sizeof(command),
  			     mode_offset, mode))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
42
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
43
  	return tpm_sendrecv_command(dev, buf, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
44
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
45
  u32 tpm_resume(struct udevice *dev)
6e64ec125   Simon Glass   tpm: Add a few ne...
46
  {
abdc7b8a2   Simon Glass   tpm: Convert to u...
47
  	return tpm_startup(dev, TPM_ST_STATE);
6e64ec125   Simon Glass   tpm: Add a few ne...
48
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
49
  u32 tpm_self_test_full(struct udevice *dev)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
50
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
51
  	const u8 command[10] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
52
53
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
  	};
abdc7b8a2   Simon Glass   tpm: Convert to u...
54
  	return tpm_sendrecv_command(dev, command, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
55
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
56
  u32 tpm_continue_self_test(struct udevice *dev)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
57
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
58
  	const u8 command[10] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
59
60
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
  	};
abdc7b8a2   Simon Glass   tpm: Convert to u...
61
  	return tpm_sendrecv_command(dev, command, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
62
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
63
  u32 tpm_clear_and_reenable(struct udevice *dev)
6e64ec125   Simon Glass   tpm: Add a few ne...
64
65
66
67
68
  {
  	u32 ret;
  
  	log_info("TPM: Clear and re-enable
  ");
abdc7b8a2   Simon Glass   tpm: Convert to u...
69
  	ret = tpm_force_clear(dev);
6e64ec125   Simon Glass   tpm: Add a few ne...
70
71
72
73
74
  	if (ret != TPM_SUCCESS) {
  		log_err("Can't initiate a force clear
  ");
  		return ret;
  	}
0a60a0a65   Simon Glass   tpm: Remove use o...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  	if (tpm_get_version(dev) == TPM_V1) {
  		ret = tpm_physical_enable(dev);
  		if (ret != TPM_SUCCESS) {
  			log_err("TPM: Can't set enabled state
  ");
  			return ret;
  		}
  
  		ret = tpm_physical_set_deactivated(dev, 0);
  		if (ret != TPM_SUCCESS) {
  			log_err("TPM: Can't set deactivated state
  ");
  			return ret;
  		}
6e64ec125   Simon Glass   tpm: Add a few ne...
89
  	}
6e64ec125   Simon Glass   tpm: Add a few ne...
90
91
92
  
  	return TPM_SUCCESS;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
93
  u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
94
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
95
  	const u8 command[101] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  		0x0, 0xc1,		/* TPM_TAG */
  		0x0, 0x0, 0x0, 0x65,	/* parameter size */
  		0x0, 0x0, 0x0, 0xcc,	/* TPM_COMMAND_CODE */
  		/* TPM_NV_DATA_PUBLIC->... */
  		0x0, 0x18,		/* ...->TPM_STRUCTURE_TAG */
  		0, 0, 0, 0,		/* ...->TPM_NV_INDEX */
  		/* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
  		0x0, 0x3,
  		0, 0, 0,
  		0x1f,
  		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  		/* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
  		0x0, 0x3,
  		0, 0, 0,
  		0x1f,
  		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  		/* TPM_NV_ATTRIBUTES->... */
  		0x0, 0x17,		/* ...->TPM_STRUCTURE_TAG */
  		0, 0, 0, 0,		/* ...->attributes */
  		/* End of TPM_NV_ATTRIBUTES */
  		0,			/* bReadSTClear */
  		0,			/* bWriteSTClear */
  		0,			/* bWriteDefine */
  		0, 0, 0, 0,		/* size */
  	};
  	const size_t index_offset = 12;
  	const size_t perm_offset = 70;
  	const size_t size_offset = 77;
b9804e5bf   Miquel Raynal   tpm: substitute d...
124
  	u8 buf[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
125
126
  
  	if (pack_byte_string(buf, sizeof(buf), "sddd",
c61791876   Miquel Raynal   tpm: align argume...
127
128
129
130
  			     0, command, sizeof(command),
  			     index_offset, index,
  			     perm_offset, perm,
  			     size_offset, size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
131
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
132
  	return tpm_sendrecv_command(dev, buf, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
133
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
134
  u32 tpm_nv_set_locked(struct udevice *dev)
6e64ec125   Simon Glass   tpm: Add a few ne...
135
  {
abdc7b8a2   Simon Glass   tpm: Convert to u...
136
  	return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
6e64ec125   Simon Glass   tpm: Add a few ne...
137
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
138
  u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
139
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
140
  	const u8 command[22] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
141
142
143
144
145
146
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
  	};
  	const size_t index_offset = 10;
  	const size_t length_offset = 18;
  	const size_t data_size_offset = 10;
  	const size_t data_offset = 14;
b9804e5bf   Miquel Raynal   tpm: substitute d...
147
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
148
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
149
150
  	u32 data_size;
  	u32 err;
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
151
152
  
  	if (pack_byte_string(buf, sizeof(buf), "sdd",
c61791876   Miquel Raynal   tpm: align argume...
153
154
155
  			     0, command, sizeof(command),
  			     index_offset, index,
  			     length_offset, count))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
156
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
157
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
158
159
160
  	if (err)
  		return err;
  	if (unpack_byte_string(response, response_length, "d",
c61791876   Miquel Raynal   tpm: align argume...
161
  			       data_size_offset, &data_size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
162
163
164
165
  		return TPM_LIB_ERROR;
  	if (data_size > count)
  		return TPM_LIB_ERROR;
  	if (unpack_byte_string(response, response_length, "s",
c61791876   Miquel Raynal   tpm: align argume...
166
  			       data_offset, data, data_size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
167
168
169
170
  		return TPM_LIB_ERROR;
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
171
172
  u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
  		       u32 length)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
173
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
174
  	const u8 command[256] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
175
176
177
178
179
180
181
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
  	};
  	const size_t command_size_offset = 2;
  	const size_t index_offset = 10;
  	const size_t length_offset = 18;
  	const size_t data_offset = 22;
  	const size_t write_info_size = 12;
b9804e5bf   Miquel Raynal   tpm: substitute d...
182
  	const u32 total_length =
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
183
  		TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
b9804e5bf   Miquel Raynal   tpm: substitute d...
184
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
185
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
186
  	u32 err;
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
187
188
  
  	if (pack_byte_string(buf, sizeof(buf), "sddds",
c61791876   Miquel Raynal   tpm: align argume...
189
190
191
192
193
  			     0, command, sizeof(command),
  			     command_size_offset, total_length,
  			     index_offset, index,
  			     length_offset, length,
  			     data_offset, data, length))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
194
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
195
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
196
197
198
199
200
  	if (err)
  		return err;
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
201
  uint32_t tpm_set_global_lock(struct udevice *dev)
6e64ec125   Simon Glass   tpm: Add a few ne...
202
  {
c7cd4afb9   Heinrich Schuchardt   tpm: simplify: tp...
203
  	return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
6e64ec125   Simon Glass   tpm: Add a few ne...
204
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
205
206
  u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
  	       void *out_digest)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
207
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
208
  	const u8 command[34] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
209
210
211
212
213
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
  	};
  	const size_t index_offset = 10;
  	const size_t in_digest_offset = 14;
  	const size_t out_digest_offset = 10;
b9804e5bf   Miquel Raynal   tpm: substitute d...
214
215
  	u8 buf[COMMAND_BUFFER_SIZE];
  	u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
216
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
217
  	u32 err;
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
218
219
  
  	if (pack_byte_string(buf, sizeof(buf), "sds",
c61791876   Miquel Raynal   tpm: align argume...
220
221
222
223
  			     0, command, sizeof(command),
  			     index_offset, index,
  			     in_digest_offset, in_digest,
  			     PCR_DIGEST_LENGTH))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
224
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
225
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
226
227
228
229
  	if (err)
  		return err;
  
  	if (unpack_byte_string(response, response_length, "s",
c61791876   Miquel Raynal   tpm: align argume...
230
231
  			       out_digest_offset, out_digest,
  			       PCR_DIGEST_LENGTH))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
232
233
234
235
  		return TPM_LIB_ERROR;
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
236
  u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
237
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
238
  	const u8 command[14] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
239
240
241
242
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
  	};
  	const size_t index_offset = 10;
  	const size_t out_digest_offset = 10;
b9804e5bf   Miquel Raynal   tpm: substitute d...
243
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
244
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
245
  	u32 err;
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
246
247
248
249
250
  
  	if (count < PCR_DIGEST_LENGTH)
  		return TPM_LIB_ERROR;
  
  	if (pack_byte_string(buf, sizeof(buf), "sd",
c61791876   Miquel Raynal   tpm: align argume...
251
252
  			     0, command, sizeof(command),
  			     index_offset, index))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
253
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
254
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
255
256
257
  	if (err)
  		return err;
  	if (unpack_byte_string(response, response_length, "s",
c61791876   Miquel Raynal   tpm: align argume...
258
  			       out_digest_offset, data, PCR_DIGEST_LENGTH))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
259
260
261
262
  		return TPM_LIB_ERROR;
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
263
  u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
264
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
265
  	const u8 command[12] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
266
267
268
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
  	};
  	const size_t presence_offset = 10;
b9804e5bf   Miquel Raynal   tpm: substitute d...
269
  	u8 buf[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
270
271
  
  	if (pack_byte_string(buf, sizeof(buf), "sw",
c61791876   Miquel Raynal   tpm: align argume...
272
273
  			     0, command, sizeof(command),
  			     presence_offset, presence))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
274
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
275
  	return tpm_sendrecv_command(dev, buf, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
276
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
277
  u32 tpm_finalise_physical_presence(struct udevice *dev)
6e64ec125   Simon Glass   tpm: Add a few ne...
278
279
280
281
  {
  	const u8 command[12] = {
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
  	};
abdc7b8a2   Simon Glass   tpm: Convert to u...
282
  	return tpm_sendrecv_command(dev, command, NULL, NULL);
6e64ec125   Simon Glass   tpm: Add a few ne...
283
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
284
  u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
285
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
286
  	const u8 command[30] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
287
288
289
290
291
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
  	};
  	const size_t response_size_offset = 2;
  	const size_t data_offset = 10;
  	const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
b9804e5bf   Miquel Raynal   tpm: substitute d...
292
  	u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
293
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
294
295
  	u32 data_size;
  	u32 err;
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
296

abdc7b8a2   Simon Glass   tpm: Convert to u...
297
  	err = tpm_sendrecv_command(dev, command, response, &response_length);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
298
299
300
  	if (err)
  		return err;
  	if (unpack_byte_string(response, response_length, "d",
c61791876   Miquel Raynal   tpm: align argume...
301
  			       response_size_offset, &data_size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
302
303
304
305
306
307
308
  		return TPM_LIB_ERROR;
  	if (data_size < header_and_checksum_size)
  		return TPM_LIB_ERROR;
  	data_size -= header_and_checksum_size;
  	if (data_size > count)
  		return TPM_LIB_ERROR;
  	if (unpack_byte_string(response, response_length, "s",
c61791876   Miquel Raynal   tpm: align argume...
309
  			       data_offset, data, data_size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
310
311
312
313
  		return TPM_LIB_ERROR;
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
314
  u32 tpm_force_clear(struct udevice *dev)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
315
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
316
  	const u8 command[10] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
317
318
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
  	};
abdc7b8a2   Simon Glass   tpm: Convert to u...
319
  	return tpm_sendrecv_command(dev, command, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
320
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
321
  u32 tpm_physical_enable(struct udevice *dev)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
322
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
323
  	const u8 command[10] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
324
325
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
  	};
abdc7b8a2   Simon Glass   tpm: Convert to u...
326
  	return tpm_sendrecv_command(dev, command, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
327
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
328
  u32 tpm_physical_disable(struct udevice *dev)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
329
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
330
  	const u8 command[10] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
331
332
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
  	};
abdc7b8a2   Simon Glass   tpm: Convert to u...
333
  	return tpm_sendrecv_command(dev, command, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
334
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
335
  u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
336
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
337
  	const u8 command[11] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
338
339
340
  		0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
  	};
  	const size_t state_offset = 10;
b9804e5bf   Miquel Raynal   tpm: substitute d...
341
  	u8 buf[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
342
343
  
  	if (pack_byte_string(buf, sizeof(buf), "sb",
c61791876   Miquel Raynal   tpm: align argume...
344
345
  			     0, command, sizeof(command),
  			     state_offset, state))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
346
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
347
  	return tpm_sendrecv_command(dev, buf, NULL, NULL);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
348
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
349
350
  u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
  		       void *cap, size_t count)
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
351
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
352
  	const u8 command[22] = {
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
353
354
355
356
357
358
359
360
361
362
363
  		0x0, 0xc1,		/* TPM_TAG */
  		0x0, 0x0, 0x0, 0x16,	/* parameter size */
  		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
  		0x0, 0x0, 0x0, 0x0,	/* TPM_CAPABILITY_AREA */
  		0x0, 0x0, 0x0, 0x4,	/* subcap size */
  		0x0, 0x0, 0x0, 0x0,	/* subcap value */
  	};
  	const size_t cap_area_offset = 10;
  	const size_t sub_cap_offset = 18;
  	const size_t cap_offset = 14;
  	const size_t cap_size_offset = 10;
b9804e5bf   Miquel Raynal   tpm: substitute d...
364
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
365
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
366
367
  	u32 cap_size;
  	u32 err;
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
368
369
  
  	if (pack_byte_string(buf, sizeof(buf), "sdd",
c61791876   Miquel Raynal   tpm: align argume...
370
371
372
  			     0, command, sizeof(command),
  			     cap_area_offset, cap_area,
  			     sub_cap_offset, sub_cap))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
373
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
374
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
375
376
377
  	if (err)
  		return err;
  	if (unpack_byte_string(response, response_length, "d",
c61791876   Miquel Raynal   tpm: align argume...
378
  			       cap_size_offset, &cap_size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
379
380
381
382
  		return TPM_LIB_ERROR;
  	if (cap_size > response_length || cap_size > count)
  		return TPM_LIB_ERROR;
  	if (unpack_byte_string(response, response_length, "s",
c61791876   Miquel Raynal   tpm: align argume...
383
  			       cap_offset, cap, cap_size))
8732b0700   Che-liang Chiou   tpm: Add TPM comm...
384
385
386
387
  		return TPM_LIB_ERROR;
  
  	return 0;
  }
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
388

abdc7b8a2   Simon Glass   tpm: Convert to u...
389
390
  u32 tpm_get_permanent_flags(struct udevice *dev,
  			    struct tpm_permanent_flags *pflags)
2132f971b   Simon Glass   tpm: Add function...
391
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
392
  	const u8 command[22] = {
2132f971b   Simon Glass   tpm: Add function...
393
394
395
396
397
398
399
  		0x0, 0xc1,		/* TPM_TAG */
  		0x0, 0x0, 0x0, 0x16,	/* parameter size */
  		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
  		0x0, 0x0, 0x0, 0x4,	/* TPM_CAP_FLAG_PERM */
  		0x0, 0x0, 0x0, 0x4,	/* subcap size */
  		0x0, 0x0, 0x1, 0x8,	/* subcap value */
  	};
e8155dfe3   André Draszik   tpm: fix reading ...
400
  	const size_t data_size_offset = TPM_HEADER_SIZE;
b9804e5bf   Miquel Raynal   tpm: substitute d...
401
402
  	const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
  	u8 response[COMMAND_BUFFER_SIZE];
2132f971b   Simon Glass   tpm: Add function...
403
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
404
405
  	u32 err;
  	u32 data_size;
2132f971b   Simon Glass   tpm: Add function...
406

abdc7b8a2   Simon Glass   tpm: Convert to u...
407
  	err = tpm_sendrecv_command(dev, command, response, &response_length);
2132f971b   Simon Glass   tpm: Add function...
408
409
  	if (err)
  		return err;
e8155dfe3   André Draszik   tpm: fix reading ...
410
  	if (unpack_byte_string(response, response_length, "d",
6e64ec125   Simon Glass   tpm: Add a few ne...
411
412
413
  			       data_size_offset, &data_size)) {
  		log_err("Cannot unpack data size
  ");
e8155dfe3   André Draszik   tpm: fix reading ...
414
  		return TPM_LIB_ERROR;
6e64ec125   Simon Glass   tpm: Add a few ne...
415
416
417
418
  	}
  	if (data_size < sizeof(*pflags)) {
  		log_err("Data size too small
  ");
e8155dfe3   André Draszik   tpm: fix reading ...
419
  		return TPM_LIB_ERROR;
6e64ec125   Simon Glass   tpm: Add a few ne...
420
  	}
e8155dfe3   André Draszik   tpm: fix reading ...
421
  	if (unpack_byte_string(response, response_length, "s",
6e64ec125   Simon Glass   tpm: Add a few ne...
422
423
424
  			       data_offset, pflags, sizeof(*pflags))) {
  		log_err("Cannot unpack pflags
  ");
e8155dfe3   André Draszik   tpm: fix reading ...
425
  		return TPM_LIB_ERROR;
6e64ec125   Simon Glass   tpm: Add a few ne...
426
  	}
2132f971b   Simon Glass   tpm: Add function...
427
428
429
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
430
  u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
2132f971b   Simon Glass   tpm: Add function...
431
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
432
  	const u8 command[22] = {
2132f971b   Simon Glass   tpm: Add function...
433
434
435
436
437
438
439
440
  		0x0, 0xc1,		/* TPM_TAG */
  		0x0, 0x0, 0x0, 0x16,	/* parameter size */
  		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
  		0x0, 0x0, 0x0, 0x11,
  		0x0, 0x0, 0x0, 0x4,
  	};
  	const size_t index_offset = 18;
  	const size_t perm_offset = 60;
b9804e5bf   Miquel Raynal   tpm: substitute d...
441
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
2132f971b   Simon Glass   tpm: Add function...
442
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
443
  	u32 err;
2132f971b   Simon Glass   tpm: Add function...
444
445
446
447
  
  	if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
  			     index_offset, index))
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
448
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
2132f971b   Simon Glass   tpm: Add function...
449
450
451
452
453
454
455
456
  	if (err)
  		return err;
  	if (unpack_byte_string(response, response_length, "d",
  			       perm_offset, perm))
  		return TPM_LIB_ERROR;
  
  	return 0;
  }
7690be35d   Mario Six   lib: tpm: Add com...
457
  #ifdef CONFIG_TPM_FLUSH_RESOURCES
abdc7b8a2   Simon Glass   tpm: Convert to u...
458
  u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
7690be35d   Mario Six   lib: tpm: Add com...
459
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
460
  	const u8 command[18] = {
7690be35d   Mario Six   lib: tpm: Add com...
461
462
463
464
465
466
467
468
  		0x00, 0xc1,             /* TPM_TAG */
  		0x00, 0x00, 0x00, 0x12, /* parameter size */
  		0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
  		0x00, 0x00, 0x00, 0x00, /* key handle */
  		0x00, 0x00, 0x00, 0x00, /* resource type */
  	};
  	const size_t key_handle_offset = 10;
  	const size_t resource_type_offset = 14;
b9804e5bf   Miquel Raynal   tpm: substitute d...
469
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
7690be35d   Mario Six   lib: tpm: Add com...
470
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
471
  	u32 err;
7690be35d   Mario Six   lib: tpm: Add com...
472
473
474
475
476
477
  
  	if (pack_byte_string(buf, sizeof(buf), "sdd",
  			     0, command, sizeof(command),
  			     key_handle_offset, key_handle,
  			     resource_type_offset, resource_type))
  		return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
478
  	err = tpm_sendrecv_command(dev, buf, response, &response_length);
7690be35d   Mario Six   lib: tpm: Add com...
479
480
481
482
483
  	if (err)
  		return err;
  	return 0;
  }
  #endif /* CONFIG_TPM_FLUSH_RESOURCES */
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  #ifdef CONFIG_TPM_AUTH_SESSIONS
  
  /**
   * Fill an authentication block in a request.
   * This func can create the first as well as the second auth block (for
   * double authorized commands).
   *
   * @param request	pointer to the request (w/ uninitialised auth data)
   * @param request_len0	length of the request without auth data
   * @param handles_len	length of the handles area in request
   * @param auth_session	pointer to the (valid) auth session to be used
   * @param request_auth	pointer to the auth block of the request to be filled
   * @param auth		authentication data (HMAC key)
   */
b9804e5bf   Miquel Raynal   tpm: substitute d...
498
499
500
501
  static u32 create_request_auth(const void *request, size_t request_len0,
  			       size_t handles_len,
  			       struct session_data *auth_session,
  			       void *request_auth, const void *auth)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
502
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
503
  	u8 hmac_data[DIGEST_LENGTH * 3 + 1];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  	sha1_context hash_ctx;
  	const size_t command_code_offset = 6;
  	const size_t auth_nonce_odd_offset = 4;
  	const size_t auth_continue_offset = 24;
  	const size_t auth_auth_offset = 25;
  
  	if (!auth_session || !auth_session->valid)
  		return TPM_LIB_ERROR;
  
  	sha1_starts(&hash_ctx);
  	sha1_update(&hash_ctx, request + command_code_offset, 4);
  	if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
  		sha1_update(&hash_ctx,
  			    request + TPM_REQUEST_HEADER_LENGTH + handles_len,
  			    request_len0 - TPM_REQUEST_HEADER_LENGTH
  			    - handles_len);
  	sha1_finish(&hash_ctx, hmac_data);
  
  	sha1_starts(&hash_ctx);
  	sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
  	sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
  	sha1_finish(&hash_ctx, auth_session->nonce_odd);
  
  	if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
  			     0, auth_session->handle,
  			     auth_nonce_odd_offset, auth_session->nonce_odd,
  			     DIGEST_LENGTH,
  			     auth_continue_offset, 1))
  		return TPM_LIB_ERROR;
  	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
  			     DIGEST_LENGTH,
  			     auth_session->nonce_even,
  			     DIGEST_LENGTH,
  			     2 * DIGEST_LENGTH,
  			     request_auth + auth_nonce_odd_offset,
  			     DIGEST_LENGTH + 1))
  		return TPM_LIB_ERROR;
  	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
  		  request_auth + auth_auth_offset);
  
  	return TPM_SUCCESS;
  }
  
  /**
   * Verify an authentication block in a response.
   * Since this func updates the nonce_even in the session data it has to be
   * called when receiving a succesfull AUTH response.
   * This func can verify the first as well as the second auth block (for
   * double authorized commands).
   *
   * @param command_code	command code of the request
   * @param response	pointer to the request (w/ uninitialised auth data)
   * @param handles_len	length of the handles area in response
   * @param auth_session	pointer to the (valid) auth session to be used
   * @param response_auth	pointer to the auth block of the response to be verified
   * @param auth		authentication data (HMAC key)
   */
b9804e5bf   Miquel Raynal   tpm: substitute d...
561
562
563
564
  static u32 verify_response_auth(u32 command_code, const void *response,
  				size_t response_len0, size_t handles_len,
  				struct session_data *auth_session,
  				const void *response_auth, const void *auth)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
565
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
566
567
  	u8 hmac_data[DIGEST_LENGTH * 3 + 1];
  	u8 computed_auth[DIGEST_LENGTH];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
568
569
570
571
  	sha1_context hash_ctx;
  	const size_t return_code_offset = 6;
  	const size_t auth_continue_offset = 20;
  	const size_t auth_auth_offset = 21;
b9804e5bf   Miquel Raynal   tpm: substitute d...
572
  	u8 auth_continue;
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  
  	if (!auth_session || !auth_session->valid)
  		return TPM_AUTHFAIL;
  	if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
  			     0, command_code))
  		return TPM_LIB_ERROR;
  	if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
  		return TPM_LIB_ERROR;
  
  	sha1_starts(&hash_ctx);
  	sha1_update(&hash_ctx, response + return_code_offset, 4);
  	sha1_update(&hash_ctx, hmac_data, 4);
  	if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
  		sha1_update(&hash_ctx,
  			    response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
  			    response_len0 - TPM_RESPONSE_HEADER_LENGTH
  			    - handles_len);
  	sha1_finish(&hash_ctx, hmac_data);
  
  	memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
b9804e5bf   Miquel Raynal   tpm: substitute d...
593
  	auth_continue = ((u8 *)response_auth)[auth_continue_offset];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
  	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
  			     DIGEST_LENGTH,
  			     response_auth,
  			     DIGEST_LENGTH,
  			     2 * DIGEST_LENGTH,
  			     auth_session->nonce_odd,
  			     DIGEST_LENGTH,
  			     3 * DIGEST_LENGTH,
  			     auth_continue))
  		return TPM_LIB_ERROR;
  
  	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
  		  computed_auth);
  
  	if (memcmp(computed_auth, response_auth + auth_auth_offset,
  		   DIGEST_LENGTH))
  		return TPM_AUTHFAIL;
  
  	return TPM_SUCCESS;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
614
  u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
615
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
616
  	const u8 command[18] = {
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
617
618
619
620
  		0x00, 0xc1,		/* TPM_TAG */
  		0x00, 0x00, 0x00, 0x00,	/* parameter size */
  		0x00, 0x00, 0x00, 0xba,	/* TPM_COMMAND_CODE */
  		0x00, 0x00, 0x00, 0x00,	/* TPM_HANDLE */
52da18a37   Miquel Raynal   tpm: fix spelling
621
  		0x00, 0x00, 0x00, 0x02,	/* TPM_RESOURCE_TYPE */
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
622
623
  	};
  	const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
b9804e5bf   Miquel Raynal   tpm: substitute d...
624
  	u8 request[COMMAND_BUFFER_SIZE];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
625
626
627
628
629
630
631
  
  	if (pack_byte_string(request, sizeof(request), "sd",
  			     0, command, sizeof(command),
  			     req_handle_offset, auth_handle))
  		return TPM_LIB_ERROR;
  	if (oiap_session.valid && oiap_session.handle == auth_handle)
  		oiap_session.valid = 0;
abdc7b8a2   Simon Glass   tpm: Convert to u...
632
  	return tpm_sendrecv_command(dev, request, NULL, NULL);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
633
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
634
  u32 tpm_end_oiap(struct udevice *dev)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
635
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
636
  	u32 err = TPM_SUCCESS;
96cc4e31f   Miquel Raynal   tpm: add extra bl...
637

be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
638
  	if (oiap_session.valid)
abdc7b8a2   Simon Glass   tpm: Convert to u...
639
  		err = tpm_terminate_auth_session(dev, oiap_session.handle);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
640
641
  	return err;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
642
  u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
643
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
644
  	const u8 command[10] = {
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
645
646
647
648
649
650
  		0x00, 0xc1,		/* TPM_TAG */
  		0x00, 0x00, 0x00, 0x0a,	/* parameter size */
  		0x00, 0x00, 0x00, 0x0a,	/* TPM_COMMAND_CODE */
  	};
  	const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
  	const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
b9804e5bf   Miquel Raynal   tpm: substitute d...
651
  	u8 response[COMMAND_BUFFER_SIZE];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
652
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
653
  	u32 err;
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
654
655
  
  	if (oiap_session.valid)
abdc7b8a2   Simon Glass   tpm: Convert to u...
656
  		tpm_terminate_auth_session(dev, oiap_session.handle);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
657

abdc7b8a2   Simon Glass   tpm: Convert to u...
658
  	err = tpm_sendrecv_command(dev, command, response, &response_length);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
659
660
661
662
663
  	if (err)
  		return err;
  	if (unpack_byte_string(response, response_length, "ds",
  			       res_auth_handle_offset, &oiap_session.handle,
  			       res_nonce_even_offset, &oiap_session.nonce_even,
b9804e5bf   Miquel Raynal   tpm: substitute d...
664
  			       (u32)DIGEST_LENGTH))
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
665
666
667
668
669
670
  		return TPM_LIB_ERROR;
  	oiap_session.valid = 1;
  	if (auth_handle)
  		*auth_handle = oiap_session.handle;
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
671
672
673
  u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
  		       size_t key_length, const void *parent_key_usage_auth,
  		       u32 *key_handle)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
674
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
675
  	const u8 command[14] = {
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
676
677
678
679
680
681
682
683
684
  		0x00, 0xc2,		/* TPM_TAG */
  		0x00, 0x00, 0x00, 0x00,	/* parameter size */
  		0x00, 0x00, 0x00, 0x41,	/* TPM_COMMAND_CODE */
  		0x00, 0x00, 0x00, 0x00,	/* parent handle */
  	};
  	const size_t req_size_offset = 2;
  	const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
  	const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
  	const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
b9804e5bf   Miquel Raynal   tpm: substitute d...
685
686
687
  	u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
  		   TPM_REQUEST_AUTH_LENGTH];
  	u8 response[COMMAND_BUFFER_SIZE];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
688
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
689
  	u32 err;
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
690
691
  
  	if (!oiap_session.valid) {
abdc7b8a2   Simon Glass   tpm: Convert to u...
692
  		err = tpm_oiap(dev, NULL);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
693
694
695
696
697
698
699
700
701
702
703
704
705
706
  		if (err)
  			return err;
  	}
  	if (pack_byte_string(request, sizeof(request), "sdds",
  			     0, command, sizeof(command),
  			     req_size_offset,
  			     sizeof(command) + key_length
  			     + TPM_REQUEST_AUTH_LENGTH,
  			     req_parent_handle_offset, parent_handle,
  			     req_key_offset, key, key_length
  		))
  		return TPM_LIB_ERROR;
  
  	err = create_request_auth(request, sizeof(command) + key_length, 4,
c61791876   Miquel Raynal   tpm: align argume...
707
708
709
  				  &oiap_session,
  				  request + sizeof(command) + key_length,
  				  parent_key_usage_auth);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
710
711
  	if (err)
  		return err;
abdc7b8a2   Simon Glass   tpm: Convert to u...
712
  	err = tpm_sendrecv_command(dev, request, response, &response_length);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
713
714
715
716
717
718
719
  	if (err) {
  		if (err == TPM_AUTHFAIL)
  			oiap_session.valid = 0;
  		return err;
  	}
  
  	err = verify_response_auth(0x00000041, response,
c61791876   Miquel Raynal   tpm: align argume...
720
721
722
723
724
  				   response_length - TPM_RESPONSE_AUTH_LENGTH,
  				   4, &oiap_session,
  				   response + response_length -
  				   TPM_RESPONSE_AUTH_LENGTH,
  				   parent_key_usage_auth);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
725
726
727
728
729
730
731
732
733
734
735
  	if (err)
  		return err;
  
  	if (key_handle) {
  		if (unpack_byte_string(response, response_length, "d",
  				       res_handle_offset, key_handle))
  			return TPM_LIB_ERROR;
  	}
  
  	return 0;
  }
abdc7b8a2   Simon Glass   tpm: Convert to u...
736
737
  u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
  			 const void *usage_auth, void *pubkey,
b9804e5bf   Miquel Raynal   tpm: substitute d...
738
  			 size_t *pubkey_len)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
739
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
740
  	const u8 command[14] = {
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
741
742
743
744
745
746
747
748
  		0x00, 0xc2,		/* TPM_TAG */
  		0x00, 0x00, 0x00, 0x00,	/* parameter size */
  		0x00, 0x00, 0x00, 0x21,	/* TPM_COMMAND_CODE */
  		0x00, 0x00, 0x00, 0x00,	/* key handle */
  	};
  	const size_t req_size_offset = 2;
  	const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
  	const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
b9804e5bf   Miquel Raynal   tpm: substitute d...
749
750
751
  	u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
  	u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
  		    TPM_RESPONSE_AUTH_LENGTH];
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
752
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
753
  	u32 err;
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
754
755
  
  	if (!oiap_session.valid) {
abdc7b8a2   Simon Glass   tpm: Convert to u...
756
  		err = tpm_oiap(dev, NULL);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
757
758
759
760
761
762
  		if (err)
  			return err;
  	}
  	if (pack_byte_string(request, sizeof(request), "sdd",
  			     0, command, sizeof(command),
  			     req_size_offset,
b9804e5bf   Miquel Raynal   tpm: substitute d...
763
  			     (u32)(sizeof(command)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
764
765
766
767
768
  			     + TPM_REQUEST_AUTH_LENGTH),
  			     req_key_handle_offset, key_handle
  		))
  		return TPM_LIB_ERROR;
  	err = create_request_auth(request, sizeof(command), 4, &oiap_session,
c61791876   Miquel Raynal   tpm: align argume...
769
  				  request + sizeof(command), usage_auth);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
770
771
  	if (err)
  		return err;
abdc7b8a2   Simon Glass   tpm: Convert to u...
772
  	err = tpm_sendrecv_command(dev, request, response, &response_length);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
773
774
775
776
777
778
  	if (err) {
  		if (err == TPM_AUTHFAIL)
  			oiap_session.valid = 0;
  		return err;
  	}
  	err = verify_response_auth(0x00000021, response,
c61791876   Miquel Raynal   tpm: align argume...
779
780
781
782
783
  				   response_length - TPM_RESPONSE_AUTH_LENGTH,
  				   0, &oiap_session,
  				   response + response_length -
  				   TPM_RESPONSE_AUTH_LENGTH,
  				   usage_auth);
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
784
785
786
787
788
  	if (err)
  		return err;
  
  	if (pubkey) {
  		if ((response_length - TPM_RESPONSE_HEADER_LENGTH
c61791876   Miquel Raynal   tpm: align argume...
789
  		     - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
790
791
792
793
794
795
796
797
798
799
  			return TPM_LIB_ERROR;
  		*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
  			- TPM_RESPONSE_AUTH_LENGTH;
  		memcpy(pubkey, response + res_pubkey_offset,
  		       response_length - TPM_RESPONSE_HEADER_LENGTH
  		       - TPM_RESPONSE_AUTH_LENGTH);
  	}
  
  	return 0;
  }
0f4b2ba17   mario.six@gdsys.cc   tpm: Add function...
800
  #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
abdc7b8a2   Simon Glass   tpm: Convert to u...
801
802
  u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
  		      const u8 pubkey_digest[20], u32 *handle)
0f4b2ba17   mario.six@gdsys.cc   tpm: Add function...
803
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
804
805
806
807
808
809
  	u16 key_count;
  	u32 key_handles[10];
  	u8 buf[288];
  	u8 *ptr;
  	u32 err;
  	u8 digest[20];
0f4b2ba17   mario.six@gdsys.cc   tpm: Add function...
810
811
812
813
  	size_t buf_len;
  	unsigned int i;
  
  	/* fetch list of already loaded keys in the TPM */
abdc7b8a2   Simon Glass   tpm: Convert to u...
814
815
  	err = tpm_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
  				 sizeof(buf));
0f4b2ba17   mario.six@gdsys.cc   tpm: Add function...
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
  	if (err)
  		return -1;
  	key_count = get_unaligned_be16(buf);
  	ptr = buf + 2;
  	for (i = 0; i < key_count; ++i, ptr += 4)
  		key_handles[i] = get_unaligned_be32(ptr);
  
  	/* now search a(/ the) key which we can access with the given auth */
  	for (i = 0; i < key_count; ++i) {
  		buf_len = sizeof(buf);
  		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
  		if (err && err != TPM_AUTHFAIL)
  			return -1;
  		if (err)
  			continue;
  		sha1_csum(buf, buf_len, digest);
  		if (!memcmp(digest, pubkey_digest, 20)) {
  			*handle = key_handles[i];
  			return 0;
  		}
  	}
  	return 1;
  }
  #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
be6c1529c   Reinhard Pfau   tpm: add AUTH1 cm...
840
  #endif /* CONFIG_TPM_AUTH_SESSIONS */
3c6050277   André Draszik   tpm: add tpm_get_...
841

abdc7b8a2   Simon Glass   tpm: Convert to u...
842
  u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
3c6050277   André Draszik   tpm: add tpm_get_...
843
  {
b9804e5bf   Miquel Raynal   tpm: substitute d...
844
  	const u8 command[14] = {
3c6050277   André Draszik   tpm: add tpm_get_...
845
846
847
848
849
850
851
  		0x0, 0xc1,		/* TPM_TAG */
  		0x0, 0x0, 0x0, 0xe,	/* parameter size */
  		0x0, 0x0, 0x0, 0x46,	/* TPM_COMMAND_CODE */
  	};
  	const size_t length_offset = 10;
  	const size_t data_size_offset = 10;
  	const size_t data_offset = 14;
b9804e5bf   Miquel Raynal   tpm: substitute d...
852
  	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
3c6050277   André Draszik   tpm: add tpm_get_...
853
  	size_t response_length = sizeof(response);
b9804e5bf   Miquel Raynal   tpm: substitute d...
854
855
  	u32 data_size;
  	u8 *out = data;
3c6050277   André Draszik   tpm: add tpm_get_...
856
857
  
  	while (count > 0) {
b9804e5bf   Miquel Raynal   tpm: substitute d...
858
859
860
  		u32 this_bytes = min((size_t)count,
  				     sizeof(response) - data_offset);
  		u32 err;
3c6050277   André Draszik   tpm: add tpm_get_...
861
862
863
864
865
  
  		if (pack_byte_string(buf, sizeof(buf), "sd",
  				     0, command, sizeof(command),
  				     length_offset, this_bytes))
  			return TPM_LIB_ERROR;
abdc7b8a2   Simon Glass   tpm: Convert to u...
866
867
  		err = tpm_sendrecv_command(dev, buf, response,
  					   &response_length);
3c6050277   André Draszik   tpm: add tpm_get_...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
  		if (err)
  			return err;
  		if (unpack_byte_string(response, response_length, "d",
  				       data_size_offset, &data_size))
  			return TPM_LIB_ERROR;
  		if (data_size > count)
  			return TPM_LIB_ERROR;
  		if (unpack_byte_string(response, response_length, "s",
  				       data_offset, out, data_size))
  			return TPM_LIB_ERROR;
  
  		count -= data_size;
  		out += data_size;
  	}
  
  	return 0;
  }