storaged: Decode TPM2 slot information

Before this change Cockpit would show the TPM2 slot as "Unknown type",
now we at least show that this slot is configured to use a TPM module
and parse, make additional information available for the UI to later
show if the data is sealed to a Platform Configuration Register (PCR)
state.

Only support removing not editing a TPM2 slot as Cockpit does not
support creating a TPM2 slot.

The Testing Farm has no /dev/tpm available so testing is skipped there.

Resolves: https://redhat.atlassian.net/browse/RHEL-167807
This commit is contained in:
Jelle van der Waa 2026-06-29 12:28:57 +02:00 committed by Jelle van der Waa
parent bc3c959b1b
commit 978ba9055d
4 changed files with 42 additions and 0 deletions

View file

@ -677,6 +677,14 @@ export class CryptoKeyslots extends React.Component {
type: "tang", type: "tang",
url: clevis.tang.url url: clevis.tang.url
}; };
} else if (clevis.pin === "tpm2") {
return {
slot: slot.Index.v,
type: "tpm2",
hash: clevis.tpm2.hash,
key: clevis.tpm2.key,
pcr_ids: clevis.tpm2.pcr_ids,
};
} else { } else {
return { return {
slot: slot.Index.v, slot: slot.Index.v,
@ -754,6 +762,11 @@ export class CryptoKeyslots extends React.Component {
_("Keyserver"), key.url, _("Keyserver"), key.url,
() => edit_clevis_dialog(client, block, key), null, () => edit_clevis_dialog(client, block, key), null,
() => remove_clevis_dialog(client, block, key)); () => remove_clevis_dialog(client, block, key));
} else if (key.type == "tpm2") {
add_row(key.slot,
"TPM2", "",
null, _("TPM2 slots can not be edited here"),
() => remove_clevis_dialog(client, block, key));
} else { } else {
add_row(key.slot, add_row(key.slot,
_("Unknown type"), key.pin, _("Unknown type"), key.pin,

View file

@ -3,6 +3,7 @@
# This simulates the org.freedesktop.UDisks.Encrypted.Slots property # This simulates the org.freedesktop.UDisks.Encrypted.Slots property
# et al for versions of UDisks that don't have them yet. # et al for versions of UDisks that don't have them yet.
# https://github.com/storaged-project/udisks/pull/539
import atexit import atexit
import base64 import base64
@ -42,6 +43,12 @@ def get_clevis_config_from_protected_header(protected_header):
else: else:
subpins[subpin].append(subconf[subpin]) subpins[subpin].append(subconf[subpin])
return {"pin": "sss", "sss": {"t": clevis["sss"]["t"], "pins": subpins}} return {"pin": "sss", "sss": {"t": clevis["sss"]["t"], "pins": subpins}}
elif pin == "tpm2":
return {"pin": pin, "tpm2": {"hash": clevis["tpm2"]["hash"],
"key": clevis["tpm2"]["key"],
"pcr_ids": clevis["tpm2"].get("pcr_ids", ""),
"pcr_bank": clevis["tpm2"].get("pcr_bank", "")
}}
else: else:
return {"pin": pin, pin: {}} return {"pin": pin, pin: {}}

View file

@ -223,6 +223,8 @@ if [ "$PLAN" = "storage-extra" ]; then
TestStorageMountingLUKS.testEncryptedMountingHelp TestStorageMountingLUKS.testEncryptedMountingHelp
TestStorageMountingLUKS.testDuplicateMountPoints TestStorageMountingLUKS.testDuplicateMountPoints
TestStorageMountingLUKS.testNeverAuto TestStorageMountingLUKS.testNeverAuto
TestStorageLuks.testClevisTPM
" "
if [ "$TEST_OS" = "centos-10-bootc" ]; then if [ "$TEST_OS" = "centos-10-bootc" ]; then

View file

@ -335,6 +335,26 @@ class TestStorageLuks(storagelib.StorageCase):
"mount_point": f"{self.mnt_dir}/foo"}) "mount_point": f"{self.mnt_dir}/foo"})
self.wait_mounted("ext4 filesystem") self.wait_mounted("ext4 filesystem")
@testlib.skipImage("no Clevis TPM2 support", "debian-*", "ubuntu-2604")
@testlib.nondestructive
def testClevisTPM(self):
m = self.machine
b = self.browser
disk = self.add_ram_disk()
m.execute(f"echo einszweidrei | cryptsetup luksFormat --pbkdf-memory 32768 {disk}")
# Two TPM2 variants..
m.execute(f"""echo einszweidrei | clevis luks bind -d {disk} tpm2 '{{"hash":"sha256","key":"ecc"}}'""")
m.execute(f"""echo einszweidrei | clevis luks bind -d {disk} tpm2 '{{"hash":"sha256","key":"ecc","pcr_ids":"7,11"}}'""")
self.login_and_go("/storage")
self.click_card_row("Storage", name=disk)
panel = "#encryption-keys "
b.wait_in_text(f"{panel} tr[data-row-slot='0']", "Passphrase")
b.wait_in_text(f"{panel} tr[data-row-slot='1']", "TPM2")
b.wait_in_text(f"{panel} tr[data-row-slot='2']", "TPM2")
@testlib.skipImage('/usr is immutable', 'centos-9-bootc') @testlib.skipImage('/usr is immutable', 'centos-9-bootc')
class TestStorageLuksDestructive(storagelib.StorageCase): class TestStorageLuksDestructive(storagelib.StorageCase):