From a30858ebc355e3f063aaa0f38313f736da7b5794 Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Mon, 14 Sep 2026 10:41:05 +0200 Subject: [PATCH] creds: add io.systemd.Credentials.PCRsKeptChanging error io.systemd.Credentials.UnexpectedPCRState used to be mapped to EUCLEAN, which now means "a PCR kept being extended while unsealing" rather than "the PCR state does not match the policy". Map it to EPERM instead, which is one of the errnos ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR() covers, and introduce a separate PCRsKeptChanging error for EUCLEAN. Also report the condition explicitly in decrypt_credential_and_warn(), like the other TPM2 unseal callers do. Signed-off-by: Alberto Planas (cherry picked from commit 42f3ac664a320a051267cda3c379558205e1bcab) --- src/shared/creds-util.c | 5 ++++- src/shared/varlink-io.systemd.Credentials.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 7fbddf7a27..766da2c9d5 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1534,6 +1534,8 @@ int decrypt_credential_and_warn( return log_error_errno(r, "TPM key integrity check failed. Key most likely does not belong to this TPM."); if (r == -EADDRNOTAVAIL) return log_error_errno(r, "NV index referenced by key is missing, unwritten, or unusable, it could be for another system."); + if (r == -EUCLEAN) + return log_error_errno(r, "PCR values kept changing while unsealing the TPM2 secret, giving up. Something on this system extends a PCR continuously."); if (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r)) return log_error_errno(r, "TPM policy does not match current system state. Either system has been tampered with or policy out-of-date: %m"); if (r < 0) @@ -1985,7 +1987,8 @@ static const CredentialsVarlinkError credentials_varlink_error_table[] = { { "io.systemd.Credentials.NullKeyNotAllowed", EHWPOISON, "The key was encrypted with a null key, but that's not allowed during decryption." }, { "io.systemd.Credentials.KeyBelongsToOtherTPM", EREMOTE, "The TPM integrity check for this key failed, key probably belongs to another TPM, or was corrupted." }, { "io.systemd.Credentials.TPMInDictionaryLockout", ENOLCK, "The TPM is in dictionary lockout mode, cannot operate." }, - { "io.systemd.Credentials.UnexpectedPCRState" , EUCLEAN, "Unexpected TPM PCR state of the system." }, + { "io.systemd.Credentials.UnexpectedPCRState", EPERM, "Unexpected TPM PCR state of the system." }, + { "io.systemd.Credentials.PCRsKeptChanging", EUCLEAN, "PCR values kept changing while unsealing the TPM2 secret, something on this system extends a PCR continuously." }, { "io.systemd.Credentials.NVIndexUnusable", EADDRNOTAVAIL, "The NV index referenced by the key is missing, unwritten, or unusable, it could be for another system." }, }; diff --git a/src/shared/varlink-io.systemd.Credentials.c b/src/shared/varlink-io.systemd.Credentials.c index d44af7e5f8..620c4f6f51 100644 --- a/src/shared/varlink-io.systemd.Credentials.c +++ b/src/shared/varlink-io.systemd.Credentials.c @@ -79,6 +79,7 @@ static SD_VARLINK_DEFINE_ERROR(NullKeyNotAllowed); static SD_VARLINK_DEFINE_ERROR(KeyBelongsToOtherTPM); static SD_VARLINK_DEFINE_ERROR(TPMInDictionaryLockout); static SD_VARLINK_DEFINE_ERROR(UnexpectedPCRState); +static SD_VARLINK_DEFINE_ERROR(PCRsKeptChanging); static SD_VARLINK_DEFINE_ERROR(NVIndexUnusable); SD_VARLINK_DEFINE_INTERFACE( @@ -113,5 +114,7 @@ SD_VARLINK_DEFINE_INTERFACE( &vl_error_TPMInDictionaryLockout, SD_VARLINK_SYMBOL_COMMENT("Unexpected TPM PCR state of the system."), &vl_error_UnexpectedPCRState, + SD_VARLINK_SYMBOL_COMMENT("PCR values kept changing while unsealing the TPM2 secret, something on this system extends a PCR continuously."), + &vl_error_PCRsKeptChanging, SD_VARLINK_SYMBOL_COMMENT("The NV index referenced by the key is missing, unwritten, or unusable, it could be for another system."), &vl_error_NVIndexUnusable);