Skip to content

Commit 52ce7d9

Browse files
jejbjarkkojs
authored andcommitted
KEYS: trusted: Add session encryption protection to the seal/unseal path
If some entity is snooping the TPM bus, the can see the data going in to be sealed and the data coming out as it is unsealed. Add parameter and response encryption to these cases to ensure that no secrets are leaked even if the bus is snooped. As part of doing this conversion it was discovered that policy sessions can't work with HMAC protected authority because of missing pieces (the tpm Nonce). I've added code to work the same way as before, which will result in potential authority exposure (while still adding security for the command and the returned blob), and a fixme to redo the API to get rid of this security hole. 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 1b6d7f9 commit 52ce7d9

File tree

1 file changed

+61
-27
lines changed

1 file changed

+61
-27
lines changed

security/keys/trusted-keys/trusted_tpm2.c

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -253,26 +253,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
253253
if (rc)
254254
return rc;
255255

256+
rc = tpm2_start_auth_session(chip);
257+
if (rc)
258+
goto out_put;
259+
256260
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
257261
if (rc) {
258-
tpm_put_ops(chip);
259-
return rc;
262+
tpm2_end_auth_session(chip);
263+
goto out_put;
260264
}
261265

262266
rc = tpm_buf_init_sized(&sized);
263267
if (rc) {
264268
tpm_buf_destroy(&buf);
265-
tpm_put_ops(chip);
266-
return rc;
269+
tpm2_end_auth_session(chip);
270+
goto out_put;
267271
}
268272

269-
tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
270-
tpm_buf_append_u32(&buf, options->keyhandle);
271-
tpm2_buf_append_auth(&buf, TPM2_RS_PW,
272-
NULL /* nonce */, 0,
273-
0 /* session_attributes */,
274-
options->keyauth /* hmac */,
275-
TPM_DIGEST_SIZE);
273+
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
274+
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT,
275+
options->keyauth, TPM_DIGEST_SIZE);
276276

277277
/* sensitive */
278278
tpm_buf_append_u16(&sized, options->blobauth_len);
@@ -314,10 +314,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
314314

315315
if (buf.flags & TPM_BUF_OVERFLOW) {
316316
rc = -E2BIG;
317+
tpm2_end_auth_session(chip);
317318
goto out;
318319
}
319320

321+
tpm_buf_fill_hmac_session(chip, &buf);
320322
rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
323+
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
321324
if (rc)
322325
goto out;
323326

@@ -348,6 +351,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
348351
else
349352
payload->blob_len = blob_len;
350353

354+
out_put:
351355
tpm_put_ops(chip);
352356
return rc;
353357
}
@@ -417,25 +421,31 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
417421
if (blob_len > payload->blob_len)
418422
return -E2BIG;
419423

420-
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
424+
rc = tpm2_start_auth_session(chip);
421425
if (rc)
422426
return rc;
423427

424-
tpm_buf_append_u32(&buf, options->keyhandle);
425-
tpm2_buf_append_auth(&buf, TPM2_RS_PW,
426-
NULL /* nonce */, 0,
427-
0 /* session_attributes */,
428-
options->keyauth /* hmac */,
429-
TPM_DIGEST_SIZE);
428+
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
429+
if (rc) {
430+
tpm2_end_auth_session(chip);
431+
return rc;
432+
}
433+
434+
tpm_buf_append_name(chip, &buf, options->keyhandle, NULL);
435+
tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth,
436+
TPM_DIGEST_SIZE);
430437

431438
tpm_buf_append(&buf, blob, blob_len);
432439

433440
if (buf.flags & TPM_BUF_OVERFLOW) {
434441
rc = -E2BIG;
442+
tpm2_end_auth_session(chip);
435443
goto out;
436444
}
437445

446+
tpm_buf_fill_hmac_session(chip, &buf);
438447
rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob");
448+
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
439449
if (!rc)
440450
*blob_handle = be32_to_cpup(
441451
(__be32 *) &buf.data[TPM_HEADER_SIZE]);
@@ -473,20 +483,44 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
473483
u8 *data;
474484
int rc;
475485

476-
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
486+
rc = tpm2_start_auth_session(chip);
477487
if (rc)
478488
return rc;
479489

480-
tpm_buf_append_u32(&buf, blob_handle);
481-
tpm2_buf_append_auth(&buf,
482-
options->policyhandle ?
483-
options->policyhandle : TPM2_RS_PW,
484-
NULL /* nonce */, 0,
485-
TPM2_SA_CONTINUE_SESSION,
486-
options->blobauth /* hmac */,
487-
options->blobauth_len);
490+
rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
491+
if (rc) {
492+
tpm2_end_auth_session(chip);
493+
return rc;
494+
}
495+
496+
tpm_buf_append_name(chip, &buf, blob_handle, NULL);
497+
498+
if (!options->policyhandle) {
499+
tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT,
500+
options->blobauth,
501+
options->blobauth_len);
502+
} else {
503+
/*
504+
* FIXME: The policy session was generated outside the
505+
* kernel so we don't known the nonce and thus can't
506+
* calculate a HMAC on it. Therefore, the user can
507+
* only really use TPM2_PolicyPassword and we must
508+
* send down the plain text password, which could be
509+
* intercepted. We can still encrypt the returned
510+
* key, but that's small comfort since the interposer
511+
* could repeat our actions with the exfiltrated
512+
* password.
513+
*/
514+
tpm2_buf_append_auth(&buf, options->policyhandle,
515+
NULL /* nonce */, 0, 0,
516+
options->blobauth, options->blobauth_len);
517+
tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT,
518+
NULL, 0);
519+
}
488520

521+
tpm_buf_fill_hmac_session(chip, &buf);
489522
rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing");
523+
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
490524
if (rc > 0)
491525
rc = -EPERM;
492526

0 commit comments

Comments
 (0)