diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-08-17 17:29:44 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2022-09-08 16:34:27 +0200 |
commit | f0f4fcaeb77c30df2dc716db15350b5ab49f45e2 (patch) | |
tree | 0b495cbf5d349d0a3d2cf72fc7ab25ed140ad97c | |
parent | creds-tool: expose new signed PCR policies in creds tool, too (diff) | |
download | systemd-f0f4fcaeb77c30df2dc716db15350b5ab49f45e2.tar.xz systemd-f0f4fcaeb77c30df2dc716db15350b5ab49f45e2.zip |
cryptenroll: hook up new TPM2 signed policies with cryptenroll
-rw-r--r-- | man/systemd-cryptenroll.xml | 53 | ||||
-rw-r--r-- | src/cryptenroll/cryptenroll-tpm2.c | 87 | ||||
-rw-r--r-- | src/cryptenroll/cryptenroll-tpm2.h | 4 | ||||
-rw-r--r-- | src/cryptenroll/cryptenroll.c | 74 | ||||
-rw-r--r-- | src/partition/repart.c | 12 | ||||
-rw-r--r-- | src/shared/tpm2-util.c | 27 | ||||
-rw-r--r-- | src/shared/tpm2-util.h | 2 |
7 files changed, 201 insertions, 58 deletions
diff --git a/man/systemd-cryptenroll.xml b/man/systemd-cryptenroll.xml index afde0fad7e..889dd39b03 100644 --- a/man/systemd-cryptenroll.xml +++ b/man/systemd-cryptenroll.xml @@ -347,17 +347,53 @@ to <literal>no</literal>. Despite being called PIN, any character can be used, not just numbers. </para> - <para>Note that incorrect PIN entry when unlocking increments the - TPM dictionary attack lockout mechanism, and may lock out users for a prolonged time, depending on - its configuration. The lockout mechanism is a global property of the TPM, - <command>systemd-cryptenroll</command> does not control or configure the lockout mechanism. You may - use tpm2-tss tools to inspect or configure the dictionary attack lockout, with - <citerefentry project='mankier'><refentrytitle>tpm2_getcap</refentrytitle><manvolnum>1</manvolnum></citerefentry> and - <citerefentry project='mankier'><refentrytitle>tpm2_dictionarylockout</refentrytitle><manvolnum>1</manvolnum></citerefentry> + <para>Note that incorrect PIN entry when unlocking increments the TPM dictionary attack lockout + mechanism, and may lock out users for a prolonged time, depending on its configuration. The lockout + mechanism is a global property of the TPM, <command>systemd-cryptenroll</command> does not control or + configure the lockout mechanism. You may use tpm2-tss tools to inspect or configure the dictionary + attack lockout, with <citerefentry + project='mankier'><refentrytitle>tpm2_getcap</refentrytitle><manvolnum>1</manvolnum></citerefentry> + and <citerefentry + project='mankier'><refentrytitle>tpm2_dictionarylockout</refentrytitle><manvolnum>1</manvolnum></citerefentry> commands, respectively.</para></listitem> </varlistentry> <varlistentry> + <term><option>--tpm2-public-key=</option><arg>PATH</arg></term> + <term><option>--tpm2-public-key-pcrs=</option><arg rep="repeat">PCR</arg></term> + <term><option>--tpm2-signature=</option><arg>PATH</arg></term> + + <listitem><para>Configures a TPM2 signed PCR policy to bind encryption to. The + <option>--tpm2-public-key=</option> option accepts a path to a PEM encoded RSA public key, to bind + the encryption to. If this is not specified explicitly, but a file + <filename>tpm2-pcr-public-key.pem</filename> exists in one of the directories + <filename>/etc/systemd/</filename>, <filename>/run/systemd/</filename>, + <filename>/usr/lib/systemd/</filename> (searched in this order), it is automatically used. The + <option>--tpm2-public-key-pcrs=</option> option takes a list of TPM2 PCR indexes to bind to (same + syntax as <option>--tpm2-pcrs=</option> described above). If not specified defaults to 11 (i.e. this + binds the policy to any unified kernel image for which a PCR signature can be provided).</para> + + <para>Note the difference between <option>--tpm2-pcrs=</option> and + <option>--tpm2-public-key-pcrs=</option>: the former binds decryption to the current, specific PCR + values; the latter binds decryption to any set of PCR values for which a signature by the specified + public key can be provided. The latter is hence more useful in scenarios where software updates shell + be possible without losing access to all previously encrypted LUKS2 volumes.</para> + + <para>The <option>--tpm2-signature=</option> option takes a path to a TPM2 PCR signature file + as generated by the + <citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry> + tool. If this this is not specified explicitly a suitable signature file + <filename>tpm2-pcr-signature.json</filename> is searched for in <filename>/etc/systemd/</filename>, + <filename>/run/systemd/</filename>, <filename>/usr/lib/systemd/</filename> (in this order) and + used. If a signature file is specified or found it is used to verify if the volume can be unlocked + with it given the current PCR state, before the new slot is written to disk. This is intended as + safety net to ensure that access to a volume is not lost if a public key is enrolled for which no + valid signature for the current PCR state is available. If the supplied signature does not unlock the + current PCR state and public key combination, no slot is enrolled and the operation will fail. If no + signature file is specified or found no such safety verification is done.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>--wipe-slot=</option><arg rep="repeat">SLOT</arg></term> <listitem><para>Wipes one or more LUKS2 key slots. Takes a comma separated list of numeric slot @@ -411,7 +447,8 @@ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-cryptsetup@.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>5</manvolnum></citerefentry>, - <citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> + <citerefentry project='die-net'><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>, + <citerefentry><refentrytitle>systemd-measure</refentrytitle><manvolnum>1</manvolnum></citerefentry> </para> </refsect1> diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index ab892d3779..5c902908c4 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -4,6 +4,7 @@ #include "ask-password-api.h" #include "cryptenroll-tpm2.h" #include "env-util.h" +#include "fileio.h" #include "hexdecoct.h" #include "json.h" #include "memory-util.h" @@ -131,13 +132,16 @@ int enroll_tpm2(struct crypt_device *cd, size_t volume_key_size, const char *device, uint32_t hash_pcr_mask, + const char *pubkey_path, + uint32_t pubkey_pcr_mask, + const char *signature_path, bool use_pin) { - _cleanup_(erase_and_freep) void *secret = NULL, *secret2 = NULL; - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + _cleanup_(erase_and_freep) void *secret = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *signature_json = NULL; _cleanup_(erase_and_freep) char *base64_encoded = NULL; - size_t secret_size, secret2_size, blob_size, hash_size; - _cleanup_free_ void *blob = NULL, *hash = NULL; + size_t secret_size, blob_size, hash_size, pubkey_size = 0; + _cleanup_free_ void *blob = NULL, *hash = NULL, *pubkey = NULL; uint16_t pcr_bank, primary_alg; const char *node; _cleanup_(erase_and_freep) char *pin_str = NULL; @@ -148,6 +152,7 @@ int enroll_tpm2(struct crypt_device *cd, assert(volume_key); assert(volume_key_size > 0); assert(TPM2_PCR_MASK_VALID(hash_pcr_mask)); + assert(TPM2_PCR_MASK_VALID(pubkey_pcr_mask)); assert_se(node = crypt_get_device_name(cd)); @@ -157,10 +162,29 @@ int enroll_tpm2(struct crypt_device *cd, return r; } + r = tpm2_load_pcr_public_key(pubkey_path, &pubkey, &pubkey_size); + if (r < 0) { + if (pubkey_path || signature_path || r != -ENOENT) + return log_error_errno(r, "Failed 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 { + /* Also try to load the signature JSON object, to verify that our enrollment will work. This is optional however. */ + + r = tpm2_load_pcr_signature(signature_path, &signature_json); + if (r < 0) { + if (signature_path || r != -ENOENT) + return log_debug_errno(r, "Failed to read TPM PCR signature: %m"); + + log_debug_errno(r, "Failed to read TPM2 PCR signature, proceeding without: %m"); + } + } + r = tpm2_seal(device, hash_pcr_mask, - /* pubkey= */ NULL, /* pubkey_size= */ 0, - /* pubkey_pcr_mask= */ 0, + pubkey, pubkey_size, + pubkey_pcr_mask, pin_str, &secret, &secret_size, &blob, &blob_size, @@ -181,24 +205,29 @@ int enroll_tpm2(struct crypt_device *cd, return r; /* return existing keyslot, so that wiping won't kill it */ } - /* Quick verification that everything is in order, we are not in a hurry after all. */ - log_debug("Unsealing for verification..."); - 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; + /* Quick verification that everything is in order, we are not in a hurry after all.*/ + if (!pubkey || signature_json) { + _cleanup_(erase_and_freep) void *secret2 = NULL; + size_t secret2_size; + + log_debug("Unsealing for verification..."); + r = tpm2_unseal(device, + hash_pcr_mask, + pcr_bank, + pubkey, pubkey_size, + pubkey_pcr_mask, + signature_json, + pin_str, + primary_alg, + blob, blob_size, + hash, hash_size, + &secret2, &secret2_size); + if (r < 0) + return r; - if (memcmp_nn(secret, secret_size, secret2, secret2_size) != 0) - return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 seal/unseal verification failed."); + if (memcmp_nn(secret, secret_size, secret2, secret2_size) != 0) + return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "TPM2 seal/unseal verification failed."); + } /* let's base64 encode the key to use, for compat with homed (and it's easier to every type it in by keyboard, if that might end up being necessary. */ r = base64mem(secret, secret_size, &base64_encoded); @@ -219,7 +248,17 @@ 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, hash_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, + pubkey, pubkey_size, + pubkey_pcr_mask, + 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 36a3097bc2..b6e0c2808e 100644 --- a/src/cryptenroll/cryptenroll-tpm2.h +++ b/src/cryptenroll/cryptenroll-tpm2.h @@ -7,9 +7,9 @@ #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 hash_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, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, 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) { +static inline int enroll_tpm2(struct crypt_device *cd, const void *volume_key, size_t volume_key_size, const char *device, uint32_t hash_pcr_mask, const char *pubkey_path, uint32_t pubkey_pcr_mask, const char *signature_path, bool use_pin) { 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 3c2b914a43..6a9170f000 100644 --- a/src/cryptenroll/cryptenroll.c +++ b/src/cryptenroll/cryptenroll.c @@ -26,6 +26,7 @@ #include "string-table.h" #include "strv.h" #include "terminal-util.h" +#include "tpm-pcr.h" #include "tpm2-util.h" static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID; @@ -35,6 +36,9 @@ static char *arg_fido2_device = NULL; static char *arg_tpm2_device = NULL; static uint32_t arg_tpm2_pcr_mask = UINT32_MAX; static bool arg_tpm2_pin = false; +static char *arg_tpm2_public_key = NULL; +static uint32_t arg_tpm2_public_key_pcr_mask = UINT32_MAX; +static char *arg_tpm2_signature = NULL; static char *arg_node = NULL; static int *arg_wipe_slots = NULL; static size_t arg_n_wipe_slots = 0; @@ -53,6 +57,8 @@ STATIC_DESTRUCTOR_REGISTER(arg_unlock_keyfile, freep); STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep); STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep); STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep); +STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep); +STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep); STATIC_DESTRUCTOR_REGISTER(arg_node, freep); STATIC_DESTRUCTOR_REGISTER(arg_wipe_slots, freep); @@ -114,6 +120,13 @@ static int help(void) { " Enroll a TPM2 device\n" " --tpm2-pcrs=PCR1+PCR2+PCR3+…\n" " Specify TPM2 PCRs to seal against\n" + " --tpm2-public-key=PATH\n" + " Enroll signed TPM2 PCR policy against PEM public key\n" + " --tpm2-public-key-pcrs=PCR1+PCR2+PCR3+…\n" + " Enroll signed TPM2 PCR policy for specified TPM2 PCRs\n" + " --tpm2-signature=PATH\n" + " Validate public key enrollment works with JSON signature\n" + " file\n" " --tpm2-with-pin=BOOL\n" " Whether to require entering a PIN to unlock the volume\n" " --wipe-slot=SLOT1,SLOT2,…\n" @@ -138,6 +151,9 @@ static int parse_argv(int argc, char *argv[]) { ARG_FIDO2_DEVICE, ARG_TPM2_DEVICE, ARG_TPM2_PCRS, + ARG_TPM2_PUBLIC_KEY, + ARG_TPM2_PUBLIC_KEY_PCRS, + ARG_TPM2_SIGNATURE, ARG_TPM2_PIN, ARG_WIPE_SLOT, ARG_FIDO2_WITH_PIN, @@ -147,21 +163,24 @@ static int parse_argv(int argc, char *argv[]) { }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "password", no_argument, NULL, ARG_PASSWORD }, - { "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY }, - { "unlock-key-file", required_argument, NULL, ARG_UNLOCK_KEYFILE }, - { "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI }, - { "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG }, - { "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE }, - { "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN }, - { "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP }, - { "fido2-with-user-verification", required_argument, NULL, ARG_FIDO2_WITH_UV }, - { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE }, - { "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS }, - { "tpm2-with-pin", required_argument, NULL, ARG_TPM2_PIN }, - { "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "password", no_argument, NULL, ARG_PASSWORD }, + { "recovery-key", no_argument, NULL, ARG_RECOVERY_KEY }, + { "unlock-key-file", required_argument, NULL, ARG_UNLOCK_KEYFILE }, + { "pkcs11-token-uri", required_argument, NULL, ARG_PKCS11_TOKEN_URI }, + { "fido2-credential-algorithm", required_argument, NULL, ARG_FIDO2_CRED_ALG }, + { "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE }, + { "fido2-with-client-pin", required_argument, NULL, ARG_FIDO2_WITH_PIN }, + { "fido2-with-user-presence", required_argument, NULL, ARG_FIDO2_WITH_UP }, + { "fido2-with-user-verification", required_argument, NULL, ARG_FIDO2_WITH_UV }, + { "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE }, + { "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS }, + { "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY }, + { "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS }, + { "tpm2-signature", required_argument, NULL, ARG_TPM2_SIGNATURE }, + { "tpm2-with-pin", required_argument, NULL, ARG_TPM2_PIN }, + { "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT }, {} }; @@ -329,6 +348,27 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_TPM2_PUBLIC_KEY: + r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_public_key); + if (r < 0) + return r; + + break; + + case ARG_TPM2_PUBLIC_KEY_PCRS: + r = tpm2_parse_pcr_argument(optarg, &arg_tpm2_public_key_pcr_mask); + if (r < 0) + return r; + + break; + + case ARG_TPM2_SIGNATURE: + r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_tpm2_signature); + if (r < 0) + return r; + + break; + case ARG_WIPE_SLOT: { const char *p = optarg; @@ -405,6 +445,8 @@ static int parse_argv(int argc, char *argv[]) { if (arg_tpm2_pcr_mask == UINT32_MAX) arg_tpm2_pcr_mask = TPM2_PCR_MASK_DEFAULT; + if (arg_tpm2_public_key_pcr_mask == UINT32_MAX) + arg_tpm2_public_key_pcr_mask = UINT32_C(1) << TPM_PCR_INDEX_KERNEL_IMAGE; return 1; } @@ -615,7 +657,7 @@ static int run(int argc, char *argv[]) { break; case ENROLL_TPM2: - slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask, arg_tpm2_pin); + slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask, arg_tpm2_public_key, arg_tpm2_public_key_pcr_mask, arg_tpm2_signature, arg_tpm2_pin); break; case _ENROLL_TYPE_INVALID: diff --git a/src/partition/repart.c b/src/partition/repart.c index af7a830377..aec04a836c 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -2950,7 +2950,17 @@ static int partition_encrypt( if (keyslot < 0) return log_error_errno(keyslot, "Failed to add new TPM2 key to %s: %m", node); - r = tpm2_make_luks2_json(keyslot, arg_tpm2_pcr_mask, pcr_bank, primary_alg, blob, blob_size, hash, hash_size, 0, &v); + r = tpm2_make_luks2_json( + keyslot, + arg_tpm2_pcr_mask, + pcr_bank, + /* pubkey= */ NULL, /* pubkey_size= */ 0, + /* pubkey_pcr_mask= */ 0, + primary_alg, + blob, blob_size, + hash, hash_size, + 0, + &v); if (r < 0) return log_error_errno(r, "Failed to prepare TPM2 JSON token object: %m"); diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index aef0603855..254e63334a 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -1822,8 +1822,11 @@ int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret) { int tpm2_make_luks2_json( int keyslot, - uint32_t pcr_mask, + uint32_t hash_pcr_mask, uint16_t pcr_bank, + const void *pubkey, + size_t pubkey_size, + uint32_t pubkey_pcr_mask, uint16_t primary_alg, const void *blob, size_t blob_size, @@ -1832,31 +1835,43 @@ int tpm2_make_luks2_json( TPM2Flags flags, JsonVariant **ret) { - _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *a = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *hmj = NULL, *pkmj = NULL; _cleanup_free_ char *keyslot_as_string = NULL; int r; assert(blob || blob_size == 0); assert(policy_hash || policy_hash_size == 0); + assert(pubkey || pubkey_size == 0); if (asprintf(&keyslot_as_string, "%i", keyslot) < 0) return -ENOMEM; - r = tpm2_make_pcr_json_array(pcr_mask, &a); + r = tpm2_make_pcr_json_array(hash_pcr_mask, &hmj); if (r < 0) return r; + if (pubkey_pcr_mask != 0) { + r = tpm2_make_pcr_json_array(pubkey_pcr_mask, &pkmj); + if (r < 0) + return r; + } + + /* Note: We made the mistake of using "-" in the field names, which isn't particular compatible with + * other programming languages. Let's not make things worse though, i.e. future additions to the JSON + * object should use "_" rather than "-" in field names. */ + r = json_build(&v, JSON_BUILD_OBJECT( JSON_BUILD_PAIR("type", JSON_BUILD_CONST_STRING("systemd-tpm2")), JSON_BUILD_PAIR("keyslots", JSON_BUILD_ARRAY(JSON_BUILD_STRING(keyslot_as_string))), JSON_BUILD_PAIR("tpm2-blob", JSON_BUILD_BASE64(blob, blob_size)), - JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(a)), + JSON_BUILD_PAIR("tpm2-pcrs", JSON_BUILD_VARIANT(hmj)), JSON_BUILD_PAIR_CONDITION(!!tpm2_pcr_bank_to_string(pcr_bank), "tpm2-pcr-bank", JSON_BUILD_STRING(tpm2_pcr_bank_to_string(pcr_bank))), JSON_BUILD_PAIR_CONDITION(!!tpm2_primary_alg_to_string(primary_alg), "tpm2-primary-alg", JSON_BUILD_STRING(tpm2_primary_alg_to_string(primary_alg))), JSON_BUILD_PAIR("tpm2-policy-hash", JSON_BUILD_HEX(policy_hash, policy_hash_size)), - JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN))) - ); + JSON_BUILD_PAIR("tpm2-pin", JSON_BUILD_BOOLEAN(flags & TPM2_FLAGS_USE_PIN)), + JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey_pcrs", JSON_BUILD_VARIANT(pkmj)), + JSON_BUILD_PAIR_CONDITION(pubkey_pcr_mask != 0, "tpm2_pubkey", JSON_BUILD_BASE64(pubkey, pubkey_size)))); if (r < 0) return r; diff --git a/src/shared/tpm2-util.h b/src/shared/tpm2-util.h index ee6e94ef67..3bdeba8f11 100644 --- a/src/shared/tpm2-util.h +++ b/src/shared/tpm2-util.h @@ -81,7 +81,7 @@ int tpm2_parse_pcrs(const char *s, uint32_t *ret); int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret); int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret); -int tpm2_make_luks2_json(int keyslot, uint32_t pcr_mask, uint16_t pcr_bank, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, JsonVariant **ret); +int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, JsonVariant **ret); #define TPM2_PCRS_MAX 24U |