diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-08-17 17:21:57 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2022-09-08 16:34:27 +0200 |
commit | d9b5841d40996d42a05b7d6f1adf7a7517966262 (patch) | |
tree | a62d8485238558e54f0a73332e195b5cf327b52c /src/cryptenroll | |
parent | measure: add 'sign' verb (diff) | |
download | systemd-d9b5841d40996d42a05b7d6f1adf7a7517966262.tar.xz systemd-d9b5841d40996d42a05b7d6f1adf7a7517966262.zip |
tpm2-util: extend TPM2 policies to optionally check PCR values against signed values
Traditionally, TPM2 PCR policies are bound against literal PCR values,
which makes them hard to work with when updating software that is
measured into PCRs: each update will change the PCR values, and thus
break TPM2 policies of existing objects.
Let's improve the situation: let's allow signed PCR policies. Secrets
and other TPM2 objects can be associated with a public key that signs a
PCR policy. Thus, if the signed policy and the public key is presented,
access to the TPM2 object can be granted. This allows a less brittle
handling of updates: for example, whenever a kernel image is updated a
new signed PCR policy can be shipped along with it, signed by a private
key owned by the kernel vendor (ideally: same private key that is used
to sign the kernel image itself). TPM2 objects can then be bound to the
associated public key, thus allowing objects that can only be unlocked
by kernels of the same vendor. This makes it very easy to update kernels
without affecting locked secrets.
This does not hook up any of the consuming code (just passes NULL/0
everywhere). This is for later commits.
Diffstat (limited to 'src/cryptenroll')
-rw-r--r-- | src/cryptenroll/cryptenroll-tpm2.c | 29 | ||||
-rw-r--r-- | src/cryptenroll/cryptenroll-tpm2.h | 2 |
2 files changed, 25 insertions, 6 deletions
diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 01f2e1183c..ab892d3779 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -130,7 +130,7 @@ int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, - uint32_t pcr_mask, + uint32_t hash_pcr_mask, bool use_pin) { _cleanup_(erase_and_freep) void *secret = NULL, *secret2 = NULL; @@ -147,7 +147,7 @@ int enroll_tpm2(struct crypt_device *cd, assert(cd); assert(volume_key); assert(volume_key_size > 0); - assert(TPM2_PCR_MASK_VALID(pcr_mask)); + assert(TPM2_PCR_MASK_VALID(hash_pcr_mask)); assert_se(node = crypt_get_device_name(cd)); @@ -157,7 +157,16 @@ int enroll_tpm2(struct crypt_device *cd, return r; } - r = tpm2_seal(device, pcr_mask, pin_str, &secret, &secret_size, &blob, &blob_size, &hash, &hash_size, &pcr_bank, &primary_alg); + r = tpm2_seal(device, + hash_pcr_mask, + /* pubkey= */ NULL, /* pubkey_size= */ 0, + /* pubkey_pcr_mask= */ 0, + pin_str, + &secret, &secret_size, + &blob, &blob_size, + &hash, &hash_size, + &pcr_bank, + &primary_alg); if (r < 0) return r; @@ -174,7 +183,17 @@ int enroll_tpm2(struct crypt_device *cd, /* Quick verification that everything is in order, we are not in a hurry after all. */ log_debug("Unsealing for verification..."); - r = tpm2_unseal(device, pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, pin_str, &secret2, &secret2_size); + r = tpm2_unseal(device, + hash_pcr_mask, + pcr_bank, + /* pubkey= */ NULL, /* pubkey_size= */ 0, + /* pubkey_pcr_mask= */ 0, + /* signature= */ NULL, + pin_str, + primary_alg, + blob, blob_size, + hash, hash_size, + &secret2, &secret2_size); if (r < 0) return r; @@ -200,7 +219,7 @@ int enroll_tpm2(struct crypt_device *cd, if (keyslot < 0) return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node); - r = tpm2_make_luks2_json(keyslot, pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, flags, &v); + r = tpm2_make_luks2_json(keyslot, hash_pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, flags, &v); if (r < 0) return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m"); diff --git a/src/cryptenroll/cryptenroll-tpm2.h b/src/cryptenroll/cryptenroll-tpm2.h index 742f49b8d5..36a3097bc2 100644 --- a/src/cryptenroll/cryptenroll-tpm2.h +++ b/src/cryptenroll/cryptenroll-tpm2.h @@ -7,7 +7,7 @@ #include "log.h" #if HAVE_TPM2 -int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t pcr_mask, bool use_pin); +int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t hash_pcr_mask, bool use_pin); #else static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t pcr_mask, bool use_pin) { return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), |