From: Paul Meyer Date: Mon, 13 Jul 2026 07:47:40 +0000 (+0200) Subject: tpm2-util: initialize NvPCRs on first extension X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dcf86d1529f438fc71eea366e25d985c951b6928;p=thirdparty%2Fsystemd.git tpm2-util: initialize NvPCRs on first extension 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 --- diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index e105794bb75..bce07454a93 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -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"); diff --git a/src/pcrextend/pcrextend.c b/src/pcrextend/pcrextend.c index 693435f3a4e..5a98d66b6cd 100644 --- a/src/pcrextend/pcrextend.c +++ b/src/pcrextend/pcrextend.c @@ -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"); diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index b57fb092bb3..3e393f053aa 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -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, diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index dbe02008406..982a0862cbc 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -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);