Add salted HMAC session with AES-128-CFB parameter encryption for TPM seal/unseal#5711
Conversation
|
Unit-tests covers the general and upgrade tests, but I need to test this manually too, in addition I want to test this with my snooping script to make sure everything is actually getting encrypted, |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5711 +/- ##
==========================================
+ Coverage 19.52% 29.10% +9.57%
==========================================
Files 19 25 +6
Lines 3021 4522 +1501
==========================================
+ Hits 590 1316 +726
- Misses 2310 2946 +636
- Partials 121 260 +139 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
eac2fb3 to
9882322
Compare
|
@shjala is there a way to detect that TPM is not a standalone chip? in case of TPM integrated into e.g CPU or ASIC when the bus is not exposed we can reduce complexity and probability of failure if we fallback to unencrypted session. But of course encryption makes power dissipation and similar attacks harder |
I don't know of any reliable way to detect this except by maintaining a list of vendors and firmwares. Besides, PR detects if TPM is not compatible and switches to legacy mode. |
9882322 to
629613a
Compare
|
Is there something we should add to SECURITY-ARCHITECTURE.md about this? |
@eriknordmark good idea, I'll add another commit. |
8513503 to
c698545
Compare
|
@eriknordmark Changes:
|
c698545 to
2626abb
Compare
I don't understand how this can be tested. After an EVE update the PCRs will not match hence the new version of EVE will go through the attestation path and then receive the encrypted vault key from the controller. After that will it not use the encrypted approach to seal it under the new PCRs? |
My mistake, I was thinking about the sealed key format rather than the actual operation requirements.
Yes it will, it defaults to encrypted sessions after the upgrade (even during the initial boot after upgrade and receiving the backup key from controller). |
|
A yetus thing to fix or silence: |
|
This doesn't run eden due to the bug with an attempt to fix in #5806 |
1729674 to
a990a67
Compare
Rebased on master. |
|
Note that 4/4 eden smoke tests fail in the known FAIL: TestHWInventory |
|
@shjala can you update the go.mod for the sniffer tool? The PR adds a new tests/tpm/sniffer/go.mod that declares go 1.22.5, which the Other go.mod files in the repo are already on Go 1.24.x — so the go directive |
@eriknordmark is this a known error? what's causing it? I don't think I've seen it before |
Claude claims the fix is just to change but it makes sense to manually check that a go mod tidy isn't needed. |
@europaul 90+% of the current Eden smoke failures I see are like this one. |
eriknordmark
left a comment
There was a problem hiding this comment.
Please fix the scan-pr / osv-scan: tests/tpm/sniffer/go.mod
a990a67 to
e03dcce
Compare
… seal/unseal Protect the disk encryption key on the CPU-TPM bus by using salted HMAC sessions with AES-128-CFB parameter encryption for seal and unseal operations. The session salt is encrypted with the EK public key. TPMs that do not support AES-128-CFB (probed via TPM2_TestParms) fall back to the legacy unencrypted seal/unseal path, preserving compatibility with all hardware. The sealed blob format is kept compatible with the legacy API to support both upgrade and rollback scenarios. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Add the go-tpm library as a vendor dependency. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
TPM unit tests in prep-and-test.sh were silently passing in CI even when individual tests failed, This commit fixes the root causes and ensures CI fails when any test fails. Fixes: - Build libtpms v0.10.0 and swtpm (commit 732bbd6) from source to match pkg/vtpm/Dockerfile, avoiding "Unknown option 'terminate'" and version mismatch errors with distro packages - Build ZFS from source and purge distro ZFS/libtpms before building to prevent DSO conflicts (zpool_search_import, libzfs_core missing symbols) - Create the EK with the standard EK auth policy so both msrv's policy-session-based ActivateCredential and vcomlink's plain-password ActivateCredential work against the same handle - Store a self-signed cert in the EK NV index for vcomlink EK cert tests - Run all TPM tests via a run_test() wrapper that accumulates failures and exits non-zero at the end, so CI catches individual failures without aborting the rest of the suite Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Run TPM test before genric go tests. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Add a TPM sniffer to capture the communication between the TPM and the host during the tests. This will help us analyze the parameters being sent to the TPM and identify any potential issues. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Add sniffer mode to TPM test script for traffic interception and analysis. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Add script to run TPM tests in a Docker container, this is used for debugging and development of the TPM tests in envirnonments that mimic the CI environment. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Add TPM bus protection details via parameter encryption. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
When UnsealDiskKey fails and we fall back to RecoverDiskKeyPolicyPcr, the original unseal error was silently discarded. Add a log parameter to UnsealDiskKeyWithRecovery and log the initial unseal failure as a warning before attempting recovery. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
Pass the actual PCR digest to PolicyPCR during the trial session so the policy digest is computed correctly. Also set AdminWithPolicy and the required null scheme on the keyed hash object as mandated by the TPM spec. Signed-off-by: Shahriyar Jalayeri <shahriyar@posteo.de>
e03dcce to
1ccc6ae
Compare
|
changes :
|
|
@eriknordmark @rene please do not merge, I want to add another commit. |
I initially wanted to secure our Endorsement Key validation against bus interception by storing the trusted EK Name in a permanently locked NV index on first boot. The plan was to read the TPM EK on subsequent boots and compare it securely against this locked index value. But we run into a chicken and egg problem. Because communication between the CPU and TPM is unencrypted by default (we are trying to solve this here), we must use a Salted HMAC Session to encrypt the bus and prevent attacker forging the locked NV read response, in order to do that we must trust EK as it is used for encrypting salt for encrypted communication 🐔🥚. Anyways, this is ready for final review. |
Is another commit comming? And what about the CVE scan/go.mod version issue for the snooper? |
@eriknordmark fix the CVE issue already 6a11283, another commit was this #5711 (comment) which I found it is not going to work. |

