diff --git a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c index 9c73463deb..af2b2b7477 100644 --- a/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c +++ b/src/cryptsetup/cryptsetup-tokens/cryptsetup-token-systemd-tpm2.c @@ -31,7 +31,7 @@ static int log_debug_open_error(struct crypt_device *cd, int token, int r) { (void) crypt_log_debug_errno(cd, r, "Token %d: no matching TPM2 token data found.", token); return -EPERM; } - if (IN_SET(r, -EREMCHG, -EREMOTE)) { + if (IN_SET(r, -EREMCHG, -EREMOTE, -EADDRNOTAVAIL)) { /* Remap as above. Note: For now without -EUCLEAN because currently the only error it * reports won't be solved by moving to another token. */ (void) crypt_log_debug_errno(cd, r, "Token %d: TPM policy does not match current system state, skipping.", token); diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c index d53b00518c..e88d159474 100644 --- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c @@ -112,7 +112,9 @@ int acquire_luks2_key( srk, ret_decrypted_key); if (r == -EREMOTE) - return log_warning_errno(r, "TPM key integrity check failed or NV index unusable. Key enrolled in superblock most likely does not belong to this TPM."); + return log_warning_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + if (r == -EADDRNOTAVAIL) + return log_warning_errno(r, "NV index referenced by token is missing, unwritten, or unusable, it could be for another system."); if (r == -EILSEQ) return log_error_errno(SYNTHETIC_ERRNO(ENOANO), "Bad PIN."); /* cryptsetup docs say we should return ENOANO on bad PIN */ if (r == -ENOLCK) diff --git a/src/shared/creds-util.c b/src/shared/creds-util.c index eaee54ee57..54a8a9abea 100644 --- a/src/shared/creds-util.c +++ b/src/shared/creds-util.c @@ -1393,6 +1393,8 @@ int decrypt_credential_and_warn( &tpm2_key); if (r == -EREMOTE) 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 (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) @@ -1837,6 +1839,7 @@ static const CredentialsVarlinkError credentials_varlink_error_table[] = { { "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.NVIndexUnusable", EADDRNOTAVAIL, "The NV index referenced by the key is missing, unwritten, or unusable, it could be for another system." }, }; const CredentialsVarlinkError* credentials_varlink_error_by_id(const char *id) { diff --git a/src/shared/cryptsetup-tpm2.c b/src/shared/cryptsetup-tpm2.c index cd7a1506a1..a34c87cb91 100644 --- a/src/shared/cryptsetup-tpm2.c +++ b/src/shared/cryptsetup-tpm2.c @@ -174,7 +174,9 @@ int acquire_tpm2_key( srk, ret_decrypted_key); if (r == -EREMOTE) - return log_warning_errno(r, "TPM key integrity check failed or NV index unusable. Key enrolled in superblock most likely does not belong to this TPM."); + return log_warning_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + if (r == -EADDRNOTAVAIL) + return log_warning_errno(r, "NV index referenced by token is missing, unwritten, or unusable, it could be for another system."); if (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r)) { log_warning_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. */ @@ -232,7 +234,9 @@ int acquire_tpm2_key( srk, ret_decrypted_key); if (r == -EREMOTE) - return log_warning_errno(r, "TPM key integrity check failed or NV index unusable. Key enrolled in superblock most likely does not belong to this TPM."); + return log_warning_errno(r, "TPM key integrity check failed. Key enrolled in superblock most likely does not belong to this TPM."); + if (r == -EADDRNOTAVAIL) + return log_warning_errno(r, "NV index referenced by token is missing, unwritten, or unusable, it could be for another system."); if (ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r)) { log_warning_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. */ diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 3a6afdb95c..11ae999093 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -4753,8 +4753,8 @@ int tpm2_policy_authorize_nv( "Submitted policy does not match policy stored in PolicyAuthorizeNV."); if ((rc & ~(TPM2_RC_N_MASK|TPM2_RC_P)) == TPM2_RC_HANDLE || rc == TPM2_RC_NV_UNINITIALIZED) /* NV index is missing, unwritten, or otherwise unusable for this policy (or: wrong authHandle/policySession). */ - return log_debug_errno(SYNTHETIC_ERRNO(EREMOTE), - "NV index referenced by token is missing, unwritten, or unusable."); + return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), + "NV index referenced by token is missing, unwritten, or unusable, it could be for another system."); if (rc != TSS2_RC_SUCCESS) return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to add AuthorizeNV policy to TPM: %s", @@ -6667,7 +6667,8 @@ int tpm2_unseal(Tpm2Context *c, /* Returns the following errors: * - * -EREMOTE → blob is from a different TPM, or NV index referenced by policy is unusable + * -EREMOTE → blob is from a different TPM + * -EADDRNOTAVAIL → NV index referenced by policy is missing, unwritten, or unusable * -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 diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index 5f60788869..ea69940701 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -54,8 +54,9 @@ int dlopen_tpm2(int log_level); #define ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(r) IN_SET(r, -EREMCHG, -ENOANO, -EUCLEAN, -EPERM) /* Errors that mean the tried TPM2 token does not match the boot state, be it due to wrong PCR state, a - * different PCR signing key/policy, or even a different TPM. The caller should keep trying other tokens. */ -#define ERRNO_IS_NEG_TPM2_TOKEN_MISMATCH(r) IN_SET(r, -EREMCHG, -ENOANO, -EPERM, -ENOSTR, -EREMOTE) + * different PCR signing key/policy, a different TPM, or an unusable NV index. The caller should keep trying + * other tokens. */ +#define ERRNO_IS_NEG_TPM2_TOKEN_MISMATCH(r) IN_SET(r, -EREMCHG, -ENOANO, -EPERM, -ENOSTR, -EREMOTE, -EADDRNOTAVAIL) #if HAVE_TPM2 #ifndef SYSTEMD_CFLAGS_MARKER_TPM2 diff --git a/src/shared/varlink-io.systemd.Credentials.c b/src/shared/varlink-io.systemd.Credentials.c index 975e992f16..cec70e2200 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(NVIndexUnusable); SD_VARLINK_DEFINE_INTERFACE( io_systemd_Credentials, @@ -111,4 +112,6 @@ SD_VARLINK_DEFINE_INTERFACE( SD_VARLINK_SYMBOL_COMMENT("The TPM is in dictionary lockout mode, cannot operate."), &vl_error_TPMInDictionaryLockout, SD_VARLINK_SYMBOL_COMMENT("Unexpected TPM PCR state of the system."), - &vl_error_UnexpectedPCRState); + &vl_error_UnexpectedPCRState, + 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);