]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2-util: initialize NvPCRs on first extension
authorPaul Meyer <katexochen0@gmail.com>
Mon, 13 Jul 2026 07:47:40 +0000 (09:47 +0200)
committerPaul Meyer <katexochen0@gmail.com>
Wed, 15 Jul 2026 11:25:37 +0000 (13:25 +0200)
Both callers of tpm2_nvpcr_extend_bytes() duplicate the same dance: on
-ENETDOWN, i.e. when the NvPCR isn't anchored yet because
systemd-tpm2-setup hasn't run, they acquire the anchor secret,
initialize the NvPCR, and extend again. Move this into
tpm2_nvpcr_extend_bytes() itself. The only caller-specific bit, whether
the anchor secret shall be synced to /var, is passed in as a parameter.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
src/cryptsetup/cryptsetup.c
src/pcrextend/pcrextend.c
src/shared/tpm2-util.c
src/shared/tpm2-util.h

index e105794bb75643c5b9f0a4b9d8827da7f636ceae..bce07454a93d87b04973d8fa93e0b37887139d0a 100644 (file)
@@ -1138,20 +1138,15 @@ static int measure_keyslot(
         if (!s)
                 return log_oom();
 
-        r = tpm2_nvpcr_extend_bytes(c, /* session= */ NULL, arg_tpm2_measure_keyslot_nvpcr, &IOVEC_MAKE_STRING(s), /* secret= */ NULL, TPM2_EVENT_KEYSLOT, s);
-        if (r == -ENETDOWN) {
-                /* NvPCR is not initialized yet. Do so now. */
-                _cleanup_(iovec_done_erase) struct iovec anchor_secret = {};
-                r = tpm2_nvpcr_acquire_anchor_secret(&anchor_secret, /* sync_secondary= */ false);
-                if (r < 0)
-                        return r;
-
-                r = tpm2_nvpcr_initialize(c, /* session= */ NULL, arg_tpm2_measure_keyslot_nvpcr, &anchor_secret);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to extend NvPCR index '%s' with anchor secret: %m", name);
-
-                r = tpm2_nvpcr_extend_bytes(c, /* session= */ NULL, arg_tpm2_measure_keyslot_nvpcr, &IOVEC_MAKE_STRING(s), /* secret= */ NULL, TPM2_EVENT_KEYSLOT, s);
-        }
+        r = tpm2_nvpcr_extend_bytes(
+                        c,
+                        /* session= */ NULL,
+                        arg_tpm2_measure_keyslot_nvpcr,
+                        &IOVEC_MAKE_STRING(s),
+                        /* secret= */ NULL,
+                        /* sync_secondary_anchor= */ false,
+                        TPM2_EVENT_KEYSLOT,
+                        s);
         if (r < 0)
                 return log_error_errno(r, "Could not extend NvPCR: %m");
 
index 693435f3a4e9e281f9cb3afde53ed6f72e745919..5a98d66b6cdca23d5feb5d95a565ff0bba113b7f 100644 (file)
@@ -373,23 +373,17 @@ static int extend_nvpcr_now(
 
         log_debug("Measuring '%s' into NvPCR index '%s'.", safe, name);
 
-        r = tpm2_nvpcr_extend_bytes(c, /* session= */ NULL, name, &IOVEC_MAKE(data, size), /* secret= */ NULL, event, safe);
-        if (r == -ENETDOWN) {
-                /* NvPCR is not initialized yet. Let's do this now. */
-
-                _cleanup_(iovec_done_erase) struct iovec anchor_secret = {};
-                r = tpm2_nvpcr_acquire_anchor_secret(&anchor_secret, /* sync_secondary= */ !arg_early);
-                if (r < 0)
-                        return r;
-
-                r = tpm2_nvpcr_initialize(c, /* session= */ NULL, name, &anchor_secret);
-                if (r == -ENOBUFS)
-                        return r; /* NV space exhausted; let caller handle gracefully */
-                if (r < 0)
-                        return log_error_errno(r, "Failed to extend NvPCR index '%s' with anchor secret: %m", name);
-
-                r = tpm2_nvpcr_extend_bytes(c, /* session= */ NULL, name, &IOVEC_MAKE(data, size), /* secret= */ NULL, event, safe);
-        }
+        r = tpm2_nvpcr_extend_bytes(
+                        c,
+                        /* session= */ NULL,
+                        name,
+                        &IOVEC_MAKE(data, size),
+                        /* secret= */ NULL,
+                        /* sync_secondary_anchor= */ !arg_early,
+                        event,
+                        safe);
+        if (r == -ENOBUFS)
+                return r; /* NV space exhausted; let caller handle gracefully */
         if (r < 0)
                 return log_error_errno(r, "Could not extend NvPCR: %m");
 
index b57fb092bb33ad7122dc0a3f1a92b556b220606a..3e393f053aadb156410564e088c0d75f2a972121 100644 (file)
@@ -8099,7 +8099,7 @@ int tpm2_nvpcr_get_index(const char *name, uint32_t *ret_nv_index, uint64_t *ret
         return 0;
 }
 
-int tpm2_nvpcr_extend_bytes(
+static int nvpcr_extend_bytes(
                 Tpm2Context *c,
                 const Tpm2Handle *session,
                 const char *name,
@@ -8211,6 +8211,37 @@ int tpm2_nvpcr_extend_bytes(
 #endif
 }
 
+int tpm2_nvpcr_extend_bytes(
+                Tpm2Context *c,
+                const Tpm2Handle *session,
+                const char *name,
+                const struct iovec *data,
+                const struct iovec *secret,
+                bool sync_secondary_anchor,
+                Tpm2UserspaceEventType event_type,
+                const char *description) {
+
+        int r;
+
+        r = nvpcr_extend_bytes(c, session, name, data, secret, event_type, description);
+        if (r != -ENETDOWN)
+                return r;
+
+        /* The NvPCR isn't anchored yet, i.e. systemd-tpm2-setup hasn't run.
+         * Anchor it now and extend again. */
+
+        _cleanup_(iovec_done_erase) struct iovec anchor_secret = {};
+        r = tpm2_nvpcr_acquire_anchor_secret(&anchor_secret, sync_secondary_anchor);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to acquire anchor secret for NvPCR '%s': %m", name);
+
+        r = tpm2_nvpcr_initialize(c, session, name, &anchor_secret);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to initialize NvPCR '%s' with anchor secret: %m", name);
+
+        return nvpcr_extend_bytes(c, session, name, data, secret, event_type, description);
+}
+
 #if HAVE_OPENSSL
 static int tpm2_nvpcr_write_anchor_secret(
                 const char *dir,
index dbe0200840690aa9fc97b950cf1d81a250bb34c7..982a0862cbcf0cf06d58930e7fea00742b92e8e5 100644 (file)
@@ -194,7 +194,7 @@ int tpm2_pcr_extend_bytes(Tpm2Context *c, char **banks, unsigned pcr_index, cons
 #define TPM2_NVPCR_PRIORITY_DEFAULT UINT64_C(1000)
 
 int tpm2_nvpcr_get_index(const char *name, uint32_t *ret_nv_index, uint64_t *ret_priority);
-int tpm2_nvpcr_extend_bytes(Tpm2Context *c, const Tpm2Handle *session, const char *name, const struct iovec *data, const struct iovec *secret, Tpm2UserspaceEventType event_type, const char *description);
+int tpm2_nvpcr_extend_bytes(Tpm2Context *c, const Tpm2Handle *session, const char *name, const struct iovec *data, const struct iovec *secret, bool sync_secondary_anchor, Tpm2UserspaceEventType event_type, const char *description);
 int tpm2_nvpcr_acquire_anchor_secret(struct iovec *ret, bool sync_secondary);
 int tpm2_nvpcr_initialize(Tpm2Context *c, const Tpm2Handle *session, const char *name, const struct iovec *anchor_secret);
 int tpm2_nvpcr_read(Tpm2Context *c, const Tpm2Handle *session, const char *name, struct iovec *ret, uint32_t *ret_nv_index, uint64_t *ret_priority);