]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptsetup: Remap bad PCR set early to EPERM
authorKai Lüke <kai@amutable.com>
Mon, 20 Apr 2026 14:07:13 +0000 (23:07 +0900)
committerKai Lüke <pothos@users.noreply.github.com>
Fri, 10 Jul 2026 06:07:47 +0000 (08:07 +0200)
Currently libcryptsetup's look treats ENOANO special because it's used
to signal PIN requirement. But the bad PCR set can also contain ENOANO
for a mismatch from a PolicyOR branch.
To continue iterating, remap the bad PCR set to EPERM early. This would
in theory also allow us to simplify the matching for the iteration
condition but we leave this as is for now to prevent a future
regression.

src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
src/shared/cryptsetup-tpm2.c

index 40bc2a8f6fded26763cd98edd9aab769ab03d130..761eb1f7193d4d8bd4df9a1c1fe3caad9be4cf18 100644 (file)
@@ -117,8 +117,11 @@ int acquire_luks2_key(
                 return log_error_errno(SYNTHETIC_ERRNO(ENOANO), "Bad PIN."); /* cryptsetup docs say we should return ENOANO on bad PIN */
         if (r == -ENOLCK)
                 return log_error_errno(r, "TPM is in dictionary attack lock-out mode.");
-        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 (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r)) {
+                log_error_errno(r, "TPM policy does not match current system state. Either system has been tempered with or policy out-of-date: %m");
+                /* Normalize to -EPERM so callers don't confuse it with -ENOANO's "needs PIN" meaning. */
+                return -EPERM;
+        }
         if (r == -ENOSTR)
                 return log_error_errno(r, "No signature for current PCR policy in TPM2 signature JSON, token does not apply to current boot state: %m");
         if (r < 0)
index c8c99cacba2a1474fc70742cca242e86de65e54e..66fbfeb18b82e6381dc0af8558f41802fd4f9eca 100644 (file)
@@ -175,8 +175,11 @@ int acquire_tpm2_key(
                                 ret_decrypted_key);
                 if (r == -EREMOTE)
                         return log_error_errno(r, "TPM key integrity check failed or NV index unusable. 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 (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r)) {
+                        log_error_errno(r, "TPM policy does not match current system state. Either system has been tempered with or policy out-of-date: %m");
+                        /* Normalize to -EPERM so callers don't confuse it with -ENOANO's "needs PIN" meaning. */
+                        return -EPERM;
+                }
                 if (r == -ENOSTR)
                         return log_error_errno(r, "No signature for current PCR policy in TPM2 signature JSON, token does not apply to current boot state: %m");
                 if (r < 0)
@@ -230,8 +233,11 @@ int acquire_tpm2_key(
                                 ret_decrypted_key);
                 if (r == -EREMOTE)
                         return log_error_errno(r, "TPM key integrity check failed or NV index unusable. 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 (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r)) {
+                        log_error_errno(r, "TPM policy does not match current system state. Either system has been tempered with or policy out-of-date: %m");
+                        /* Normalize to -EPERM so callers don't confuse it with -ENOANO's "needs PIN" meaning. */
+                        return -EPERM;
+                }
                 if (r == -ENOSTR)
                         return log_error_errno(r, "No signature for current PCR policy in TPM2 signature JSON, token does not apply to current boot state: %m");
                 if (r == -ENOLCK)