cryptenroll: Support rotating PIN on an existing TPM2 enrollment

This commit is contained in:
Gabríel Arthúr Pétursson
2024-02-01 13:55:17 +00:00
parent 631cf7f004
commit 47ec2c8a8e
4 changed files with 34 additions and 7 deletions
+11 -3
View File
@@ -252,7 +252,8 @@ int enroll_tpm2(struct crypt_device *cd,
uint32_t pubkey_pcr_mask, uint32_t pubkey_pcr_mask,
const char *signature_path, const char *signature_path,
bool use_pin, 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_(json_variant_unrefp) JsonVariant *v = NULL, *signature_json = NULL;
_cleanup_(erase_and_freep) char *base64_encoded = NULL; _cleanup_(erase_and_freep) char *base64_encoded = NULL;
@@ -261,7 +262,7 @@ int enroll_tpm2(struct crypt_device *cd,
const char *node; const char *node;
_cleanup_(erase_and_freep) char *pin_str = NULL; _cleanup_(erase_and_freep) char *pin_str = NULL;
ssize_t base64_encoded_size; ssize_t base64_encoded_size;
int r, keyslot; int r, keyslot, slot_to_wipe = -1;
TPM2Flags flags = 0; TPM2Flags flags = 0;
uint8_t binary_salt[SHA256_DIGEST_SIZE] = {}; uint8_t binary_salt[SHA256_DIGEST_SIZE] = {};
/* /*
@@ -277,6 +278,7 @@ int enroll_tpm2(struct crypt_device *cd,
assert(volume_key_size > 0); assert(volume_key_size > 0);
assert(tpm2_pcr_values_valid(hash_pcr_values, n_hash_pcr_values)); assert(tpm2_pcr_values_valid(hash_pcr_values, n_hash_pcr_values));
assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask)); assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask));
assert(ret_slot_to_wipe);
assert_se(node = crypt_get_device_name(cd)); 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."); log_debug_errno(r, "PCR policy hash not yet enrolled, enrolling now.");
else if (r < 0) else if (r < 0)
return r; 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."); 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 */ 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"); 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); log_info("New TPM2 token enrolled as key slot %i.", keyslot);
*ret_slot_to_wipe = slot_to_wipe;
return keyslot; return keyslot;
} }
+1 -1
View File
@@ -9,7 +9,7 @@
#if HAVE_TPM2 #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 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 #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) { 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), return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+15 -3
View File
@@ -727,7 +727,7 @@ static int run(int argc, char *argv[]) {
_cleanup_(crypt_freep) struct crypt_device *cd = NULL; _cleanup_(crypt_freep) struct crypt_device *cd = NULL;
_cleanup_(erase_and_freep) void *vk = NULL; _cleanup_(erase_and_freep) void *vk = NULL;
size_t vks; size_t vks;
int slot, r; int slot, slot_to_wipe, r;
log_show_color(true); log_show_color(true);
log_parse_environment(); log_parse_environment();
@@ -768,9 +768,21 @@ static int run(int argc, char *argv[]) {
break; break;
case ENROLL_TPM2: 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);
break;
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: case _ENROLL_TYPE_INVALID:
/* List enrolled slots if we are called without anything to enroll or wipe */ /* List enrolled slots if we are called without anything to enroll or wipe */
if (!wipe_requested()) if (!wipe_requested())
+7
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 --recovery-key "$IMAGE"
systemd-cryptenroll --unlock-tpm2-device=auto --tpm2-device=auto --wipe-slot=tpm2 "$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-client-pin=false)
(! systemd-cryptenroll --fido2-with-user-presence=f "$IMAGE" /tmp/foo) (! systemd-cryptenroll --fido2-with-user-presence=f "$IMAGE" /tmp/foo)
(! systemd-cryptenroll --fido2-with-client-pin=1234 "$IMAGE") (! systemd-cryptenroll --fido2-with-client-pin=1234 "$IMAGE")