diff --git a/0008-mb-support-EV_EFI_HANDOFF_TABLES-events-on-PCR1.patch b/0008-mb-support-EV_EFI_HANDOFF_TABLES-events-on-PCR1.patch new file mode 100644 index 0000000..80fdde9 --- /dev/null +++ b/0008-mb-support-EV_EFI_HANDOFF_TABLES-events-on-PCR1.patch @@ -0,0 +1,29 @@ +From d14e0a132cfedd081bffa7a990b9401d5e257cac Mon Sep 17 00:00:00 2001 +From: Sergio Correia +Date: Fri, 8 Aug 2025 16:40:01 +0100 +Subject: [PATCH 8/9] mb: support EV_EFI_HANDOFF_TABLES events on PCR1 + +Allow EV_EFI_HANDOFF_TABLES events on PCR1 alongside the existing +EV_EFI_HANDOFF_TABLES2 support to handle different firmware +implementations, in the example policy. + +Signed-off-by: Sergio Correia +--- + keylime/mba/elchecking/example.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/keylime/mba/elchecking/example.py b/keylime/mba/elchecking/example.py +index 2c6f699..a3d918a 100644 +--- a/keylime/mba/elchecking/example.py ++++ b/keylime/mba/elchecking/example.py +@@ -185,6 +185,7 @@ class Example(policies.Policy): + # We only expect one EV_NO_ACTION event at the start. + dispatcher.set((0, "EV_NO_ACTION"), tests.OnceTest(tests.AcceptAll())) + dispatcher.set((1, "EV_CPU_MICROCODE"), tests.OnceTest(tests.AcceptAll())) ++ dispatcher.set((1, "EV_EFI_HANDOFF_TABLES"), tests.OnceTest(tests.AcceptAll())) + dispatcher.set((1, "EV_EFI_HANDOFF_TABLES2"), tests.OnceTest(tests.AcceptAll())) + dispatcher.set((0, "EV_S_CRTM_VERSION"), events_final.get("s_crtms")) + dispatcher.set((0, "EV_EFI_PLATFORM_FIRMWARE_BLOB"), events_final.get("platform_firmware_blobs")) +-- +2.47.3 + diff --git a/0009-mb-support-vendor_db-as-logged-by-newer-shim-version.patch b/0009-mb-support-vendor_db-as-logged-by-newer-shim-version.patch new file mode 100644 index 0000000..bcc024e --- /dev/null +++ b/0009-mb-support-vendor_db-as-logged-by-newer-shim-version.patch @@ -0,0 +1,356 @@ +From 607b97ac8d414cb57b1ca89925631d41bd7ac04c Mon Sep 17 00:00:00 2001 +From: Sergio Correia +Date: Fri, 8 Aug 2025 16:41:54 +0100 +Subject: [PATCH 9/9] mb: support vendor_db as logged by newer shim versions + +- Updated example policy to properly handle different event structures + for vendor_db validation: + - KeySubsetMulti for EV_EFI_VARIABLE_DRIVER_CONFIG (has SignatureType field) + - SignatureSetMember for EV_EFI_VARIABLE_AUTHORITY (direct signature format) + +- Added method to extract vendor_db from EV_EFI_VARIABLE_AUTHORITY events + in reference state generation (keylime-policy create measured-boot and + the legacy create_mb_refstate script) +- Made vendor_db optional for backward compatibility + +This fixes attestation failures when vendor_db variables are present but +missing from reference states or validated with incorrect test types. + +See: https://github.com/rhboot/shim/pull/728 +Signed-off-by: Sergio Correia +--- + keylime/mba/elchecking/example.py | 45 +++++++++ + keylime/policy/create_mb_policy.py | 30 ++++++ + scripts/create_mb_refstate | 30 ++++++ + test/test_create_mb_policy.py | 142 +++++++++++++++++++++++++++++ + 4 files changed, 247 insertions(+) + +diff --git a/keylime/mba/elchecking/example.py b/keylime/mba/elchecking/example.py +index a3d918a..5a933ac 100644 +--- a/keylime/mba/elchecking/example.py ++++ b/keylime/mba/elchecking/example.py +@@ -21,6 +21,7 @@ from . import policies, tests + # kek - list of allowed KEK keys + # db - list of allowed db keys + # dbx - list of required dbx keys ++# vendor_db - list of allowed vendor_db keys (optional, for newer shim versions) + # mokdig - list of allowed digests of MoKList (PCR 14 EV_IPL) + # mokxdig - list of allowed digests of MoKListX (PCR 14 EV_IPL) + # kernels - list of allowed { +@@ -121,6 +122,10 @@ class Example(policies.Policy): + if req not in refstate: + raise Exception(f"refstate lacks {req}") + ++ # vendor_db is optional for backward compatibility ++ if "vendor_db" not in refstate: ++ refstate["vendor_db"] = [] ++ + dispatcher = tests.Dispatcher(("PCRIndex", "EventType")) + vd_driver_config = tests.VariableDispatch() + vd_authority = tests.VariableDispatch() +@@ -268,6 +273,34 @@ class Example(policies.Policy): + "db", + db_test, + ) ++ # Support vendor_db as logged by newer shim versions ++ # See: https://github.com/rhboot/shim/pull/728 ++ if not has_secureboot and not refstate["vendor_db"]: ++ vendor_db_test = tests.OnceTest(tests.AcceptAll()) ++ else: ++ vendor_db_test = tests.OnceTest( ++ tests.Or( ++ tests.KeySubsetMulti( ++ ["a159c0a5-e494-a74a-87b5-ab155c2bf072", "2616c4c1-4c50-9240-aca9-41f936934328"], ++ sigs_strip0x(refstate["vendor_db"]), ++ ), ++ tests.KeySubsetMulti( ++ ["a5c059a1-94e4-4aa7-87b5-ab155c2bf072", "c1c41626-504c-4092-aca9-41f936934328"], ++ sigs_strip0x(refstate["vendor_db"]), ++ ), ++ ) ++ ) ++ ++ vd_driver_config.set( ++ "cbb219d7-3a3d-9645-a3bc-dad00e67656f", ++ "vendor_db", ++ vendor_db_test, ++ ) ++ vd_driver_config.set( ++ "d719b2cb-3d3a-4596-a3bc-dad00e67656f", ++ "vendor_db", ++ vendor_db_test, ++ ) + + if not has_secureboot and not refstate["dbx"]: + dbx_test = tests.OnceTest(tests.AcceptAll()) +@@ -295,6 +328,18 @@ class Example(policies.Policy): + vd_db_test = tests.OnceTest(tests.AcceptAll()) + vd_authority.set("cbb219d7-3a3d-9645-a3bc-dad00e67656f", "db", vd_db_test) + vd_authority.set("d719b2cb-3d3a-4596-a3bc-dad00e67656f", "db", vd_db_test) ++ # Support vendor_db as logged by newer shim versions in EV_EFI_VARIABLE_AUTHORITY events ++ # See: https://github.com/rhboot/shim/pull/728 ++ # EV_EFI_VARIABLE_AUTHORITY events have different structure than EV_EFI_VARIABLE_DRIVER_CONFIG ++ # They contain direct signature data without SignatureType field ++ if not has_secureboot and not refstate["vendor_db"]: ++ vendor_db_authority_test = tests.OnceTest(tests.AcceptAll()) ++ else: ++ vendor_db_authority_test = tests.OnceTest( ++ tests.IterateTest(tests.SignatureSetMember(sigs_strip0x(refstate["vendor_db"]))) ++ ) ++ vd_authority.set("cbb219d7-3a3d-9645-a3bc-dad00e67656f", "vendor_db", vendor_db_authority_test) ++ vd_authority.set("d719b2cb-3d3a-4596-a3bc-dad00e67656f", "vendor_db", vendor_db_authority_test) + # Accept all SbatLevels of the Shim, because we already checked the hash of the Shim itself. + vd_sbat_level_test = tests.OnceTest(tests.AcceptAll()) + vd_authority.set("50ab5d60-46e0-0043-abb6-3dd810dd8b23", "SbatLevel", vd_sbat_level_test) +diff --git a/keylime/policy/create_mb_policy.py b/keylime/policy/create_mb_policy.py +index 859e652..b2b48f7 100644 +--- a/keylime/policy/create_mb_policy.py ++++ b/keylime/policy/create_mb_policy.py +@@ -93,6 +93,35 @@ def get_keys(events: List[Dict[str, Any]]) -> Dict[str, List[Any]]: + return out + + ++def get_vendor_db(events: List[Dict[str, Any]]) -> Dict[str, List[Any]]: ++ """Get vendor_db signatures from EV_EFI_VARIABLE_AUTHORITY events.""" ++ out: Dict[str, List[Any]] = {"vendor_db": []} ++ ++ for event in events: ++ if "EventType" not in event: ++ continue ++ if event["EventType"] != "EV_EFI_VARIABLE_AUTHORITY": ++ continue ++ if "Event" not in event or "UnicodeName" not in event["Event"]: ++ continue ++ ++ event_name = event["Event"]["UnicodeName"].lower() ++ if event_name == "vendor_db": ++ data = None ++ if "VariableData" in event["Event"]: ++ data = event["Event"]["VariableData"] ++ ++ if data is not None: ++ # VariableData for EV_EFI_VARIABLE_AUTHORITY is a list of signatures ++ for entry in data: ++ if "SignatureOwner" in entry and "SignatureData" in entry: ++ out["vendor_db"].append( ++ {"SignatureOwner": entry["SignatureOwner"], "SignatureData": f"0x{entry['SignatureData']}"} ++ ) ++ ++ return out ++ ++ + def get_kernel(events: List[Dict[str, Any]], secure_boot: bool) -> Dict[str, List[Dict[str, Any]]]: + """Extract digest for Shim, Grub, Linux Kernel and initrd.""" + out = [] +@@ -259,6 +288,7 @@ def create_mb_refstate(args: argparse.Namespace) -> Optional[Dict[str, object]]: + } + ], + **get_keys(events), ++ **get_vendor_db(events), + **get_mok(events), + **get_kernel(events, has_secureboot), + } +diff --git a/scripts/create_mb_refstate b/scripts/create_mb_refstate +index 23cafb9..c98e61d 100755 +--- a/scripts/create_mb_refstate ++++ b/scripts/create_mb_refstate +@@ -78,6 +78,35 @@ def get_keys(events): + return out + + ++def get_vendor_db(events): ++ """Get vendor_db signatures from EV_EFI_VARIABLE_AUTHORITY events.""" ++ out = {"vendor_db": []} ++ ++ for event in events: ++ if "EventType" not in event: ++ continue ++ if event["EventType"] != "EV_EFI_VARIABLE_AUTHORITY": ++ continue ++ if "Event" not in event or "UnicodeName" not in event["Event"]: ++ continue ++ ++ event_name = event["Event"]["UnicodeName"].lower() ++ if event_name == "vendor_db": ++ data = None ++ if "VariableData" in event["Event"]: ++ data = event["Event"]["VariableData"] ++ ++ if data is not None: ++ # VariableData for EV_EFI_VARIABLE_AUTHORITY is a list of signatures ++ for entry in data: ++ if "SignatureOwner" in entry and "SignatureData" in entry: ++ out["vendor_db"].append( ++ {"SignatureOwner": entry["SignatureOwner"], "SignatureData": f"0x{entry['SignatureData']}"} ++ ) ++ ++ return out ++ ++ + def get_kernel(events, secure_boot): + """ + Extract digest for Shim, Grub, Linux Kernel and initrd. +@@ -197,6 +226,7 @@ def main(): + } + ], + **get_keys(events), ++ **get_vendor_db(events), + **get_mok(events), + **get_kernel(events, has_secureboot), + } +diff --git a/test/test_create_mb_policy.py b/test/test_create_mb_policy.py +index b00d8e7..cd32bda 100644 +--- a/test/test_create_mb_policy.py ++++ b/test/test_create_mb_policy.py +@@ -364,6 +364,148 @@ class CreateMeasuredBootPolicy_Test(unittest.TestCase): + for c in test_cases: + self.assertDictEqual(create_mb_policy.get_mok(c["events"]), c["expected"]) + ++ def test_get_vendor_db(self): ++ test_cases = [ ++ {"events": [], "expected": {"vendor_db": []}}, ++ # No EV_EFI_VARIABLE_AUTHORITY events. ++ { ++ "events": [ ++ { ++ "EventType": "EV_EFI_VARIABLE_DRIVER_CONFIG", ++ "Event": {"UnicodeName": "vendor_db", "VariableData": []}, ++ } ++ ], ++ "expected": {"vendor_db": []}, ++ }, ++ # Good vendor_db event with EV_EFI_VARIABLE_AUTHORITY. ++ { ++ "events": [ ++ { ++ "EventType": "EV_EFI_VARIABLE_AUTHORITY", ++ "Event": { ++ "UnicodeName": "vendor_db", ++ "VariableData": [ ++ { ++ "SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", ++ "SignatureData": "sig-data-1", ++ } ++ ], ++ }, ++ } ++ ], ++ "expected": { ++ "vendor_db": [ ++ {"SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", "SignatureData": "0xsig-data-1"} ++ ] ++ }, ++ }, ++ # Multiple vendor_db signatures. ++ { ++ "events": [ ++ { ++ "EventType": "EV_EFI_VARIABLE_AUTHORITY", ++ "Event": { ++ "UnicodeName": "vendor_db", ++ "VariableData": [ ++ { ++ "SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", ++ "SignatureData": "sig-data-1", ++ }, ++ { ++ "SignatureOwner": "77fa9abd-0359-4d32-bd60-28f4e78f784b", ++ "SignatureData": "sig-data-2", ++ }, ++ ], ++ }, ++ } ++ ], ++ "expected": { ++ "vendor_db": [ ++ {"SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", "SignatureData": "0xsig-data-1"}, ++ {"SignatureOwner": "77fa9abd-0359-4d32-bd60-28f4e78f784b", "SignatureData": "0xsig-data-2"}, ++ ] ++ }, ++ }, ++ # Missing EventType. ++ { ++ "events": [ ++ { ++ "Event": { ++ "UnicodeName": "vendor_db", ++ "VariableData": [ ++ { ++ "SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", ++ "SignatureData": "sig-data-1", ++ } ++ ], ++ } ++ } ++ ], ++ "expected": {"vendor_db": []}, ++ }, ++ # Wrong EventType. ++ { ++ "events": [ ++ { ++ "EventType": "EV_EFI_VARIABLE_DRIVER_CONFIG", ++ "Event": { ++ "UnicodeName": "vendor_db", ++ "VariableData": [ ++ { ++ "SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", ++ "SignatureData": "sig-data-1", ++ } ++ ], ++ }, ++ } ++ ], ++ "expected": {"vendor_db": []}, ++ }, ++ # Missing Event. ++ { ++ "events": [{"EventType": "EV_EFI_VARIABLE_AUTHORITY"}], ++ "expected": {"vendor_db": []}, ++ }, ++ # Missing UnicodeName. ++ { ++ "events": [ ++ { ++ "EventType": "EV_EFI_VARIABLE_AUTHORITY", ++ "Event": { ++ "VariableData": [ ++ { ++ "SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", ++ "SignatureData": "sig-data-1", ++ } ++ ] ++ }, ++ } ++ ], ++ "expected": {"vendor_db": []}, ++ }, ++ # Wrong UnicodeName. ++ { ++ "events": [ ++ { ++ "EventType": "EV_EFI_VARIABLE_AUTHORITY", ++ "Event": { ++ "UnicodeName": "db", ++ "VariableData": [ ++ { ++ "SignatureOwner": "0223eddb-9079-4388-af77-2d65b1c35d3b", ++ "SignatureData": "sig-data-1", ++ } ++ ], ++ }, ++ } ++ ], ++ "expected": {"vendor_db": []}, ++ }, ++ ] ++ ++ for c in test_cases: ++ self.assertDictEqual(create_mb_policy.get_vendor_db(c["events"]), c["expected"]) ++ + def test_get_kernel(self): + test_cases = [ + {"events": [], "secureboot": False, "expected": {}}, +-- +2.47.3 + diff --git a/keylime.spec b/keylime.spec index 3e52794..b935da2 100644 --- a/keylime.spec +++ b/keylime.spec @@ -9,7 +9,7 @@ Name: keylime Version: 7.12.1 -Release: 8%{?dist} +Release: 9%{?dist} Summary: Open source TPM software for Bootstrapping and Maintaining Trust URL: https://github.com/keylime/keylime @@ -30,6 +30,10 @@ Patch: 0006-Revert-default-server_key_password-for-verifier-regi.patch # Backported from https://github.com/keylime/keylime/pull/1782 Patch: 0007-fix_db_connection_leaks.patch +# Backported from https://github.com/keylime/keylime/pull/1791 +Patch: 0008-mb-support-EV_EFI_HANDOFF_TABLES-events-on-PCR1.patch +Patch: 0009-mb-support-vendor_db-as-logged-by-newer-shim-version.patch + License: ASL 2.0 and MIT BuildRequires: git-core @@ -423,6 +427,10 @@ fi %license LICENSE %changelog +* Tue Aug 11 2025 Sergio Correia - 7.12.1-9 +- Support vendor_db as logged by newer shim versions + Resolves: RHEL-8045 + * Fri Aug 08 2025 Anderson Toshiyuki Sasaki - 7.12.1-8 - Fix DB connection leaks Resolves: RHEL-108263