]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
measure: make tpm_log_tagged_event() measure CC as well
authorVitaly Kuznetsov <vkuznets@redhat.com>
Fri, 13 Mar 2026 12:02:51 +0000 (13:02 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Wed, 18 Mar 2026 12:35:21 +0000 (12:35 +0000)
tpm_log_tagged_event() only measures the event to the TPM while
tpm_log_ipl_event() measures the event both to the TPM and CC. Fix the
inconsistency.

Note, this is a potentially breaking change for TDX guests as systemd will
now measure more stuff to the MRTD/RTMRs, reference values for attestation may
need to be adjusted.

Found by Claude Code Review.

NEWS
src/boot/measure.c

diff --git a/NEWS b/NEWS
index 8595a285b86f1bafd7e4d924e887610b8eedfe8d..85cc7ac2d1d355c5cffc9072b52d3d7f4e99ab52 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,18 @@
 systemd System and Service Manager
 
+CHANGES WITH 261 in spe:
+
+        Feature Removals and Incompatible Changes:
+
+        * It was discovered that systemd-stub does not measure all the events
+          it measures to the TPM to the hardware CC registers (e.g. Intel TDX
+          RTMRs) using EFI_CC_MEASUREMENT_PROTOCOL. In particular, devicetree,
+          initrd, ucode addons and the UKI profile were only measured to the
+          TPM. The missing measurements got added, however, the expected
+          register values are now changed. This may need to be reflected in the
+          attestation environments which use hardware CC registers and not the
+          TPM quote.
+
 CHANGES WITH 260:
 
         Feature Removals and Incompatible Changes:
index cf3d4254b86cbe596e95bd3f2dfc0edc7bd2c647..085ebde472567ab94600d256a483fd6102aa4540 100644 (file)
@@ -232,6 +232,33 @@ static EFI_STATUS tcg2_log_ipl_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buf
         return EFI_SUCCESS;
 }
 
+static EFI_STATUS tcg2_log_tagged_event(
+                uint32_t pcrindex,
+                EFI_PHYSICAL_ADDRESS buffer,
+                size_t buffer_size,
+                uint32_t event_id,
+                const char16_t *description,
+                bool *ret_measured) {
+
+        EFI_TCG2_PROTOCOL *tpm2;
+        EFI_STATUS err = EFI_SUCCESS;
+
+        assert(ret_measured);
+
+        tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
+        if (!tpm2) {
+                *ret_measured = false;
+                return EFI_SUCCESS;
+        }
+
+        err = tpm2_measure_to_pcr_and_tagged_event_log(tpm2, pcrindex, buffer, buffer_size, event_id, description);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        *ret_measured = true;
+        return EFI_SUCCESS;
+}
+
 static EFI_STATUS cc_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t buffer_size, const char16_t *description, bool *ret_measured) {
         EFI_CC_MEASUREMENT_PROTOCOL *cc;
         EFI_STATUS err = EFI_SUCCESS;
@@ -291,8 +318,8 @@ EFI_STATUS tpm_log_tagged_event(
                 const char16_t *description,
                 bool *ret_measured) {
 
-        EFI_TCG2_PROTOCOL *tpm2;
         EFI_STATUS err;
+        bool tpm_ret_measured, cc_ret_measured;
 
         assert(description || pcrindex == UINT32_MAX);
         assert(event_id > 0);
@@ -300,20 +327,26 @@ EFI_STATUS tpm_log_tagged_event(
         /* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
          * something, or false if measurement was turned off. */
 
-        tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
-        if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */
+        if (pcrindex == UINT32_MAX) { /* PCR disabled? */
                 if (ret_measured)
                         *ret_measured = false;
 
                 return EFI_SUCCESS;
         }
 
-        err = tpm2_measure_to_pcr_and_tagged_event_log(tpm2, pcrindex, buffer, buffer_size, event_id, description);
+        /* Measure into both CC and TPM if both are available to avoid a problem like CVE-2021-42299.
+         * The CC protocol has no tagged-event concept, hence use the IPL event log there. */
+        err = cc_log_event(pcrindex, buffer, buffer_size, description, &cc_ret_measured);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        err = tcg2_log_tagged_event(pcrindex, buffer, buffer_size, event_id, description, &tpm_ret_measured);
         if (err != EFI_SUCCESS)
                 return err;
 
         if (ret_measured)
-                *ret_measured = true;
+                *ret_measured = tpm_ret_measured || cc_ret_measured;
+
         return EFI_SUCCESS;
 }