]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - lib/tpm-v2.c
f1bbca8e7aa51e06806fa5914404605d64bc0d8f
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2018 Bootlin
4 * Author: Miquel Raynal <miquel.raynal@bootlin.com>
9 #include <tpm-common.h>
11 #include "tpm-utils.h"
13 u32
tpm2_startup(enum tpm2_startup_types mode
)
15 const u8 command_v2
[12] = {
16 tpm_u16(TPM2_ST_NO_SESSIONS
),
18 tpm_u32(TPM2_CC_STARTUP
),
24 * Note TPM2_Startup command will return RC_SUCCESS the first time,
25 * but will return RC_INITIALIZE otherwise.
27 ret
= tpm_sendrecv_command(command_v2
, NULL
, NULL
);
28 if (ret
&& ret
!= TPM2_RC_INITIALIZE
)
34 u32
tpm2_self_test(enum tpm2_yes_no full_test
)
36 const u8 command_v2
[12] = {
37 tpm_u16(TPM2_ST_NO_SESSIONS
),
39 tpm_u32(TPM2_CC_SELF_TEST
),
43 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
46 u32
tpm2_clear(u32 handle
, const char *pw
, const ssize_t pw_sz
)
48 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
49 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
50 tpm_u32(27 + pw_sz
), /* Length */
51 tpm_u32(TPM2_CC_CLEAR
), /* Command code */
54 tpm_u32(handle
), /* TPM resource handle */
57 tpm_u32(9 + pw_sz
), /* Authorization size */
58 tpm_u32(TPM2_RS_PW
), /* Session handle */
59 tpm_u16(0), /* Size of <nonce> */
60 /* <nonce> (if any) */
61 0, /* Attributes: Cont/Excl/Rst */
62 tpm_u16(pw_sz
), /* Size of <hmac/password> */
63 /* STRING(pw) <hmac/password> (if any) */
65 unsigned int offset
= 27;
69 * Fill the command structure starting from the first buffer:
70 * - the password (if any)
72 ret
= pack_byte_string(command_v2
, sizeof(command_v2
), "s",
78 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
81 u32
tpm2_pcr_extend(u32 index
, const uint8_t *digest
)
83 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
84 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
85 tpm_u32(33 + TPM2_DIGEST_LEN
), /* Length */
86 tpm_u32(TPM2_CC_PCR_EXTEND
), /* Command code */
89 tpm_u32(index
), /* Handle (PCR Index) */
92 tpm_u32(9), /* Authorization size */
93 tpm_u32(TPM2_RS_PW
), /* Session handle */
94 tpm_u16(0), /* Size of <nonce> */
95 /* <nonce> (if any) */
96 0, /* Attributes: Cont/Excl/Rst */
97 tpm_u16(0), /* Size of <hmac/password> */
98 /* <hmac/password> (if any) */
99 tpm_u32(1), /* Count (number of hashes) */
100 tpm_u16(TPM2_ALG_SHA256
), /* Algorithm of the hash */
101 /* STRING(digest) Digest */
103 unsigned int offset
= 33;
107 * Fill the command structure starting from the first buffer:
110 ret
= pack_byte_string(command_v2
, sizeof(command_v2
), "s",
111 offset
, digest
, TPM2_DIGEST_LEN
);
112 offset
+= TPM2_DIGEST_LEN
;
114 return TPM_LIB_ERROR
;
116 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
119 u32
tpm2_pcr_read(u32 idx
, unsigned int idx_min_sz
, void *data
,
120 unsigned int *updates
)
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
), /* TAG */
125 tpm_u32(17 + idx_array_sz
), /* Length */
126 tpm_u32(TPM2_CC_PCR_READ
), /* Command code */
128 /* TPML_PCR_SELECTION */
129 tpm_u32(1), /* Number of selections */
130 tpm_u16(TPM2_ALG_SHA256
), /* Algorithm of the hash */
131 idx_array_sz
, /* Array size for selection */
132 /* bitmap(idx) Selected PCR bitmap */
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;
141 if (pack_byte_string(command_v2
, COMMAND_BUFFER_SIZE
, "b",
142 17 + pcr_sel_idx
, pcr_sel_bit
))
143 return TPM_LIB_ERROR
;
145 ret
= tpm_sendrecv_command(command_v2
, response
, &response_len
);
149 if (unpack_byte_string(response
, response_len
, "ds",
151 response_len
- TPM2_DIGEST_LEN
, data
,
153 return TPM_LIB_ERROR
;
161 u32
tpm2_get_capability(u32 capability
, u32 property
, void *buf
,
164 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
165 tpm_u16(TPM2_ST_NO_SESSIONS
), /* TAG */
166 tpm_u32(22), /* Length */
167 tpm_u32(TPM2_CC_GET_CAPABILITY
), /* Command code */
169 tpm_u32(capability
), /* Capability */
170 tpm_u32(property
), /* Property */
171 tpm_u32(prop_count
), /* Property count */
173 u8 response
[COMMAND_BUFFER_SIZE
];
174 size_t response_len
= COMMAND_BUFFER_SIZE
;
175 unsigned int properties_off
;
178 ret
= tpm_sendrecv_command(command_v2
, response
, &response_len
);
183 * In the response buffer, the properties are located after the:
184 * tag (u16), response size (u32), response code (u32),
185 * YES/NO flag (u8), TPM_CAP (u32) and TPMU_CAPABILITIES (u32).
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
);
194 u32
tpm2_dam_reset(const char *pw
, const ssize_t pw_sz
)
196 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
197 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
198 tpm_u32(27 + pw_sz
), /* Length */
199 tpm_u32(TPM2_CC_DAM_RESET
), /* Command code */
202 tpm_u32(TPM2_RH_LOCKOUT
), /* TPM resource handle */
205 tpm_u32(9 + pw_sz
), /* Authorization size */
206 tpm_u32(TPM2_RS_PW
), /* Session handle */
207 tpm_u16(0), /* Size of <nonce> */
208 /* <nonce> (if any) */
209 0, /* Attributes: Cont/Excl/Rst */
210 tpm_u16(pw_sz
), /* Size of <hmac/password> */
211 /* STRING(pw) <hmac/password> (if any) */
213 unsigned int offset
= 27;
217 * Fill the command structure starting from the first buffer:
218 * - the password (if any)
220 ret
= pack_byte_string(command_v2
, sizeof(command_v2
), "s",
224 return TPM_LIB_ERROR
;
226 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
229 u32
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
)
233 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
234 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
235 tpm_u32(27 + pw_sz
+ 12), /* Length */
236 tpm_u32(TPM2_CC_DAM_PARAMETERS
), /* Command code */
239 tpm_u32(TPM2_RH_LOCKOUT
), /* TPM resource handle */
242 tpm_u32(9 + pw_sz
), /* Authorization size */
243 tpm_u32(TPM2_RS_PW
), /* Session handle */
244 tpm_u16(0), /* Size of <nonce> */
245 /* <nonce> (if any) */
246 0, /* Attributes: Cont/Excl/Rst */
247 tpm_u16(pw_sz
), /* Size of <hmac/password> */
248 /* STRING(pw) <hmac/password> (if any) */
250 /* LOCKOUT PARAMETERS */
251 /* tpm_u32(max_tries) Max tries (0, always lock) */
252 /* tpm_u32(recovery_time) Recovery time (0, no lock) */
253 /* tpm_u32(lockout_recovery) Lockout recovery */
255 unsigned int offset
= 27;
259 * Fill the command structure starting from the first buffer:
260 * - the password (if any)
265 ret
= pack_byte_string(command_v2
, sizeof(command_v2
), "sddd",
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;
272 return TPM_LIB_ERROR
;
274 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
277 int tpm2_change_auth(u32 handle
, const char *newpw
, const ssize_t newpw_sz
,
278 const char *oldpw
, const ssize_t oldpw_sz
)
280 unsigned int offset
= 27;
281 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
282 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
283 tpm_u32(offset
+ oldpw_sz
+ 2 + newpw_sz
), /* Length */
284 tpm_u32(TPM2_CC_HIERCHANGEAUTH
), /* Command code */
287 tpm_u32(handle
), /* TPM resource handle */
290 tpm_u32(9 + oldpw_sz
), /* Authorization size */
291 tpm_u32(TPM2_RS_PW
), /* Session handle */
292 tpm_u16(0), /* Size of <nonce> */
293 /* <nonce> (if any) */
294 0, /* Attributes: Cont/Excl/Rst */
295 tpm_u16(oldpw_sz
) /* Size of <hmac/password> */
296 /* STRING(oldpw) <hmac/password> (if any) */
298 /* TPM2B_AUTH (TPM2B_DIGEST) */
299 /* tpm_u16(newpw_sz) Digest size, new pw length */
300 /* STRING(newpw) Digest buffer, new pw */
305 * Fill the command structure starting from the first buffer:
306 * - the old password (if any)
307 * - size of the new password
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
;
316 return TPM_LIB_ERROR
;
318 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
321 u32
tpm2_pcr_setauthpolicy(const char *pw
, const ssize_t pw_sz
, u32 index
,
324 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
325 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
326 tpm_u32(35 + pw_sz
+ TPM2_DIGEST_LEN
), /* Length */
327 tpm_u32(TPM2_CC_PCR_SETAUTHPOL
), /* Command code */
330 tpm_u32(TPM2_RH_PLATFORM
), /* TPM resource handle */
333 tpm_u32(9 + pw_sz
), /* Authorization size */
334 tpm_u32(TPM2_RS_PW
), /* session handle */
335 tpm_u16(0), /* Size of <nonce> */
336 /* <nonce> (if any) */
337 0, /* Attributes: Cont/Excl/Rst */
338 tpm_u16(pw_sz
) /* Size of <hmac/password> */
339 /* STRING(pw) <hmac/password> (if any) */
341 /* TPM2B_AUTH (TPM2B_DIGEST) */
342 /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */
343 /* STRING(key) Digest buffer (PCR key) */
346 /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */
349 /* tpm_u32(index), PCR Index */
351 unsigned int offset
= 27;
355 * Fill the command structure starting from the first buffer:
356 * - the password (if any)
357 * - the PCR key length
359 * - the hash algorithm
362 ret
= pack_byte_string(command_v2
, sizeof(command_v2
), "swswd",
364 offset
+ pw_sz
, TPM2_DIGEST_LEN
,
365 offset
+ pw_sz
+ 2, key
, TPM2_DIGEST_LEN
,
366 offset
+ pw_sz
+ 2 + TPM2_DIGEST_LEN
,
368 offset
+ pw_sz
+ 4 + TPM2_DIGEST_LEN
, index
);
369 offset
+= pw_sz
+ 2 + TPM2_DIGEST_LEN
+ 2 + 4;
371 return TPM_LIB_ERROR
;
373 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);
376 u32
tpm2_pcr_setauthvalue(const char *pw
, const ssize_t pw_sz
, u32 index
,
377 const char *key
, const ssize_t key_sz
)
379 u8 command_v2
[COMMAND_BUFFER_SIZE
] = {
380 tpm_u16(TPM2_ST_SESSIONS
), /* TAG */
381 tpm_u32(33 + pw_sz
+ TPM2_DIGEST_LEN
), /* Length */
382 tpm_u32(TPM2_CC_PCR_SETAUTHVAL
), /* Command code */
385 tpm_u32(index
), /* Handle (PCR Index) */
388 tpm_u32(9 + pw_sz
), /* Authorization size */
389 tpm_u32(TPM2_RS_PW
), /* session handle */
390 tpm_u16(0), /* Size of <nonce> */
391 /* <nonce> (if any) */
392 0, /* Attributes: Cont/Excl/Rst */
393 tpm_u16(pw_sz
), /* Size of <hmac/password> */
394 /* STRING(pw) <hmac/password> (if any) */
397 /* tpm_u16(key_sz) Key length */
398 /* STRING(key) Key */
400 unsigned int offset
= 27;
404 * Fill the command structure starting from the first buffer:
405 * - the password (if any)
406 * - the number of digests, 1 in our case
407 * - the algorithm, sha256 in our case
408 * - the digest (64 bytes)
410 ret
= pack_byte_string(command_v2
, sizeof(command_v2
), "sws",
412 offset
+ pw_sz
, key_sz
,
413 offset
+ pw_sz
+ 2, key
, key_sz
);
414 offset
+= pw_sz
+ 2 + key_sz
;
416 return TPM_LIB_ERROR
;
418 return tpm_sendrecv_command(command_v2
, NULL
, NULL
);