From 03e3b2672bb6c242c445ee8c02ae7d23dbfcf87d Mon Sep 17 00:00:00 2001 From: Sam Leonard Date: Fri, 26 Apr 2024 13:35:05 +0100 Subject: [PATCH] cryptenroll: disable loading public key if --tpm2-public-key= is empty --- src/cryptenroll/cryptenroll-tpm2.c | 37 ++++++++++++++++-------------- src/cryptenroll/cryptenroll-tpm2.h | 4 ++-- src/cryptenroll/cryptenroll.c | 11 ++++++++- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 83a2f4420f5..1656dc1e834 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -250,6 +250,7 @@ int enroll_tpm2(struct crypt_device *cd, Tpm2PCRValue *hash_pcr_values, size_t n_hash_pcr_values, const char *pubkey_path, + bool load_pubkey, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, @@ -306,25 +307,27 @@ int enroll_tpm2(struct crypt_device *cd, } TPM2B_PUBLIC public = {}; - r = tpm2_load_pcr_public_key(pubkey_path, &pubkey.iov_base, &pubkey.iov_len); - if (r < 0) { - if (pubkey_path || signature_path || r != -ENOENT) - return log_error_errno(r, "Failed to read TPM PCR public key: %m"); + if (load_pubkey) { + r = tpm2_load_pcr_public_key(pubkey_path, &pubkey.iov_base, &pubkey.iov_len); + if (r < 0) { + if (pubkey_path || signature_path || r != -ENOENT) + return log_error_errno(r, "Failed to read TPM PCR public key: %m"); - log_debug_errno(r, "Failed to read TPM2 PCR public key, proceeding without: %m"); - pubkey_pcr_mask = 0; - } else { - r = tpm2_tpm2b_public_from_pem(pubkey.iov_base, pubkey.iov_len, &public); - if (r < 0) - return log_error_errno(r, "Could not convert public key to TPM2B_PUBLIC: %m"); - - if (signature_path) { - /* Also try to load the signature JSON object, to verify that our enrollment will work. - * This is optional however, skip it if it's not explicitly provided. */ - - r = tpm2_load_pcr_signature(signature_path, &signature_json); + log_debug_errno(r, "Failed to read TPM2 PCR public key, proceeding without: %m"); + pubkey_pcr_mask = 0; + } else { + r = tpm2_tpm2b_public_from_pem(pubkey.iov_base, pubkey.iov_len, &public); if (r < 0) - return log_debug_errno(r, "Failed to read TPM PCR signature: %m"); + return log_error_errno(r, "Could not convert public key to TPM2B_PUBLIC: %m"); + + if (signature_path) { + /* Also try to load the signature JSON object, to verify that our enrollment will work. + * This is optional however, skip it if it's not explicitly provided. */ + + r = tpm2_load_pcr_signature(signature_path, &signature_json); + if (r < 0) + return log_debug_errno(r, "Failed to read TPM PCR signature: %m"); + } } } diff --git a/src/cryptenroll/cryptenroll-tpm2.h b/src/cryptenroll/cryptenroll-tpm2.h index 634d7637b90..4522b0b5950 100644 --- a/src/cryptenroll/cryptenroll-tpm2.h +++ b/src/cryptenroll/cryptenroll-tpm2.h @@ -9,14 +9,14 @@ #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 *ret_slot_to_wipe); +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_pcr_values, size_t n_hash_pcr_values, const char *pubkey_path, bool disable_loading_pubkey, 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), "TPM2 unlocking not supported."); } -static inline 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 *slot_to_wipe) { +static inline 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_pcr_values, size_t n_hash_pcr_values, const char *pubkey_path, bool disable_loading_pubkey, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin, const char *pcrlock_path, int *ret_slot_to_wipe) { return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "TPM2 key enrollment not supported."); } diff --git a/src/cryptenroll/cryptenroll.c b/src/cryptenroll/cryptenroll.c index 9c618ad28a5..6e700d30143 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -46,6 +46,7 @@ static Tpm2PCRValue *arg_tpm2_hash_pcr_values = NULL; static size_t arg_tpm2_n_hash_pcr_values = 0; static bool arg_tpm2_pin = false; static char *arg_tpm2_public_key = NULL; +static bool arg_tpm2_load_public_key = true; static uint32_t arg_tpm2_public_key_pcr_mask = 0; static char *arg_tpm2_signature = NULL; static char *arg_tpm2_pcrlock = NULL; @@ -498,9 +499,17 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_TPM2_PUBLIC_KEY: + /* an empty argument disables loading a public key */ + if (isempty(optarg)) { + arg_tpm2_load_public_key = false; + arg_tpm2_public_key = mfree(arg_tpm2_public_key); + break; + } + r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_public_key); if (r < 0) return r; + arg_tpm2_load_public_key = true; break; @@ -834,7 +843,7 @@ 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_to_wipe); + 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_load_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 */