Description
72d915f Protect the disk encryption key on the CPU-TPM bus by using salted HMAC sessions with AES-128-CFB parameter encryption for seal and unseal operations. The session salt is encrypted with the EK public key.
TPMs that do not support AES-128-CFB (probed via TPM2_TestParms) fall back to the legacy unencrypted seal/unseal path, preserving compatibility with all hardware. The sealed blob format is kept compatible with the legacy API to support both upgrade and rollback scenarios.
8929afe fixes silently failing TPM unit tests in CI.
Seal (Create): plaintext vs. encrypted on the wire
The same secret (
"secret", 6 bytes) is sealed in two test paths. The difference is visible directly in theCreatecommand bytes captured by the sniffer.TestSealUnsealLegacy- no parameter encryption:The legacy path uses a password session (
TPM_RS_PW = 0x40000009). TheinSensitiveis sent in plaintext:TestSealUnseal- with AES-128-CFB parameter encryption:The encrypted path uses an HMAC session with AES-128-CFB. The client encrypts
inSensitivebefore sending."secret"is not visible anywhere in the command.Unseal response: plaintext vs. ciphertext on the wire
TestSealUnsealLegacy- no parameter encryption:Unseal command, the
outDatacomes back in plaintext:TestSealUnseal- with AES-128-CFB parameter encryption :Unseal command, the TPM AES-128-CFB encrypts
outDatabefore putting it on the bus.PR dependencies
N/A
How to test and validate this PR
Unit tests
The following unit tests in cover the new functionality.
TestSealUnsealSealDiskKey/UnsealDiskKeyAPI round-trip (exercises the AES-CFB dispatch logic)TestSealUnsealWithParamEncsealDiskKeyEncrypted/unsealDiskKeyEncrypted, plus unseal failure after PCR extendTestSealUnsealLegacysealDiskKeyLegacy/unsealDiskKeyLegacyTestSealLegacyUnsealModernTestSealModernUnsealLegacyRun with:
Manual validation
"TPM supports AES-128-CFB, sealing with parameter encryption".Changelog notes
Seal/unseal of the disk encryption key now uses AES-128-CFB parameter encryption on the CPU-TPM bus to prevent passive bus snooping, with automatic fallback for TPMs that lack AES support.
PR Backports
N/A
Checklist
For backport PRs (remove it if it's not a backport):
And the last but not least:
check them.
Please, check the boxes above after submitting the PR in interactive mode.