]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2: add a clear error message for all errors that suggest a PCR violation
authorLennart Poettering <lennart@poettering.net>
Mon, 2 Jun 2025 11:13:17 +0000 (13:13 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 3 Jun 2025 14:16:46 +0000 (16:16 +0200)
Fixes: #35187
src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
src/shared/creds-util.c
src/shared/cryptsetup-tpm2.c
src/shared/tpm2-util.h

index 956487de772a11ac4b56cdf3e66b73af161d575b..708d8a7645946bb0f06af510a463edb4b39ff349 100644 (file)
@@ -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");
 
index 93bf121ccff2919813956149bad0520e8162c068..384b19293a3df77df2ae7c682034927ede22263c 100644 (file)
@@ -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
index 7fc0bf9fdd83d4e39039675afefa7230dd7f78f4..b62b0f8b33274d15729b5dd59dee76a409eb957b 100644 (file)
@@ -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;
                 }
 
index d81c362c4459bfe6ad97d6e92f434d8bac815978..9b6b143619f293ef400a74ef5da6c0619c51556a 100644 (file)
@@ -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);