From: Gabríel Arthúr Pétursson Date: Thu, 4 Jan 2024 15:34:28 +0000 (+0000) Subject: cryptenroll: Support rotating PIN on an existing TPM2 enrollment X-Git-Tag: v256-rc1~936^2 X-Git-Url: http://git-history.diyao.me/?a=commitdiff_plain;h=47ec2c8a8ee53fbdde30dc73747dbbe1ddd7bdfd;p=systemd%2F.git cryptenroll: Support rotating PIN on an existing TPM2 enrollment --- diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index b0937ec684..fb862a3329 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -252,7 +252,8 @@ int enroll_tpm2(struct crypt_device *cd, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, - const char *pcrlock_path) { + const char *pcrlock_path, + int *ret_slot_to_wipe) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *signature_json = NULL; _cleanup_(erase_and_freep) char *base64_encoded = NULL; @@ -261,7 +262,7 @@ int enroll_tpm2(struct crypt_device *cd, const char *node; _cleanup_(erase_and_freep) char *pin_str = NULL; ssize_t base64_encoded_size; - int r, keyslot; + int r, keyslot, slot_to_wipe = -1; TPM2Flags flags = 0; uint8_t binary_salt[SHA256_DIGEST_SIZE] = {}; /* @@ -277,6 +278,7 @@ int enroll_tpm2(struct crypt_device *cd, assert(volume_key_size > 0); assert(tpm2_pcr_values_valid(hash_pcr_values, n_hash_pcr_values)); assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask)); + assert(ret_slot_to_wipe); assert_se(node = crypt_get_device_name(cd)); @@ -416,8 +418,12 @@ int enroll_tpm2(struct crypt_device *cd, log_debug_errno(r, "PCR policy hash not yet enrolled, enrolling now."); else if (r < 0) return r; - else { + else if (use_pin) { + log_debug("This PCR set is already enrolled, re-enrolling anyway to update PIN."); + slot_to_wipe = r; + } else { log_info("This PCR set is already enrolled, executing no operation."); + *ret_slot_to_wipe = slot_to_wipe; return r; /* return existing keyslot, so that wiping won't kill it */ } @@ -487,5 +493,7 @@ int enroll_tpm2(struct crypt_device *cd, return log_error_errno(r, "Failed to add TPM2 JSON token to LUKS2 header: %m"); log_info("New TPM2 token enrolled as key slot %i.", keyslot); + + *ret_slot_to_wipe = slot_to_wipe; return keyslot; } diff --git a/src/cryptenroll/cryptenroll-tpm2.h b/src/cryptenroll/cryptenroll-tpm2.h index 7908b03310..634d7637b9 100644 --- a/src/cryptenroll/cryptenroll-tpm2.h +++ b/src/cryptenroll/cryptenroll-tpm2.h @@ -9,7 +9,7 @@ #if HAVE_TPM2 int load_volume_key_tpm2(struct crypt_device *cd, const char *cd_node, const char *device, void *ret_vk, size_t *ret_vks); -int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t seal_key_handle, const char *device_key, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, const char *pcrlock_path); +int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t seal_key_handle, const char *device_key, Tpm2PCRValue *hash_pcrs, size_t n_hash_pcrs, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, const char *pcrlock_path, int *ret_slot_to_wipe); #else static inline int load_volume_key_tpm2(struct crypt_device *cd, const char *cd_node, const char *device, void *ret_vk, size_t *ret_vks) { return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 76ef3da624..12e7e10d03 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -727,7 +727,7 @@ static int run(int argc, char *argv[]) { _cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(erase_and_freep) void *vk = NULL; size_t vks; - int slot, r; + int slot, slot_to_wipe, r; log_show_color(true); log_parse_environment(); @@ -768,9 +768,21 @@ static int run(int argc, char *argv[]) { break; case ENROLL_TPM2: - slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_seal_key_handle, arg_tpm2_device_key, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin, arg_tpm2_pcrlock); + slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_seal_key_handle, arg_tpm2_device_key, arg_tpm2_hash_pcr_values, arg_tpm2_n_hash_pcr_values, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin, arg_tpm2_pcrlock, &slot_to_wipe); + + if (slot >= 0 && slot_to_wipe >= 0) { + /* Updating PIN on an existing enrollment */ + r = wipe_slots( + cd, + &slot_to_wipe, + /* n_explicit_slots= */ 1, + WIPE_EXPLICIT, + /* by_mask= */ 0, + /* except_slot= */ -1); + if (r < 0) + return r; + } break; - case _ENROLL_TYPE_INVALID: /* List enrolled slots if we are called without anything to enroll or wipe */ if (!wipe_requested()) diff --git a/test/units/testsuite-70.cryptenroll.sh b/test/units/testsuite-70.cryptenroll.sh index 266c5de692..f18ef020a7 100755 --- a/test/units/testsuite-70.cryptenroll.sh +++ b/test/units/testsuite-70.cryptenroll.sh @@ -64,6 +64,13 @@ PASSWORD=foo systemd-cryptenroll --tpm2-device=auto "$IMAGE" systemd-cryptenroll --unlock-tpm2-device=auto --recovery-key "$IMAGE" systemd-cryptenroll --unlock-tpm2-device=auto --tpm2-device=auto --wipe-slot=tpm2 "$IMAGE" +# Add PIN to TPM2 enrollment +NEWPIN=1234 systemd-cryptenroll --unlock-tpm2-device=auto --tpm2-device=auto --tpm2-with-pin=yes "$IMAGE" + +# Change PIN on TPM2 enrollment +PIN=1234 NEWPIN=4321 systemd-cryptenroll --unlock-tpm2-device=auto --tpm2-device=auto --tpm2-with-pin=yes "$IMAGE" +PIN=4321 systemd-cryptenroll --unlock-tpm2-device=auto --recovery-key "$IMAGE" + (! systemd-cryptenroll --fido2-with-client-pin=false) (! systemd-cryptenroll --fido2-with-user-presence=f "$IMAGE" /tmp/foo) (! systemd-cryptenroll --fido2-with-client-pin=1234 "$IMAGE")