various tweaks for systemd-creds & related (#38979)

This commit is contained in:
Yu Watanabe
2025-09-19 16:21:12 +09:00
committed by GitHub
6 changed files with 130 additions and 62 deletions
+39 -14
View File
@@ -1201,6 +1201,19 @@ int decrypt_credential_and_warn(
assert(iovec_is_valid(input));
assert(ret);
/* Relevant error codes:
*
* -EBADMSG → Corrupted file
* -EOPNOTSUPP → Unsupported file type (could be: requires TPM but we have no TPM)
* -EHOSTDOWN → Need PCR signature file, but couldn't find it
* -EHWPOISON → Attempt to decode NULL key (and CREDENTIAL_ALLOW_NULL is off), but the system has a TPM and SecureBoot is on
* -EMEDIUMTYPE → File has unexpected scope, i.e. user-scoped credential is attempted to be unlocked in system scope, or vice versa
* -EDESTADDRREQ → Credential is incorrectly named (i.e. the authenticated name does not match the actual name)
* -ESTALE → Credential's valdity has passed
* -ESRCH → User specified for scope does not exist on this system
*
* (plus the various error codes tpm2_unseal() returns) */
h = (struct encrypted_credential_header*) input->iov_base;
/* The ID must fit in, for the current and all future formats */
@@ -1218,8 +1231,10 @@ int decrypt_credential_and_warn(
if (with_tpm2_pk) {
r = tpm2_load_pcr_signature(tpm2_signature_path, &signature_json);
if (r == -ENOENT)
return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN), "Couldn't find PCR signature file: %m");
if (r < 0)
return log_error_errno(r, "Failed to load pcr signature: %m");
return log_error_errno(r, "Failed to load PCR signature: %m");
}
if (with_null && !FLAGS_SET(flags, CREDENTIAL_ALLOW_NULL)) {
@@ -1234,7 +1249,7 @@ int decrypt_credential_and_warn(
if (efi_has_tpm2()) {
if (is_efi_secure_boot())
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
return log_error_errno(SYNTHETIC_ERRNO(EHWPOISON),
"Credential uses fixed key for fallback use when TPM2 is absent — but TPM2 is present, and SecureBoot is enabled, refusing.");
log_warning("Credential uses fixed key for use when TPM2 is absent, but TPM2 is present! Accepting anyway, since SecureBoot is disabled.");
@@ -1354,7 +1369,7 @@ int decrypt_credential_and_warn(
/* srk= */ NULL,
&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.");
return log_error_errno(r, "TPM key integrity check failed. Key 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)
@@ -1486,7 +1501,7 @@ int decrypt_credential_and_warn(
if (r < 0 && r != -ENXIO)
log_debug_errno(r, "Failed to parse $SYSTEMD_CREDENTIAL_VALIDATE_NAME: %m");
if (r != 0)
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Embedded credential name '%s' does not match filename '%s', refusing.", embedded_name, validate_name);
return log_error_errno(SYNTHETIC_ERRNO(EDESTADDRREQ), "Embedded credential name '%s' does not match filename '%s', refusing.", embedded_name, validate_name);
log_debug("Embedded credential name '%s' does not match expected name '%s', but configured to use credential anyway.", embedded_name, validate_name);
}
@@ -1637,16 +1652,26 @@ int ipc_decrypt_credential(const char *validate_name, usec_t validate_timestamp,
if (r < 0)
return log_error_errno(r, "Failed to call Decrypt() varlink call.");
if (!isempty(error_id)) {
if (streq(error_id, "io.systemd.Credentials.BadFormat"))
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Bad credential format.");
if (streq(error_id, "io.systemd.Credentials.NameMismatch"))
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "Name in credential doesn't match expectations.");
if (streq(error_id, "io.systemd.Credentials.TimeMismatch"))
return log_error_errno(SYNTHETIC_ERRNO(ESTALE), "Outside of credential validity time window.");
if (streq(error_id, "io.systemd.Credentials.NoSuchUser"))
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "No such user.");
if (streq(error_id, "io.systemd.Credentials.BadScope"))
return log_error_errno(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Scope mismtach.");
static struct {
const char *id;
int errnum;
const char *msg;
} table[] = {
{ "io.systemd.Credentials.BadFormat", EBADMSG, "Bad credential format." },
{ "io.systemd.Credentials.NameMismatch", EDESTADDRREQ, "Name in credential doesn't match expectations." },
{ "io.systemd.Credentials.TimeMismatch", ESTALE, "Outside of credential validity time window." },
{ "io.systemd.Credentials.NoSuchUser", ESRCH, "No such user." },
{ "io.systemd.Credentials.BadScope", EMEDIUMTYPE, "Scope mismatch." },
{ "io.systemd.Credentials.CantFindPCRSignature", EHOSTDOWN, "PCR signature required for decryption, but could not be found." },
{ "io.systemd.Credentials.NullKeyNotAllowed", EHWPOISON, "The key was encrypted with a null key, but that's now allowed during decryption." },
{ "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." },
};
FOREACH_ELEMENT(i, table)
if (streq(i->id, error_id))
return log_error_errno(SYNTHETIC_ERRNO(i->errnum), "%s", i->msg);
return log_error_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to decrypt: %s", error_id);
}
+16 -1
View File
@@ -44,6 +44,11 @@ static SD_VARLINK_DEFINE_ERROR(NameMismatch);
static SD_VARLINK_DEFINE_ERROR(TimeMismatch);
static SD_VARLINK_DEFINE_ERROR(NoSuchUser);
static SD_VARLINK_DEFINE_ERROR(BadScope);
static SD_VARLINK_DEFINE_ERROR(CantFindPCRSignature);
static SD_VARLINK_DEFINE_ERROR(NullKeyNotAllowed);
static SD_VARLINK_DEFINE_ERROR(KeyBelongsToOtherTPM);
static SD_VARLINK_DEFINE_ERROR(TPMInDictionaryLockout);
static SD_VARLINK_DEFINE_ERROR(UnexpectedPCRState);
SD_VARLINK_DEFINE_INTERFACE(
io_systemd_Credentials,
@@ -62,4 +67,14 @@ SD_VARLINK_DEFINE_INTERFACE(
SD_VARLINK_SYMBOL_COMMENT("The specified user does not exist."),
&vl_error_NoSuchUser,
SD_VARLINK_SYMBOL_COMMENT("The credential does not match the selected scope."),
&vl_error_BadScope);
&vl_error_BadScope,
SD_VARLINK_SYMBOL_COMMENT("PCR signature required for decryption, but not found."),
&vl_error_CantFindPCRSignature,
SD_VARLINK_SYMBOL_COMMENT("The key was encrypted with a null key, but that's now allowed during decryption."),
&vl_error_NullKeyNotAllowed,
SD_VARLINK_SYMBOL_COMMENT("The TPM integrity check for this key failed, key probably belongs to another TPM, or was corrupted."),
&vl_error_KeyBelongsToOtherTPM,
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);