From 1e08f92250178c075a6813f42298a0ab1823a6cc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 2 Jun 2025 13:13:17 +0200 Subject: [PATCH] tpm2: add a clear error message for all errors that suggest a PCR violation Fixes: #35187 --- src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 2 ++ src/shared/creds-util.c | 2 ++ src/shared/cryptsetup-tpm2.c | 6 +++++- src/shared/tpm2-util.h | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c index 956487de77..708d8a7645 100644 --- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c @@ -111,6 +111,8 @@ int acquire_luks2_key( ret_decrypted_key); if (r == -EREMOTE) return log_error_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + 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 tempered with or policy out-of-date: %m"); if (r < 0) return log_error_errno(r, "Failed to unseal secret using TPM2: %m"); diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index 93bf121ccf..384b19293a 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1366,6 +1366,8 @@ int decrypt_credential_and_warn( &tpm2_key); if (r == -EREMOTE) return log_error_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + 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 tempered with or policy out-of-date: %m"); if (r < 0) return log_error_errno(r, "Failed to unseal secret using TPM2: %m"); #else diff --git a/src/shared/cryptsetup-tpm2.c b/src/shared/cryptsetup-tpm2.c index 7fc0bf9fdd..b62b0f8b33 100644 --- a/src/shared/cryptsetup-tpm2.c +++ b/src/shared/cryptsetup-tpm2.c @@ -173,6 +173,8 @@ int acquire_tpm2_key( ret_decrypted_key); if (r == -EREMOTE) return log_error_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + 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 tempered with or policy out-of-date: %m"); if (r < 0) return log_error_errno(r, "Failed to unseal secret using TPM2: %m"); @@ -223,12 +225,14 @@ int acquire_tpm2_key( ret_decrypted_key); if (r == -EREMOTE) return log_error_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + 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 tempered with or policy out-of-date: %m"); if (r < 0) { log_error_errno(r, "Failed to unseal secret using TPM2: %m"); /* We get this error in case there is an authentication policy mismatch. This should * not happen, but this avoids confusing behavior, just in case. */ - if (!IN_SET(r, -EPERM, -ENOLCK)) + if (r != -ENOLCK) continue; } diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index d81c362c44..9b6b143619 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -283,6 +283,9 @@ int tpm2_get_or_create_srk(Tpm2Context *c, const Tpm2Handle *session, TPM2B_PUBL int tpm2_seal(Tpm2Context *c, uint32_t seal_key_handle, const TPM2B_DIGEST policy_hash[], size_t n_policy, const char *pin, struct iovec *ret_secret, struct iovec **ret_blobs, size_t *ret_n_blobs, uint16_t *ret_primary_alg, struct iovec *ret_srk); int tpm2_unseal(Tpm2Context *c, uint32_t hash_pcr_mask, uint16_t pcr_bank, const struct iovec *pubkey, uint32_t pubkey_pcr_mask, sd_json_variant *signature, const char *pin, const Tpm2PCRLockPolicy *pcrlock_policy, uint16_t primary_alg, const struct iovec blobs[], size_t n_blobs, const struct iovec known_policy_hash[], size_t n_known_policy_hash, const struct iovec *srk, struct iovec *ret_secret); +/* tpm2_unseal() returns a bunch of different errors for various flavours of PCR issues, let's group them */ +#define ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r) IN_SET(r, -EREMCHG, -ENOANO, -EUCLEAN, -EPERM) + #if HAVE_OPENSSL int tpm2_tpm2b_public_to_openssl_pkey(const TPM2B_PUBLIC *public, EVP_PKEY **ret); int tpm2_tpm2b_public_from_openssl_pkey(const EVP_PKEY *pkey, TPM2B_PUBLIC *ret);