Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e5fb5d2

Browse files
James Bottomleyjarkkojs
authored andcommitted
security: keys: trusted: Make sealed key properly interoperable
The current implementation appends a migratable flag to the end of a key, meaning the format isn't exactly interoperable because the using party needs to know to strip this extra byte. However, all other consumers of TPM sealed blobs expect the unseal to return exactly the key. Since TPM2 keys have a key property flag that corresponds to migratable, use that flag instead and make the actual key the only sealed quantity. This is secure because the key properties are bound to a hash in the private part, so if they're altered the key won't load. Backwards compatibility is implemented by detecting whether we're loading a new format key or not and correctly setting migratable from the last byte of old format keys. Signed-off-by: James Bottomley <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Tested-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent f221974 commit e5fb5d2

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

include/linux/tpm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ struct tpm_buf {
305305
};
306306

307307
enum tpm2_object_attributes {
308+
TPM2_OA_FIXED_TPM = BIT(1),
309+
TPM2_OA_FIXED_PARENT = BIT(4),
308310
TPM2_OA_USER_WITH_AUTH = BIT(6),
309311
};
310312

security/keys/trusted-keys/trusted_tpm2.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
231231
int blob_len = 0;
232232
struct tpm_buf buf;
233233
u32 hash;
234+
u32 flags;
234235
int i;
235236
int rc;
236237

@@ -265,31 +266,32 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
265266
TPM_DIGEST_SIZE);
266267

267268
/* sensitive */
268-
tpm_buf_append_u16(&buf, 4 + options->blobauth_len + payload->key_len + 1);
269+
tpm_buf_append_u16(&buf, 4 + options->blobauth_len + payload->key_len);
269270

270271
tpm_buf_append_u16(&buf, options->blobauth_len);
271272
if (options->blobauth_len)
272273
tpm_buf_append(&buf, options->blobauth, options->blobauth_len);
273274

274-
tpm_buf_append_u16(&buf, payload->key_len + 1);
275+
tpm_buf_append_u16(&buf, payload->key_len);
275276
tpm_buf_append(&buf, payload->key, payload->key_len);
276-
tpm_buf_append_u8(&buf, payload->migratable);
277277

278278
/* public */
279279
tpm_buf_append_u16(&buf, 14 + options->policydigest_len);
280280
tpm_buf_append_u16(&buf, TPM_ALG_KEYEDHASH);
281281
tpm_buf_append_u16(&buf, hash);
282282

283+
/* key properties */
284+
flags = 0;
285+
flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH;
286+
flags |= payload->migratable ? (TPM2_OA_FIXED_TPM |
287+
TPM2_OA_FIXED_PARENT) : 0;
288+
tpm_buf_append_u32(&buf, flags);
289+
283290
/* policy */
284-
if (options->policydigest_len) {
285-
tpm_buf_append_u32(&buf, 0);
286-
tpm_buf_append_u16(&buf, options->policydigest_len);
291+
tpm_buf_append_u16(&buf, options->policydigest_len);
292+
if (options->policydigest_len)
287293
tpm_buf_append(&buf, options->policydigest,
288294
options->policydigest_len);
289-
} else {
290-
tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH);
291-
tpm_buf_append_u16(&buf, 0);
292-
}
293295

294296
/* public parameters */
295297
tpm_buf_append_u16(&buf, TPM_ALG_NULL);
@@ -364,8 +366,9 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
364366
unsigned int private_len;
365367
unsigned int public_len;
366368
unsigned int blob_len;
367-
u8 *blob;
369+
u8 *blob, *pub;
368370
int rc;
371+
u32 attrs;
369372

370373
rc = tpm2_key_decode(payload, options, &blob);
371374
if (rc) {
@@ -392,6 +395,16 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
392395
if (private_len + 2 + public_len + 2 > payload->blob_len)
393396
return -E2BIG;
394397

398+
pub = blob + 2 + private_len + 2;
399+
/* key attributes are always at offset 4 */
400+
attrs = get_unaligned_be32(pub + 4);
401+
402+
if ((attrs & (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT)) ==
403+
(TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT))
404+
payload->migratable = 0;
405+
else
406+
payload->migratable = 1;
407+
395408
blob_len = private_len + public_len + 4;
396409
if (blob_len > payload->blob_len)
397410
return -E2BIG;
@@ -472,7 +485,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
472485
if (!rc) {
473486
data_len = be16_to_cpup(
474487
(__be16 *) &buf.data[TPM_HEADER_SIZE + 4]);
475-
if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE + 1) {
488+
if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE) {
476489
rc = -EFAULT;
477490
goto out;
478491
}
@@ -483,9 +496,19 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
483496
}
484497
data = &buf.data[TPM_HEADER_SIZE + 6];
485498

486-
memcpy(payload->key, data, data_len - 1);
487-
payload->key_len = data_len - 1;
488-
payload->migratable = data[data_len - 1];
499+
if (payload->old_format) {
500+
/* migratable flag is at the end of the key */
501+
memcpy(payload->key, data, data_len - 1);
502+
payload->key_len = data_len - 1;
503+
payload->migratable = data[data_len - 1];
504+
} else {
505+
/*
506+
* migratable flag already collected from key
507+
* attributes
508+
*/
509+
memcpy(payload->key, data, data_len);
510+
payload->key_len = data_len;
511+
}
489512
}
490513

491514
out:

0 commit comments

Comments
 (0)