1
2
3
4
5
6
7#include <common.h>
8#include <dm.h>
9#include <tpm-common.h>
10#include <tpm-v2.h>
11#include "tpm-utils.h"
12
13u32 tpm2_startup(enum tpm2_startup_types mode)
14{
15 const u8 command_v2[12] = {
16 tpm_u16(TPM2_ST_NO_SESSIONS),
17 tpm_u32(12),
18 tpm_u32(TPM2_CC_STARTUP),
19 tpm_u16(mode),
20 };
21 int ret;
22
23
24
25
26
27 ret = tpm_sendrecv_command(command_v2, NULL, NULL);
28 if (ret && ret != TPM2_RC_INITIALIZE)
29 return ret;
30
31 return 0;
32}
33
34u32 tpm2_self_test(enum tpm2_yes_no full_test)
35{
36 const u8 command_v2[12] = {
37 tpm_u16(TPM2_ST_NO_SESSIONS),
38 tpm_u32(11),
39 tpm_u32(TPM2_CC_SELF_TEST),
40 full_test,
41 };
42
43 return tpm_sendrecv_command(command_v2, NULL, NULL);
44}
45
46u32 tpm2_clear(u32 handle, const char *pw, const ssize_t pw_sz)
47{
48 u8 command_v2[COMMAND_BUFFER_SIZE] = {
49 tpm_u16(TPM2_ST_SESSIONS),
50 tpm_u32(27 + pw_sz),
51 tpm_u32(TPM2_CC_CLEAR),
52
53
54 tpm_u32(handle),
55
56
57 tpm_u32(9 + pw_sz),
58 tpm_u32(TPM2_RS_PW),
59 tpm_u16(0),
60
61 0,
62 tpm_u16(pw_sz),
63
64 };
65 unsigned int offset = 27;
66 int ret;
67
68
69
70
71
72 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
73 offset, pw, pw_sz);
74 offset += pw_sz;
75 if (ret)
76 return TPM_LIB_ERROR;
77
78 return tpm_sendrecv_command(command_v2, NULL, NULL);
79}
80
81u32 tpm2_pcr_extend(u32 index, const uint8_t *digest)
82{
83 u8 command_v2[COMMAND_BUFFER_SIZE] = {
84 tpm_u16(TPM2_ST_SESSIONS),
85 tpm_u32(33 + TPM2_DIGEST_LEN),
86 tpm_u32(TPM2_CC_PCR_EXTEND),
87
88
89 tpm_u32(index),
90
91
92 tpm_u32(9),
93 tpm_u32(TPM2_RS_PW),
94 tpm_u16(0),
95
96 0,
97 tpm_u16(0),
98
99 tpm_u32(1),
100 tpm_u16(TPM2_ALG_SHA256),
101
102 };
103 unsigned int offset = 33;
104 int ret;
105
106
107
108
109
110 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
111 offset, digest, TPM2_DIGEST_LEN);
112 offset += TPM2_DIGEST_LEN;
113 if (ret)
114 return TPM_LIB_ERROR;
115
116 return tpm_sendrecv_command(command_v2, NULL, NULL);
117}
118
119u32 tpm2_pcr_read(u32 idx, unsigned int idx_min_sz, void *data,
120 unsigned int *updates)
121{
122 u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
123 u8 command_v2[COMMAND_BUFFER_SIZE] = {
124 tpm_u16(TPM2_ST_NO_SESSIONS),
125 tpm_u32(17 + idx_array_sz),
126 tpm_u32(TPM2_CC_PCR_READ),
127
128
129 tpm_u32(1),
130 tpm_u16(TPM2_ALG_SHA256),
131 idx_array_sz,
132
133 };
134 size_t response_len = COMMAND_BUFFER_SIZE;
135 u8 response[COMMAND_BUFFER_SIZE];
136 unsigned int pcr_sel_idx = idx / 8;
137 u8 pcr_sel_bit = BIT(idx % 8);
138 unsigned int counter = 0;
139 int ret;
140
141 if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
142 17 + pcr_sel_idx, pcr_sel_bit))
143 return TPM_LIB_ERROR;
144
145 ret = tpm_sendrecv_command(command_v2, response, &response_len);
146 if (ret)
147 return ret;
148
149 if (unpack_byte_string(response, response_len, "ds",
150 10, &counter,
151 response_len - TPM2_DIGEST_LEN, data,
152 TPM2_DIGEST_LEN))
153 return TPM_LIB_ERROR;
154
155 if (updates)
156 *updates = counter;
157
158 return 0;
159}
160
161u32 tpm2_get_capability(u32 capability, u32 property, void *buf,
162 size_t prop_count)
163{
164 u8 command_v2[COMMAND_BUFFER_SIZE] = {
165 tpm_u16(TPM2_ST_NO_SESSIONS),
166 tpm_u32(22),
167 tpm_u32(TPM2_CC_GET_CAPABILITY),
168
169 tpm_u32(capability),
170 tpm_u32(property),
171 tpm_u32(prop_count),
172 };
173 u8 response[COMMAND_BUFFER_SIZE];
174 size_t response_len = COMMAND_BUFFER_SIZE;
175 unsigned int properties_off;
176 int ret;
177
178 ret = tpm_sendrecv_command(command_v2, response, &response_len);
179 if (ret)
180 return ret;
181
182
183
184
185
186
187 properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
188 sizeof(u8) + sizeof(u32) + sizeof(u32);
189 memcpy(buf, &response[properties_off], response_len - properties_off);
190
191 return 0;
192}
193
194u32 tpm2_dam_reset(const char *pw, const ssize_t pw_sz)
195{
196 u8 command_v2[COMMAND_BUFFER_SIZE] = {
197 tpm_u16(TPM2_ST_SESSIONS),
198 tpm_u32(27 + pw_sz),
199 tpm_u32(TPM2_CC_DAM_RESET),
200
201
202 tpm_u32(TPM2_RH_LOCKOUT),
203
204
205 tpm_u32(9 + pw_sz),
206 tpm_u32(TPM2_RS_PW),
207 tpm_u16(0),
208
209 0,
210 tpm_u16(pw_sz),
211
212 };
213 unsigned int offset = 27;
214 int ret;
215
216
217
218
219
220 ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
221 offset, pw, pw_sz);
222 offset += pw_sz;
223 if (ret)
224 return TPM_LIB_ERROR;
225
226 return tpm_sendrecv_command(command_v2, NULL, NULL);
227}
228
229u32 tpm2_dam_parameters(const char *pw, const ssize_t pw_sz,
230 unsigned int max_tries, unsigned int recovery_time,
231 unsigned int lockout_recovery)
232{
233 u8 command_v2[COMMAND_BUFFER_SIZE] = {
234 tpm_u16(TPM2_ST_SESSIONS),
235 tpm_u32(27 + pw_sz + 12),
236 tpm_u32(TPM2_CC_DAM_PARAMETERS),
237
238
239 tpm_u32(TPM2_RH_LOCKOUT),
240
241
242 tpm_u32(9 + pw_sz),
243 tpm_u32(TPM2_RS_PW),
244 tpm_u16(0),
245
246 0,
247 tpm_u16(pw_sz),
248
249
250
251
252
253
254 };
255 unsigned int offset = 27;
256 int ret;
257
258
259
260
261
262
263
264
265 ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
266 offset, pw, pw_sz,
267 offset + pw_sz, max_tries,
268 offset + pw_sz + 4, recovery_time,
269 offset + pw_sz + 8, lockout_recovery);
270 offset += pw_sz + 12;
271 if (ret)
272 return TPM_LIB_ERROR;
273
274 return tpm_sendrecv_command(command_v2, NULL, NULL);
275}
276
277int tpm2_change_auth(u32 handle, const char *newpw, const ssize_t newpw_sz,
278 const char *oldpw, const ssize_t oldpw_sz)
279{
280 unsigned int offset = 27;
281 u8 command_v2[COMMAND_BUFFER_SIZE] = {
282 tpm_u16(TPM2_ST_SESSIONS),
283 tpm_u32(offset + oldpw_sz + 2 + newpw_sz),
284 tpm_u32(TPM2_CC_HIERCHANGEAUTH),
285
286
287 tpm_u32(handle),
288
289
290 tpm_u32(9 + oldpw_sz),
291 tpm_u32(TPM2_RS_PW),
292 tpm_u16(0),
293
294 0,
295 tpm_u16(oldpw_sz)
296
297
298
299
300
301 };
302 int ret;
303
304
305
306
307
308
309
310 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
311 offset, oldpw, oldpw_sz,
312 offset + oldpw_sz, newpw_sz,
313 offset + oldpw_sz + 2, newpw, newpw_sz);
314 offset += oldpw_sz + 2 + newpw_sz;
315 if (ret)
316 return TPM_LIB_ERROR;
317
318 return tpm_sendrecv_command(command_v2, NULL, NULL);
319}
320
321u32 tpm2_pcr_setauthpolicy(const char *pw, const ssize_t pw_sz, u32 index,
322 const char *key)
323{
324 u8 command_v2[COMMAND_BUFFER_SIZE] = {
325 tpm_u16(TPM2_ST_SESSIONS),
326 tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN),
327 tpm_u32(TPM2_CC_PCR_SETAUTHPOL),
328
329
330 tpm_u32(TPM2_RH_PLATFORM),
331
332
333 tpm_u32(9 + pw_sz),
334 tpm_u32(TPM2_RS_PW),
335 tpm_u16(0),
336
337 0,
338 tpm_u16(pw_sz)
339
340
341
342
343
344
345
346
347
348
349
350 };
351 unsigned int offset = 27;
352 int ret;
353
354
355
356
357
358
359
360
361
362 ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
363 offset, pw, pw_sz,
364 offset + pw_sz, TPM2_DIGEST_LEN,
365 offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
366 offset + pw_sz + 2 + TPM2_DIGEST_LEN,
367 TPM2_ALG_SHA256,
368 offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
369 offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
370 if (ret)
371 return TPM_LIB_ERROR;
372
373 return tpm_sendrecv_command(command_v2, NULL, NULL);
374}
375
376u32 tpm2_pcr_setauthvalue(const char *pw, const ssize_t pw_sz, u32 index,
377 const char *key, const ssize_t key_sz)
378{
379 u8 command_v2[COMMAND_BUFFER_SIZE] = {
380 tpm_u16(TPM2_ST_SESSIONS),
381 tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN),
382 tpm_u32(TPM2_CC_PCR_SETAUTHVAL),
383
384
385 tpm_u32(index),
386
387
388 tpm_u32(9 + pw_sz),
389 tpm_u32(TPM2_RS_PW),
390 tpm_u16(0),
391
392 0,
393 tpm_u16(pw_sz),
394
395
396
397
398
399 };
400 unsigned int offset = 27;
401 int ret;
402
403
404
405
406
407
408
409
410 ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
411 offset, pw, pw_sz,
412 offset + pw_sz, key_sz,
413 offset + pw_sz + 2, key, key_sz);
414 offset += pw_sz + 2 + key_sz;
415 if (ret)
416 return TPM_LIB_ERROR;
417
418 return tpm_sendrecv_command(command_v2, NULL, NULL);
419}
420