]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptenroll: Support rotating PIN on an existing TPM2 enrollment 30766/head
authorGabríel Arthúr Pétursson <gabriel.petursson@marel.com>
Thu, 4 Jan 2024 15:34:28 +0000 (15:34 +0000)
committerGabríel Arthúr Pétursson <gabriel.petursson@marel.com>
Thu, 1 Feb 2024 13:55:17 +0000 (13:55 +0000)
src/cryptenroll/cryptenroll-tpm2.c
src/cryptenroll/cryptenroll-tpm2.h
src/cryptenroll/cryptenroll.c
test/units/testsuite-70.cryptenroll.sh

index b0937ec6840f40afbe467bcce8b86e8314dfd687..fb862a332902691bf790e0124339c2b0e1263e4a 100644 (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;
 }
index 7908b0331043432939179bc64e9b5b90a4787f2d..634d7637b9087d7ce229b863f4a580bc7fd6b6f9 100644 (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),
index 76ef3da624301764275955f2cc8f2de189ae986c..12e7e10d03e6b3d3714e3c2a539e234b0bf15c55 100644 (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);
+                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())
index 266c5de692af28ec85d6e10a8b6722d011b3abca..f18ef020a75e9a4499a0e353dc26b27e44dcaa09 100755 (executable)
@@ -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")