357 lines
14 KiB
Diff
357 lines
14 KiB
Diff
From 607b97ac8d414cb57b1ca89925631d41bd7ac04c Mon Sep 17 00:00:00 2001
|
|
From: Sergio Correia <scorreia@redhat.com>
|
|
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 <scorreia@redhat.com>
|
|
---
|
|
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
|
|
|