cryptenroll: Support rotating PIN on an existing TPM2 enrollment

This commit is contained in:
Gabríel Arthúr Pétursson
2024-01-04 15:34:28 +00:00
parent 631cf7f004
commit 47ec2c8a8e
4 changed files with 34 additions and 7 deletions

View File

@@ -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;
}

View File

@@ -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),

View File

@@ -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);
break;
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())

View File

@@ -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")