]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptsetup: Report mismatching TPM token error separately
authorKai Lüke <kai@amutable.com>
Mon, 20 Apr 2026 06:47:45 +0000 (15:47 +0900)
committerKai Lüke <pothos@users.noreply.github.com>
Fri, 10 Jul 2026 06:07:47 +0000 (08:07 +0200)
When we enroll two UKIs with different PCR pub keys into one LUKS slot/
token each, then we can encounter the wrong one and should report it
with a clearer error than the generic "Failed to unseal secret using
TPM2".
So when we don't have the right signature, report this as separate
error.

src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c
src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
src/shared/cryptsetup-tpm2.c
src/shared/tpm2-util.c

index 450399ec129ab9bd127192c4057e4ceb367fbd4d..d8d233fabb6ccbe0c2d870d057ede2260dc19bf1 100644 (file)
@@ -26,7 +26,7 @@ _public_ const char *cryptsetup_token_version(void) {
 static int log_debug_open_error(struct crypt_device *cd, int r) {
         if (r == -EAGAIN)
                 return crypt_log_debug_errno(cd, r, "TPM2 device not found.");
-        if (r == -ENXIO)
+        if (r == -ENOSTR)
                 return crypt_log_debug_errno(cd, r, "No matching TPM2 token data found.");
 
         return crypt_log_debug_errno(cd, r, TOKEN_NAME " open failed: %m.");
index edc0e7de5bc774244fd87f88ee7a3e1bf1727f34..b611aab83fe2fb0941713203f469b550e748ad7f 100644 (file)
@@ -119,6 +119,8 @@ int acquire_luks2_key(
                 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 (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)
                 return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
 
index 5d68f9bba4691b354ba991978643359cea83e5e5..f536cb8113ad9f4cdb4ffedec3d9a8b070b4ef0d 100644 (file)
@@ -177,6 +177,8 @@ int acquire_tpm2_key(
                         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 == -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)
                         return log_error_errno(r, "Failed to unseal secret using TPM2: %m");
 
@@ -230,6 +232,8 @@ int acquire_tpm2_key(
                         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 == -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)
                         return log_error_errno(r, "TPM is in dictionary attack lock-out mode.");
                 if (r == -EILSEQ) {
index 27606ab73d04ce68b67b8cd142dcb942cc70cd65..a60eca51acbb43a181314ea3481ccb0f6a6fc3a7 100644 (file)
@@ -4241,7 +4241,7 @@ static int find_signature(
         /* First, find field by bank */
         b = sd_json_variant_by_key(v, k);
         if (!b)
-                return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Signature lacks data for PCR bank '%s'.", k);
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOSTR), "Signature lacks data for PCR bank '%s'.", k);
 
         if (!sd_json_variant_is_array(b))
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Bank data is not a JSON array.");
@@ -4311,7 +4311,7 @@ static int find_signature(
                 return sd_json_variant_unbase64(sigj, ret_signature, ret_signature_size);
         }
 
-        return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Couldn't find signature for this PCR bank, PCR index and public key.");
+        return log_debug_errno(SYNTHETIC_ERRNO(ENOSTR), "Couldn't find signature for this PCR bank, PCR index and public key.");
 #else /* HAVE_OPENSSL */
         return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "OpenSSL support is disabled.");
 #endif
@@ -6661,6 +6661,7 @@ int tpm2_unseal(Tpm2Context *c,
         /* Returns the following errors:
          *
          *   -EREMOTE         → blob is from a different TPM
+         *   -ENOSTR          → signature JSON has no matching entry for the current PCR policy
          *   -EDEADLK         → couldn't create primary key because authorization failure
          *   -ENOLCK          → TPM is in dictionary lockout mode
          *   -EREMCHG         → submitted policy doesn't match NV index stored policy (in case of PolicyAuthorizeNV)