On Thu, Mar 06, 2025 at 10:15:09PM +0100, Diorcet Yann wrote: > The systemd TPM2 key protector is a module that enables the automatic > retrieval > of a fully-encrypted disk's unlocking key from a systemd token in luks2 > partition header. > > Inspired by the tpm2_key_protector module and the cryptsetup systemd > implementation. > > The systemd TPM2 key protector registers two commands: > > - systemd_tpm2_key_protector_init: Initializes the state of the TPM2 key > protector for later usage, clearing any > previous state, too, if any. > > - systemd_tpm2_key_protector_clear: Clears any state set by > systemd_tpm2_key_protector_init. > > Create the token inside LUKS2 header using TPM2 device: > systemd-cryptenroll /dev/sdXY --tpm2-device=auto > > Mount the partition in GRUB2: > systemd_tpm2_key_protector_init --device=hdX,gptY > cryptomount hdX,gptY -P systemd-tpm2 > > New tpm2srk module is created in order to factorize the code between > tpm2_key_protector and systemd_tpm2_key_protector. > Instead of a new module/command, is it possible to treat the systemd key slot as a new key format for tpm2_key_protector? E.g. a new parameter, '--device=hdX,gptY' or '-u <UUID>' is introduced to locate the partition and interpret the systemd key slot within tpm2_key_protector.
Thanks, Gary Lin > New base64 module is created in order to factorize the code between > luks2 and systemd_tpm2_key_protector. > > Exposing some structures and functions from luks2 notably the new > luks2_iterate_keyslot function and adding the token parsing code > in luks2_get_keyslot. > > Signed-off-by: Diorcet Yann <diorcet.y...@gmail.com> > --- > Makefile.util.def | 1 + > grub-core/Makefile.core.def | 28 +- > .../systemd_tpm2_key_protector/module.c | 346 ++++++++++++++++++ > .../systemd_tpm2_key_protector/tpm2_luks2.c | 238 ++++++++++++ > .../systemd_tpm2_key_protector/tpm2_luks2.h | 37 ++ > .../commands/tpm2_key_protector/module.c | 171 +-------- > .../commands/tpm2_key_protector/tpm2_args.h | 13 +- > grub-core/disk/luks2.c | 252 +++++++++---- > grub-core/lib/base64.c | 21 ++ > grub-core/lib/tpm2srk.c | 191 ++++++++++ > include/grub/luks2.h | 148 ++++++++ > .../grub}/tpm2.h | 11 + > include/grub/tpm2srk.h | 44 +++ > util/grub-protect.c | 60 +-- > 14 files changed, 1259 insertions(+), 302 deletions(-) > create mode 100644 grub-core/commands/systemd_tpm2_key_protector/module.c > create mode 100644 > grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.c > create mode 100644 > grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.h > create mode 100644 grub-core/lib/base64.c > create mode 100644 grub-core/lib/tpm2srk.c > create mode 100644 include/grub/luks2.h > rename {grub-core/commands/tpm2_key_protector => include/grub}/tpm2.h (85%) > create mode 100644 include/grub/tpm2srk.h > > diff --git a/Makefile.util.def b/Makefile.util.def > index 3a80e6d28..744ff6337 100644 > --- a/Makefile.util.def > +++ b/Makefile.util.def > @@ -213,6 +213,7 @@ program = { > > common = grub-core/kern/emu/argp_common.c; > common = grub-core/osdep/init.c; > + common = grub-core/lib/tpm2srk.c; > common = grub-core/lib/tss2/buffer.c; > common = grub-core/lib/tss2/tss2_mu.c; > common = grub-core/lib/tss2/tpm2_cmd.c; > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index f6d312033..792460e54 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -1215,6 +1215,14 @@ module = { > common = lib/json/json.c; > }; > > +module = { > + name = base64; > + common = lib/gnulib/base64.c; > + common = lib/base64.c; > + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; > + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; > +}; > + > module = { > name = afsplitter; > common = disk/AFSplitter.c; > @@ -1228,7 +1236,6 @@ module = { > module = { > name = luks2; > common = disk/luks2.c; > - common = lib/gnulib/base64.c; > cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; > cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json'; > }; > @@ -2570,6 +2577,14 @@ module = { > cppflags = '-I$(srcdir)/lib/tss2'; > }; > > +module = { > + name = tpm2srk; > + common = lib/tpm2srk.c; > + enable = efi; > + enable = emu; > + cppflags = '-I$(srcdir)/lib/tss2'; > +}; > + > module = { > name = tpm2_key_protector; > common = commands/tpm2_key_protector/args.c; > @@ -2582,6 +2597,17 @@ module = { > cppflags = '-I$(srcdir)/lib/tss2 -I$(srcdir)/lib/libtasn1-grub'; > }; > > +module = { > + name = systemd_tpm2_key_protector; > + common = commands/systemd_tpm2_key_protector/tpm2_luks2.c; > + common = commands/systemd_tpm2_key_protector/module.c; > + /* The plaform support of systemd_tpm2_key_protector depends on the tcg2 > implementation in tss2. */ > + enable = efi; > + enable = emu; > + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; > + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json > -I$(srcdir)/lib/tss2'; > +}; > + > module = { > name = tr; > common = commands/tr.c; > diff --git a/grub-core/commands/systemd_tpm2_key_protector/module.c > b/grub-core/commands/systemd_tpm2_key_protector/module.c > new file mode 100644 > index 000000000..827e93c04 > --- /dev/null > +++ b/grub-core/commands/systemd_tpm2_key_protector/module.c > @@ -0,0 +1,346 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/dl.h> > +#include <grub/extcmd.h> > +#include <grub/file.h> > +#include <grub/list.h> > +#include <grub/misc.h> > +#include <grub/err.h> > +#include <grub/mm.h> > +#include <grub/key_protector.h> > + > +#include <base64.h> > + > +#include <grub/luks2.h> > + > +#include "tpm2_luks2.h" > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +typedef enum systemd_tpm2_protector_device > +{ > + SYSTEMD_TPM2_PROTECTOR_DEVICE_UNSET, > + SYSTEMD_TPM2_PROTECTOR_DEVICE_SET, > +} systemd_tpm2_protector_device_t; > + > +typedef enum tpm2_protector_options > +{ > + OPTION_DEVICE, > +} systemd_tpm2_protector_options_t; > + > +typedef struct systemd_tpm2_protector_context > +{ > + systemd_tpm2_protector_device_t mode; > + grub_luks2_token_t token; > +} systemd_tpm2_protector_context_t; > + > +static const struct grub_arg_option > systemd_tpm2_protector_init_cmd_options[] = > + { > + { > + .longarg = "device", > + .shortarg = 'd', > + .flags = 0, > + .arg = NULL, > + .type = ARG_TYPE_STRING, > + .doc = N_("Set LUKS partition to use"), > + }, > + /* End of list */ > + {0, 0, 0, 0, 0, 0} > + }; > + > +static grub_extcmd_t systemd_tpm2_protector_init_cmd; > +static grub_extcmd_t systemd_tpm2_protector_clear_cmd; > +static systemd_tpm2_protector_context_t systemd_tpm2_protector_ctx = {0}; > + > +static inline int > +hex2val (char hex) > +{ > + if ('0' <= hex && hex <= '9') > + return hex - '0'; > + if ('a' <= hex && hex <= 'f') > + return hex - 'a' + 10; > + if ('A' <= hex && hex <= 'F') > + return hex - 'A' + 10; > + return -1; > +} > + > +static grub_err_t > +unhex_hash (const char *p, idx_t l, void **ret, idx_t *ret_len) { > + char *buf = NULL; > + idx_t buf_size; > + char *z; > + int r = GRUB_ERR_NONE; > + > + if (p == NULL || l == 0 || ret == NULL || ret_len == NULL) > + return GRUB_ERR_BAD_ARGUMENT; > + > + if (l == SIZE_MAX) > + l = grub_strlen(p); > + > + /* Note that the calculation of memory size is an upper boundary, > + as we ignore whitespace while decoding */ > + buf_size = (l + 1) / 2 + 1; > + buf = z = grub_malloc(buf_size); > + if (!buf) > + return GRUB_ERR_OUT_OF_MEMORY; > + > + while (p[0] != 0) > + { > + int high, low; > + > + /* Remove spaces before first hex character */ > + while (p[0] != 0 && grub_isspace (p[0])) > + p++; > + > + /* End of the string */ > + if (p[0] == 0) > + break; > + > + /* First hex character */ > + high = hex2val (*p++); > + > + /* Remove spaces after first hex character */ > + while (p[0] != 0 && grub_isspace (p[0])) > + p++; > + if (p[0] == 0 || high < 0) > + { > + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid hex string"); > + goto on_failure; > + } > + > + /* Second hex character */ > + low = hex2val (*p++); > + if (low < 0) > + { > + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid hex string"); > + goto on_failure; > + } > + > + *z++ = (high << 4) | low; > + } > + > + *z = 0; > + > + *ret_len = (size_t) (z - buf); > + *ret = buf; > + > + return r; > + > +on_failure: > + grub_free(buf); > + *ret = NULL; > + *ret_len = 0; > + > + return r; > +} > + > +static grub_err_t > +systemd_tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t > *key_size) > +{ > + const char *base64_blob; > + char *blob; > + idx_t blob_size; > + void *decrypted_key; > + grub_size_t decrypted_key_size; > + char *base64_encode; > + idx_t base64_encode_size; > + > + const char *hex_hash; > + char *policy_hash; > + idx_t policy_hash_size; > + grub_err_t ret = GRUB_ERR_NONE; > + > + /* Expect a call to systemd_tpm2_protector_init before anybody tries to > use us */ > + if (systemd_tpm2_protector_ctx.mode == > SYSTEMD_TPM2_PROTECTOR_DEVICE_UNSET) > + return grub_error (GRUB_ERR_INVALID_COMMAND, N_("cannot use systemd > TPM2 key protector without initializing it, call systemd_tpm2_protector_init > first")); > + > + if (key == NULL || key_size == NULL) > + return GRUB_ERR_BAD_ARGUMENT; > + > + base64_blob = > systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob; > + if(base64_decode_alloc(base64_blob, grub_strlen (base64_blob), &blob, > &blob_size) == 0) > + { > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Can't decode base64 > blob")); > + } > + > + hex_hash = > systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash; > + ret = unhex_hash(hex_hash, grub_strlen (hex_hash), (void*)&policy_hash, > &policy_hash_size); > + if(ret != GRUB_ERR_NONE) > + { > + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Can't unhex policy > hash")); > + goto exit1; > + } > + > + ret = tpm2_luks2_acquire_luks2_key( > + systemd_tpm2_protector_ctx.token.u.systemd_tpm2.pcr_mask, > + systemd_tpm2_protector_ctx.token.u.systemd_tpm2.pcr_bank, > + systemd_tpm2_protector_ctx.token.u.systemd_tpm2.primary_alg, > + blob, > + blob_size, > + policy_hash, > + policy_hash_size, > + &decrypted_key, > + &decrypted_key_size); > + > + if (ret != GRUB_ERR_NONE) > + goto exit2; > + > + /* Before using this key as passphrase we base64 encode it, for compat > with homed */ > + base64_encode_size = base64_encode_alloc(decrypted_key, > decrypted_key_size, &base64_encode); > + if (base64_encode_size <= 0) > + { > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Can't encode > passphrase")); > + goto exit3; > + } > + > + *key = (grub_uint8_t *) base64_encode; > + *key_size = grub_strlen(base64_encode); > + > +exit3: > + grub_free(decrypted_key); > +exit2: > + grub_free(policy_hash); > +exit1: > + grub_free(blob); > + > + return ret; > +} > + > +static grub_err_t > +tpm2_protector_parse_device (const char *value, const char **file) > +{ > + if (grub_strlen (value) == 0) > + return GRUB_ERR_BAD_ARGUMENT; > + > + *file = value; > + > + return GRUB_ERR_NONE; > +} > + > +static void > +luks2_iterate_fct(grub_luks2_keyslot_t *k __attribute__ ((unused)), > + grub_luks2_digest_t *d __attribute__ ((unused)), > + grub_luks2_segment_t *s __attribute__ ((unused)), > + grub_luks2_token_t *t) > +{ > + grub_memcpy(&systemd_tpm2_protector_ctx.token, t, > sizeof(grub_luks2_token_t)); > + systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob = > + grub_strdup(systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob); > + systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash = > + > grub_strdup(systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash); > +} > + > +static grub_err_t > +systemd_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int > argc, > + char **args __attribute__ > ((unused))) > +{ > + grub_err_t err; > + struct grub_arg_list *state = ctxt->state; > + const char *device = NULL; > + > + if (systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob != NULL) > + grub_free((void > *)systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob); > + if (systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash != > NULL) > + grub_free((void > *)systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash); > + grub_memset (&systemd_tpm2_protector_ctx, 0, sizeof > (systemd_tpm2_protector_ctx)); > + > + if (argc != 0) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > N_("systemd_tpm2_key_protector_init accepts no arguments")); > + > + if (state[OPTION_DEVICE].set) /* device */ > + { > + err = tpm2_protector_parse_device (state[OPTION_DEVICE].arg, > &device); > + if (err != GRUB_ERR_NONE) > + return err; > + } > + > + if (device == NULL) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > N_("systemd_tpm2_key_protector_init: no device provided")); > + > + /* Open disk. */ > + grub_disk_t disk = grub_disk_open (device); > + if (! disk) > + { > + err = grub_error (GRUB_ERR_BAD_ARGUMENT, > N_("systemd_tpm2_key_protector_init: can't open device %s"), device); > + goto error; > + } > + > + luks2_iterate_keyslot(disk, LUKS2_ITERATE_FLAGS_WITH_TOKEN, > luks2_iterate_fct); > + > + if (systemd_tpm2_protector_ctx.token.type != > LUKS2_TOKEN_TYPE_SYSTEMD_TPM2) > + err = grub_error (GRUB_ERR_BAD_ARGUMENT, > N_("systemd_tpm2_key_protector_init: no systemd-tpm2 token found on %s"), > device); > + else > + systemd_tpm2_protector_ctx.mode = SYSTEMD_TPM2_PROTECTOR_DEVICE_SET; > + > + grub_disk_close(disk); > + > +error: > + return err; > +} > + > +static grub_err_t > +systemd_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt > __attribute__ ((unused)), > + int argc, char **args __attribute__ > ((unused))) > +{ > + if (argc != 0) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > N_("systemd_tpm2_key_protector_clear accepts no arguments")); > + > + if (systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob != NULL) > + grub_free((void > *)systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob); > + if (systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash != > NULL) > + grub_free((void > *)systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash); > + grub_memset (&systemd_tpm2_protector_ctx, 0, sizeof > (systemd_tpm2_protector_ctx)); > + > + return GRUB_ERR_NONE; > +} > + > +static struct grub_key_protector systemd_tpm2_key_protector = > + { > + .name = "systemd-tpm2", > + .recover_key = systemd_tpm2_protector_recover_key > + }; > + > +GRUB_MOD_INIT (systemd_tpm2_key_protector) > +{ > + grub_memset (&systemd_tpm2_protector_ctx, 0, sizeof > (systemd_tpm2_protector_ctx)); > + systemd_tpm2_protector_init_cmd = > + grub_register_extcmd ("systemd_tpm2_key_protector_init", > + systemd_tpm2_protector_init_cmd_handler, 0, > + N_("device "), > + N_("Initialize the systemd TPM2 key protector."), > + systemd_tpm2_protector_init_cmd_options); > + systemd_tpm2_protector_clear_cmd = > + grub_register_extcmd ("systemd_tpm2_key_protector_clear", > + systemd_tpm2_protector_clear_cmd_handler, 0, NULL, > + N_("Clear the systemd TPM2 key protector if > previously initialized."), > + NULL); > + grub_key_protector_register (&systemd_tpm2_key_protector); > + > +} > + > +GRUB_MOD_FINI (systemd_tpm2_key_protector) > +{ > + if (systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob != NULL) > + grub_free((void > *)systemd_tpm2_protector_ctx.token.u.systemd_tpm2.base64_blob); > + if (systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash != > NULL) > + grub_free((void > *)systemd_tpm2_protector_ctx.token.u.systemd_tpm2.hex_policy_hash); > + grub_key_protector_unregister (&systemd_tpm2_key_protector); > + grub_unregister_extcmd (systemd_tpm2_protector_clear_cmd); > + grub_unregister_extcmd (systemd_tpm2_protector_init_cmd); > +} > diff --git a/grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.c > b/grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.c > new file mode 100644 > index 000000000..d07344a38 > --- /dev/null > +++ b/grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.c > @@ -0,0 +1,238 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include "tpm2_luks2.h" > + > +#include <grub/list.h> > +#include <grub/misc.h> > +#include <grub/mm.h> > +#include <grub/luks2.h> > +#include <grub/tpm2.h> > +#include <grub/tpm2srk.h> > + > +#include <tss2_buffer.h> > +#include <tss2_mu.h> > + > +static grub_err_t > +tpm2_luks2_unmarshal_raw (const void *sealed_key, > + grub_size_t sealed_key_size, > + tpm2_sealed_key_t *sk) > +{ > + struct grub_tpm2_buffer buf; > + > + grub_tpm2_buffer_init (&buf); > + if (sealed_key_size > buf.cap) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("sealed key larger than > %llu bytes"), (unsigned long long)buf.cap); > + > + grub_memcpy (buf.data, sealed_key, sealed_key_size); > + buf.size = sealed_key_size; > + > + grub_Tss2_MU_TPM2B_PRIVATE_Unmarshal (&buf, &sk->private); > + grub_Tss2_MU_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); > + > + if (buf.error != 0) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("malformed TPM wire key > file")); > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +tpm2_luks2_make_pcr_session(TPMI_SH_AUTH_SESSION_t session, grub_uint32_t > pcr_mask, grub_uint16_t pcr_bank, TPM2B_DIGEST_t *digest) > +{ > + grub_uint16_t i; > + > + TPM_RC_t rc; > + TPM2B_DIGEST_t pcr_digest = {0}; > + TPM2B_DIGEST_t policy_digest = {0}; > + TPML_PCR_SELECTION_t pcr_sel = { > + .count = 1, > + .pcrSelections = { > + { > + .hash = 0, > + .sizeOfSelect = 3, > + .pcrSelect = {0} > + }, > + } > + }; > + > + /* Specify the bank */ > + if (pcr_bank == LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA256) > + { > + pcr_sel.pcrSelections[0].hash = TPM_ALG_SHA256; > + } > + else if (LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA1) > + { > + pcr_sel.pcrSelections[0].hash = TPM_ALG_SHA1; > + } > + else > + { > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + /* Convert PCR mask to PCR selection */ > + for(i = 0; i < TPM_MAX_PCRS; ++i) > + if ((pcr_mask & (1 << i)) != 0) > + TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], i); > + > + /* PCR Policy */ > + rc = grub_tpm2_policypcr (session, NULL, &pcr_digest, &pcr_sel, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + return grub_error (GRUB_ERR_BAD_DEVICE, "Failed to submit PCR > policy (TPM2_PolicyPCR: 0x%x).", rc); > + } > + > + /* Retrieve Policy Digest */ > + rc = grub_tpm2_policygetdigest (session, NULL, &policy_digest, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + return grub_error (GRUB_ERR_BAD_DEVICE, "failed to get policy digest > (TPM2_PolicyGetDigest: 0x%x).", rc); > + } > + > + *digest = policy_digest; > + return GRUB_ERR_NONE; > +} > + > +grub_err_t > +tpm2_luks2_acquire_luks2_key( > + grub_uint32_t pcr_mask, > + grub_uint16_t pcr_bank, > + grub_uint16_t primary_alg, > + const void *key_data, > + grub_size_t key_data_size, > + const void *policy_hash, > + grub_size_t policy_hash_size, > + void **ret_decrypted_key, > + grub_size_t *ret_decrypted_key_size) { > + > + tpm2_sealed_key_t sk; > + grub_srk_type_t srk_type; > + > + grub_err_t err; > + grub_uint8_t *key_out; > + > + TPM_HANDLE_t parent_handle = 0; > + TPM_HANDLE_t sealed_handle = 0; > + TPM_HANDLE_t srk_handle = 0; > + TPMS_AUTH_COMMAND_t authCmd = {0}; > + TPM2B_NONCE_t nonceCaller = {0}; > + TPMT_SYM_DEF_t symmetric = {0}; > + TPM2B_DIGEST_t pcr_digest = {0}; > + TPM_RC_t rc; > + TPMI_SH_AUTH_SESSION_t session; > + TPM2B_SENSITIVE_DATA_t data; > + > + if (ret_decrypted_key == NULL || ret_decrypted_key_size == NULL) > + { > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + /* Decode blob: PRIVATE + PUBLIC */ > + err = tpm2_luks2_unmarshal_raw(key_data, key_data_size, &sk); > + if (err != GRUB_ERR_NONE) > + { > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Can't unmarshal blob"); > + } > + > + /* Use specified algo */ > + if (primary_alg == LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_ECC) > + { > + srk_type.noDA = false; > + srk_type.type = TPM_ALG_ECC; > + srk_type.detail.ecc_curve = TPM_ECC_NIST_P256; > + } > + else if (LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_RSA) > + { > + srk_type.noDA = false; > + srk_type.type = TPM_ALG_RSA; > + srk_type.detail.rsa_bits = 2048; > + } > + else > + { > + return GRUB_ERR_BAD_ARGUMENT; > + } > + > + parent_handle = TPM_RH_OWNER; > + if (TPM_HT_IS_PERSISTENT (parent_handle)) > + srk_handle = parent_handle; > + > + /* Load SRK and sealed and get handles */ > + err = tpm2_protector_srk_load(srk_type, &sk, parent_handle, > &sealed_handle, &srk_handle); > + if (err != GRUB_ERR_NONE) > + { > + grub_print_error (); > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Can't load srk"); > + } > + > + /* Start Auth Session */ > + nonceCaller.size = TPM_SHA256_DIGEST_SIZE; > + symmetric.algorithm = TPM_ALG_NULL; > + rc = grub_tpm2_startauthsession (TPM_RH_NULL, TPM_RH_NULL, NULL, > &nonceCaller, NULL, > + TPM_SE_POLICY, &symmetric, > TPM_ALG_SHA256, > + &session, NULL, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to start auth session > (TPM2_StartAuthSession: 0x%x)", rc); > + goto exit1; > + } > + > + /* Create PCR digest from the given setting */ > + err = tpm2_luks2_make_pcr_session(session, pcr_mask, pcr_bank, > &pcr_digest); > + if(err != GRUB_ERR_NONE) > + goto exit2; > + > + /* Compare the computed digest with the joined one */ > + if (policy_hash_size > 0 && ( policy_hash_size != pcr_digest.size || > grub_memcmp(pcr_digest.buffer, policy_hash, policy_hash_size))) > + { > + err = grub_error (GRUB_ERR_BAD_DEVICE, "Current policy digest does > not match stored policy digest, cancelling TPM2 authentication attempt."); > + goto exit2; > + } > + > + /* Unseal Sealed Key */ > + authCmd.sessionHandle = session; > + rc = grub_tpm2_unseal (sealed_handle, &authCmd, &data, NULL); > + if (rc != TPM_RC_SUCCESS) > + { > + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to unseal sealed key > (TPM2_Unseal: 0x%x)", rc); > + goto exit2; > + } > + > + /* Epilogue */ > + key_out = grub_malloc (data.size); > + if (key_out == NULL) > + { > + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("no memory left to > allocate unlock key buffer")); > + goto exit2; > + } > + > + grub_memcpy (key_out, data.buffer, data.size); > + > + *ret_decrypted_key = key_out; > + *ret_decrypted_key_size = data.size; > + > + err = GRUB_ERR_NONE; > + > + exit2: > + grub_tpm2_flushcontext (session); > + exit1: > + grub_tpm2_flushcontext (sealed_handle); > + > + if (!TPM_HT_IS_PERSISTENT (srk_handle)) > + grub_tpm2_flushcontext (srk_handle); > + > + return err; > +} > \ No newline at end of file > diff --git a/grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.h > b/grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.h > new file mode 100644 > index 000000000..b00c42868 > --- /dev/null > +++ b/grub-core/commands/systemd_tpm2_key_protector/tpm2_luks2.h > @@ -0,0 +1,37 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef GRUB_SYSTEMD_TPM2_LUKS2_TPM2_HEADER > +#define GRUB_SYSTEMD_TPM2_LUKS2_TPM2_HEADER 1 > + > +#include <grub/types.h> > +#include <grub/err.h> > + > +extern grub_err_t > +tpm2_luks2_acquire_luks2_key( > + grub_uint32_t pcr_mask, > + grub_uint16_t pcr_bank, > + grub_uint16_t primary_alg, > + const void *key_data, > + grub_size_t key_data_size, > + const void *policy_hash, > + grub_size_t policy_hash_size, > + void **ret_decrypted_key, > + grub_size_t *ret_decrypted_key_size); > + > +#endif /* GRUB_SYSTEMD_TPM2_LUKS2_TPM2_HEADER */ > diff --git a/grub-core/commands/tpm2_key_protector/module.c > b/grub-core/commands/tpm2_key_protector/module.c > index 857f3753f..553538861 100644 > --- a/grub-core/commands/tpm2_key_protector/module.c > +++ b/grub-core/commands/tpm2_key_protector/module.c > @@ -24,13 +24,14 @@ > #include <grub/misc.h> > #include <grub/mm.h> > #include <grub/key_protector.h> > +#include <grub/tpm2.h> > +#include <grub/tpm2srk.h> > > #include <tss2_buffer.h> > #include <tss2_types.h> > #include <tss2_mu.h> > > #include "tpm2_args.h" > -#include "tpm2.h" > #include "tpm2key.h" > > GRUB_MOD_LICENSE ("GPLv3+"); > @@ -400,170 +401,6 @@ tpm2_protector_unmarshal_tpm2key (void *sealed_key, > return err; > } > > -/* Check if the SRK exists in the specified handle */ > -static grub_err_t > -tpm2_protector_srk_check (const TPM_HANDLE_t srk_handle) > -{ > - TPM_RC_t rc; > - TPM2B_PUBLIC_t public; > - > - /* Find SRK */ > - rc = grub_tpm2_readpublic (srk_handle, NULL, &public); > - if (rc == TPM_RC_SUCCESS) > - return GRUB_ERR_NONE; > - > - return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve SRK from > 0x%x (TPM2_ReadPublic: 0x%x)", srk_handle, rc); > -} > - > -/* Get the SRK with the template */ > -static grub_err_t > -tpm2_protector_srk_get (const grub_srk_type_t srk_type, > - const TPM_HANDLE_t parent, > - TPM_HANDLE_t *srk_handle) > -{ > - TPM_RC_t rc; > - TPMT_PUBLIC_PARMS_t parms = {0}; > - TPMS_AUTH_COMMAND_t authCommand = {0}; > - TPM2B_SENSITIVE_CREATE_t inSensitive = {0}; > - TPM2B_PUBLIC_t inPublic = {0}; > - TPM2B_DATA_t outsideInfo = {0}; > - TPML_PCR_SELECTION_t creationPcr = {0}; > - TPM2B_PUBLIC_t outPublic = {0}; > - TPM2B_CREATION_DATA_t creationData = {0}; > - TPM2B_DIGEST_t creationHash = {0}; > - TPMT_TK_CREATION_t creationTicket = {0}; > - TPM2B_NAME_t srkName = {0}; > - TPM_HANDLE_t tmp_handle = 0; > - > - inPublic.publicArea.type = srk_type.type; > - inPublic.publicArea.nameAlg = TPM_ALG_SHA256; > - inPublic.publicArea.objectAttributes.restricted = 1; > - inPublic.publicArea.objectAttributes.userWithAuth = 1; > - inPublic.publicArea.objectAttributes.decrypt = 1; > - inPublic.publicArea.objectAttributes.fixedTPM = 1; > - inPublic.publicArea.objectAttributes.fixedParent = 1; > - inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; > - inPublic.publicArea.objectAttributes.noDA = 1; > - > - if (srk_type.type == TPM_ALG_RSA) > - { > - inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = > TPM_ALG_AES; > - inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; > - inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = > TPM_ALG_CFB; > - inPublic.publicArea.parameters.rsaDetail.scheme.scheme = > TPM_ALG_NULL; > - inPublic.publicArea.parameters.rsaDetail.keyBits = > srk_type.detail.rsa_bits; > - inPublic.publicArea.parameters.rsaDetail.exponent = 0; > - } > - else if (srk_type.type == TPM_ALG_ECC) > - { > - inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = > TPM_ALG_AES; > - inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; > - inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = > TPM_ALG_CFB; > - inPublic.publicArea.parameters.eccDetail.scheme.scheme = > TPM_ALG_NULL; > - inPublic.publicArea.parameters.eccDetail.curveID = > srk_type.detail.ecc_curve; > - inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; > - } > - else > - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown SRK algorithm"); > - > - /* Test the parameters before SRK generation */ > - parms.type = srk_type.type; > - grub_memcpy (&parms.parameters, &inPublic.publicArea.parameters, > - sizeof (TPMU_PUBLIC_PARMS_t)); > - > - rc = grub_tpm2_testparms (&parms, NULL); > - if (rc != TPM_RC_SUCCESS) > - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported SRK template > (TPM2_TestParms: 0x%x)", rc); > - > - /* Create SRK */ > - authCommand.sessionHandle = TPM_RS_PW; > - rc = grub_tpm2_createprimary (parent, &authCommand, &inSensitive, > &inPublic, > - &outsideInfo, &creationPcr, &tmp_handle, > &outPublic, > - &creationData, &creationHash, > &creationTicket, > - &srkName, NULL); > - if (rc != TPM_RC_SUCCESS) > - return grub_error (GRUB_ERR_BAD_DEVICE, "could not create SRK > (TPM2_CreatePrimary: 0x%x)", rc); > - > - *srk_handle = tmp_handle; > - > - return GRUB_ERR_NONE; > -} > - > -/* > - * Load the SRK from the persistent handle or create one with a given type > of > - * template, and then associate the sealed key with the SRK > - * Return values: > - * - GRUB_ERR_NONE: Everything is fine. > - * - GRUB_ERR_BAD_ARGUMENT: The SRK doesn't match. Try another one. > - * - Other: Something went wrong. > - */ > -static grub_err_t > -tpm2_protector_srk_load (const grub_srk_type_t srk_type, > - const tpm2_sealed_key_t *sealed_key, > - const TPM_HANDLE_t parent, > - TPM_HANDLE_t *sealed_handle, > - TPM_HANDLE_t *srk_handle) > -{ > - TPMS_AUTH_COMMAND_t authCmd = {0}; > - TPM2B_NAME_t name = {0}; > - TPM_RC_t rc; > - grub_err_t err; > - > - if (srk_handle == NULL) > - return GRUB_ERR_BUG; > - > - if (*srk_handle != 0) > - { > - err = tpm2_protector_srk_check (*srk_handle); > - if (err != GRUB_ERR_NONE) > - return err; > - } > - else > - { > - err = tpm2_protector_srk_get (srk_type, parent, srk_handle); > - if (err != GRUB_ERR_NONE) > - return err; > - } > - > - /* Load the sealed key and associate it with the SRK */ > - authCmd.sessionHandle = TPM_RS_PW; > - rc = grub_tpm2_load (*srk_handle, &authCmd, &sealed_key->private, > &sealed_key->public, > - sealed_handle, &name, NULL); > - /* > - * If TPM2_Load returns (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1), then it > - * implies the wrong SRK is used. > - */ > - if (rc == (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1)) > - { > - err = grub_error (GRUB_ERR_BAD_ARGUMENT, "SRK not matched"); > - goto error; > - } > - else if (rc != TPM_RC_SUCCESS) > - { > - err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to load sealed key > (TPM2_Load: 0x%x)", rc); > - goto error; > - } > - > - return GRUB_ERR_NONE; > - > - error: > - if (!TPM_HT_IS_PERSISTENT (*srk_handle)) > - grub_tpm2_flushcontext (*srk_handle); > - > - return err; > -} > - > -static const char * > -srk_type_to_name (grub_srk_type_t srk_type) > -{ > - if (srk_type.type == TPM_ALG_ECC && srk_type.detail.ecc_curve == > TPM_ECC_NIST_P256) > - return "ECC_NIST_P256"; > - else if (srk_type.type == TPM_ALG_RSA && srk_type.detail.rsa_bits == > 2048) > - return "RSA2048"; > - > - return "Unknown"; > -} > - > static grub_err_t > tpm2_protector_load_key (const tpm2_protector_context_t *ctx, > const tpm2_sealed_key_t *sealed_key, > @@ -577,10 +414,12 @@ tpm2_protector_load_key (const > tpm2_protector_context_t *ctx, > { > .type = TPM_ALG_ECC, > .detail.ecc_curve = TPM_ECC_NIST_P256, > + .noDA = true, > }, > { > .type = TPM_ALG_RSA, > .detail.rsa_bits = 2048, > + .noDA = true, > }, > { > .type = TPM_ALG_ERROR, > @@ -1022,6 +861,7 @@ tpm2_protector_key_from_buffer (const > tpm2_protector_context_t *ctx, > ctx_w = (tpm2_protector_context_t *)ctx; > ctx_w->srk_type.type = TPM_ALG_RSA; > ctx_w->srk_type.detail.rsa_bits = 2048; > + ctx_w->srk_type.noDA = true; > } > } > else > @@ -1289,6 +1129,7 @@ tpm2_protector_check_args (tpm2_protector_context_t > *ctx) > { > ctx->srk_type.type = TPM_ALG_ECC; > ctx->srk_type.detail.ecc_curve = TPM_ECC_NIST_P256; > + ctx->srk_type.noDA = true; > } > > return GRUB_ERR_NONE; > diff --git a/grub-core/commands/tpm2_key_protector/tpm2_args.h > b/grub-core/commands/tpm2_key_protector/tpm2_args.h > index bdbf9f373..805e293f0 100644 > --- a/grub-core/commands/tpm2_key_protector/tpm2_args.h > +++ b/grub-core/commands/tpm2_key_protector/tpm2_args.h > @@ -21,18 +21,7 @@ > #define GRUB_TPM2_INTERNAL_ARGS_HEADER 1 > > #include <grub/err.h> > - > -#include "tpm2.h" > - > -struct grub_srk_type > -{ > - TPMI_ALG_PUBLIC_t type; > - union { > - TPM_KEY_BITS_t rsa_bits; > - TPM_ECC_CURVE_t ecc_curve; > - } detail; > -}; > -typedef struct grub_srk_type grub_srk_type_t; > +#include <grub/tpm2.h> > > extern grub_err_t > grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, > grub_uint8_t *pcr_count); > diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c > index 8036d76ff..3e0894320 100644 > --- a/grub-core/disk/luks2.c > +++ b/grub-core/disk/luks2.c > @@ -28,6 +28,8 @@ > #include <grub/i18n.h> > #include <grub/safemath.h> > > +#include <grub/luks2.h> > + > #include <base64.h> > #include <json.h> > > @@ -36,12 +38,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); > #define LUKS_MAGIC_1ST "LUKS\xBA\xBE" > #define LUKS_MAGIC_2ND "SKUL\xBA\xBE" > > -enum grub_luks2_kdf_type > -{ > - LUKS2_KDF_TYPE_ARGON2I, > - LUKS2_KDF_TYPE_PBKDF2 > -}; > -typedef enum grub_luks2_kdf_type grub_luks2_kdf_type_t; > +/* From tss2_types.h */ > +#define TPM_MAX_PCRS 24 > > /* On disk LUKS header */ > struct grub_luks2_header > @@ -62,69 +60,6 @@ struct grub_luks2_header > } GRUB_PACKED; > typedef struct grub_luks2_header grub_luks2_header_t; > > -struct grub_luks2_keyslot > -{ > - /* The integer key to the associative array of keyslots. */ > - grub_uint64_t idx; > - grub_int64_t key_size; > - grub_int64_t priority; > - struct > - { > - const char *encryption; > - grub_uint64_t offset; > - grub_uint64_t size; > - grub_int64_t key_size; > - } area; > - struct > - { > - const char *hash; > - grub_int64_t stripes; > - } af; > - struct > - { > - grub_luks2_kdf_type_t type; > - const char *salt; > - union > - { > - struct > - { > - grub_int64_t time; > - grub_int64_t memory; > - grub_int64_t cpus; > - } argon2i; > - struct > - { > - const char *hash; > - grub_int64_t iterations; > - } pbkdf2; > - } u; > - } kdf; > -}; > -typedef struct grub_luks2_keyslot grub_luks2_keyslot_t; > - > -struct grub_luks2_segment > -{ > - grub_uint64_t idx; > - grub_uint64_t offset; > - const char *size; > - const char *encryption; > - grub_int64_t sector_size; > -}; > -typedef struct grub_luks2_segment grub_luks2_segment_t; > - > -struct grub_luks2_digest > -{ > - grub_uint64_t idx; > - /* Both keyslots and segments are interpreted as bitfields here */ > - grub_uint64_t keyslots; > - grub_uint64_t segments; > - const char *salt; > - const char *digest; > - const char *hash; > - grub_int64_t iterations; > -}; > -typedef struct grub_luks2_digest grub_luks2_digest_t; > - > gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, > grub_uint8_t * dst, grub_size_t blocksize, > grub_size_t blocknumbers); > @@ -258,11 +193,78 @@ luks2_parse_digest (grub_luks2_digest_t *out, const > grub_json_t *digest) > return GRUB_ERR_NONE; > } > > +static grub_err_t > +luks2_parse_token (grub_luks2_token_t *out, const grub_json_t *token) > +{ > + grub_json_t keyslots, pcrs, o; > + grub_size_t i, size; > + grub_uint64_t bit; > + const char *type; > + const char *pcr_bank; > + const char *alg; > + > + if (grub_json_getstring (&type, token, "type")) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest type"); > + else if (grub_strcmp (type, "systemd-tpm2")) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported digest type %s", > type); > + out->type = LUKS2_TOKEN_TYPE_SYSTEMD_TPM2; > + > + if (grub_json_getvalue (&keyslots, token, "keyslots") || > + grub_json_getvalue (&pcrs, token, "tpm2-pcrs") || > + grub_json_getstring (&pcr_bank, token, "tpm2-pcr-bank") || > + grub_json_getstring (&alg, token, "tpm2-primary-alg") || > + grub_json_getstring (&out->u.systemd_tpm2.base64_blob, token, > "tpm2-blob") || > + grub_json_getstring (&out->u.systemd_tpm2.hex_policy_hash, token, > "tpm2-policy-hash")) > + { > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing token parameters"); > + } > + > + if (grub_json_getsize (&size, &pcrs)) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "token references no pcrs"); > + > + out->u.systemd_tpm2.pcr_mask = 0; > + for (i = 0; i < size; i++) > + { > + if (grub_json_getchild (&o, &pcrs, i) || > + grub_json_getuint64 (&bit, &o, NULL) || bit >= TPM_MAX_PCRS) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid pcr"); > + out->u.systemd_tpm2.pcr_mask |= (1 << bit); > + } > + > + if (grub_strcmp (pcr_bank, "sha256") == 0) > + out->u.systemd_tpm2.pcr_bank = > LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA256; > + else if (grub_strcmp (pcr_bank, "sha1") == 0) > + out->u.systemd_tpm2.pcr_bank = > LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA1; > + else > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported pcr-bank type > %s", pcr_bank); > + > + if (grub_strcmp (alg, "ecc") == 0) > + out->u.systemd_tpm2.primary_alg = > LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_ECC; > + else if (grub_strcmp (alg, "rsa") == 0) > + out->u.systemd_tpm2.primary_alg = > LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_RSA; > + else > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported algo type %s", > alg); > + > + if (grub_json_getsize (&size, &keyslots)) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "token references no > keyslots"); > + > + out->keyslots = 0; > + for (i = 0; i < size; i++) > + { > + if (grub_json_getchild (&o, &keyslots, i) || > + grub_json_getuint64 (&bit, &o, NULL)) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot"); > + out->keyslots |= (1 << bit); > + } > + > + return GRUB_ERR_NONE; > +} > + > static grub_err_t > luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, > grub_luks2_segment_t *s, > - const grub_json_t *root, grub_size_t keyslot_json_idx) > + grub_luks2_token_t *t, const grub_json_t *root, grub_size_t > keyslot_json_idx) > { > - grub_json_t keyslots, keyslot, digests, digest, segments, segment; > + grub_json_t keyslots, keyslot, digests, digest, segments, segment, > tokens, token; > grub_size_t json_idx, size; > > /* Get nth keyslot */ > @@ -309,6 +311,27 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k, > grub_luks2_digest_t *d, grub_luks2_s > if (json_idx == size) > return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%" > PRIuGRUB_UINT64_T "\"", d->idx); > > + if (t == NULL) > + return GRUB_ERR_NONE; > + > + /* Get token that matches the keyslot. */ > + if (grub_json_getvalue (&tokens, root, "tokens") || > + grub_json_getsize (&size, &tokens)) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get tokens"); > + for (json_idx = 0; json_idx < size; json_idx++) > + { > + if (grub_json_getchild (&token, &tokens, json_idx) || > + grub_json_getuint64 (&t->idx, &token, NULL) || > + grub_json_getchild (&token, &token, 0) || > + luks2_parse_token (t, &token)) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse token > index %" PRIuGRUB_SIZE, json_idx); > + > + if ((t->keyslots & (1 << k->idx))) > + break; > + } > + if (json_idx == size) > + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No token for keyslot > \"%" PRIuGRUB_UINT64_T "\"", k->idx); > + > return GRUB_ERR_NONE; > } > > @@ -555,6 +578,91 @@ luks2_decrypt_key (grub_uint8_t *out_key, > return ret; > } > > +extern grub_err_t > +luks2_iterate_keyslot(grub_disk_t source, grub_uint32_t flags, > luks2_iterate_fct_t fct) > +{ > + char *json_header = NULL, *ptr; > + grub_size_t json_idx, size; > + grub_luks2_header_t header; > + grub_luks2_keyslot_t keyslot; > + grub_luks2_digest_t digest; > + grub_luks2_segment_t segment; > + grub_luks2_token_t token; > + grub_json_t *json = NULL, keyslots; > + grub_err_t ret; > + grub_size_t sz; > + > + ret = luks2_read_header (source, &header); > + if (ret) > + return ret; > + > + if (grub_sub (grub_be_to_cpu64 (header.hdr_size), sizeof (header), &sz)) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while > calculating json header size"); > + > + json_header = grub_zalloc (sz); > + if (!json_header) > + return GRUB_ERR_OUT_OF_MEMORY; > + > + /* Read the JSON area. */ > + ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + > sizeof (header), > + grub_be_to_cpu64 (header.hdr_size) - sizeof > (header), json_header); > + if (ret) > + goto err; > + > + ptr = grub_memchr (json_header, 0, grub_be_to_cpu64 (header.hdr_size) - > sizeof (header)); > + if (!ptr) > + goto err; > + > + ret = grub_json_parse (&json, json_header, grub_be_to_cpu64 > (header.hdr_size)); > + if (ret) > + { > + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid LUKS2 JSON > header"); > + goto err; > + } > + > + if (grub_json_getvalue (&keyslots, json, "keyslots") || > + grub_json_getsize (&size, &keyslots)) > + { > + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get keyslots"); > + goto err; > + } > + > + if (grub_disk_native_sectors (source) == GRUB_DISK_SIZE_UNKNOWN) > + { > + /* FIXME: Allow use of source disk, and maybe cause errors in read. > */ > + grub_dprintf ("luks2", "Source disk %s has an unknown size, " > + "conservatively returning error\n", > source->name); > + ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source > device"); > + goto err; > + } > + > + /* Try all keyslot */ > + for (json_idx = 0; json_idx < size; json_idx++) > + { > + grub_errno = GRUB_ERR_NONE; > + ret = luks2_get_keyslot (&keyslot, &digest, &segment, (flags & > LUKS2_ITERATE_FLAGS_WITH_TOKEN) ? &token: NULL, json, json_idx); > + if (ret) > + { > + /* > + * luks2_get_keyslot() can fail for a variety of reasons that do > not > + * necessarily mean the next keyslot should not be tried (e.g. a > new > + * kdf type). So always try the next slot. > + */ > + grub_dprintf ("luks2", "Failed to get keyslot %" PRIuGRUB_UINT64_T > "\n", keyslot.idx); > + continue; > + } > + if (grub_errno != GRUB_ERR_NONE) > + grub_dprintf ("luks2", "Ignoring unhandled error %d from > luks2_get_keyslot\n", grub_errno); > + > + > + fct(&keyslot, &digest, &segment, (flags & > LUKS2_ITERATE_FLAGS_WITH_TOKEN) ? &token: NULL); > + } > +err: > + grub_free (json_header); > + grub_json_free (json); > + return ret; > +} > + > static grub_err_t > luks2_recover_key (grub_disk_t source, > grub_cryptodisk_t crypt, > @@ -626,7 +734,7 @@ luks2_recover_key (grub_disk_t source, > typeof (source->total_sectors) max_crypt_sectors = 0; > > grub_errno = GRUB_ERR_NONE; > - ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, > json_idx); > + ret = luks2_get_keyslot (&keyslot, &digest, &segment, NULL, json, > json_idx); > if (ret) > { > /* > diff --git a/grub-core/lib/base64.c b/grub-core/lib/base64.c > new file mode 100644 > index 000000000..b12668fad > --- /dev/null > +++ b/grub-core/lib/base64.c > @@ -0,0 +1,21 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/dl.h> > + > +GRUB_MOD_LICENSE ("GPLv2+"); > \ No newline at end of file > diff --git a/grub-core/lib/tpm2srk.c b/grub-core/lib/tpm2srk.c > new file mode 100644 > index 000000000..3c1e4f7dc > --- /dev/null > +++ b/grub-core/lib/tpm2srk.c > @@ -0,0 +1,191 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2022 Microsoft Corporation > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/tpm2srk.h> > + > +#include <grub/dl.h> > +#include <grub/misc.h> > +#include <grub/types.h> > +#include <stddef.h> > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +/* Check if the SRK exists in the specified handle */ > +grub_err_t > +tpm2_protector_srk_check (const TPM_HANDLE_t srk_handle) > +{ > + TPM_RC_t rc; > + TPM2B_PUBLIC_t public; > + > + /* Find SRK */ > + rc = grub_tpm2_readpublic (srk_handle, NULL, &public); > + if (rc == TPM_RC_SUCCESS) > + return GRUB_ERR_NONE; > + > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve SRK from > 0x%x (TPM2_ReadPublic: 0x%x)", srk_handle, rc); > +} > + > +/* Get the SRK with the template */ > +grub_err_t > +tpm2_protector_srk_get (const grub_srk_type_t srk_type, > + const TPM_HANDLE_t parent, > + TPM_HANDLE_t *srk_handle) > +{ > + TPM_RC_t rc; > + TPMT_PUBLIC_PARMS_t parms = {0}; > + TPMS_AUTH_COMMAND_t authCommand = {0}; > + TPM2B_SENSITIVE_CREATE_t inSensitive = {0}; > + TPM2B_PUBLIC_t inPublic = {0}; > + TPM2B_DATA_t outsideInfo = {0}; > + TPML_PCR_SELECTION_t creationPcr = {0}; > + TPM2B_PUBLIC_t outPublic = {0}; > + TPM2B_CREATION_DATA_t creationData = {0}; > + TPM2B_DIGEST_t creationHash = {0}; > + TPMT_TK_CREATION_t creationTicket = {0}; > + TPM2B_NAME_t srkName = {0}; > + TPM_HANDLE_t tmp_handle = 0; > + > + inPublic.publicArea.type = srk_type.type; > + inPublic.publicArea.nameAlg = TPM_ALG_SHA256; > + inPublic.publicArea.objectAttributes.restricted = 1; > + inPublic.publicArea.objectAttributes.userWithAuth = 1; > + inPublic.publicArea.objectAttributes.decrypt = 1; > + inPublic.publicArea.objectAttributes.fixedTPM = 1; > + inPublic.publicArea.objectAttributes.fixedParent = 1; > + inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; > + inPublic.publicArea.objectAttributes.noDA = srk_type.noDA; > + > + if (srk_type.type == TPM_ALG_RSA) > + { > + inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = > TPM_ALG_AES; > + inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; > + inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = > TPM_ALG_CFB; > + inPublic.publicArea.parameters.rsaDetail.scheme.scheme = > TPM_ALG_NULL; > + inPublic.publicArea.parameters.rsaDetail.keyBits = > srk_type.detail.rsa_bits; > + inPublic.publicArea.parameters.rsaDetail.exponent = 0; > + } > + else if (srk_type.type == TPM_ALG_ECC) > + { > + inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = > TPM_ALG_AES; > + inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; > + inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = > TPM_ALG_CFB; > + inPublic.publicArea.parameters.eccDetail.scheme.scheme = > TPM_ALG_NULL; > + inPublic.publicArea.parameters.eccDetail.curveID = > srk_type.detail.ecc_curve; > + inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; > + } > + else > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown SRK algorithm"); > + > + /* Test the parameters before SRK generation */ > + parms.type = srk_type.type; > + grub_memcpy (&parms.parameters, &inPublic.publicArea.parameters, > + sizeof (TPMU_PUBLIC_PARMS_t)); > + > + rc = grub_tpm2_testparms (&parms, NULL); > + if (rc != TPM_RC_SUCCESS) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported SRK template > (TPM2_TestParms: 0x%x)", rc); > + > + /* Create SRK */ > + authCommand.sessionHandle = TPM_RS_PW; > + rc = grub_tpm2_createprimary (parent, &authCommand, &inSensitive, > &inPublic, > + &outsideInfo, &creationPcr, &tmp_handle, > &outPublic, > + &creationData, &creationHash, > &creationTicket, > + &srkName, NULL); > + if (rc != TPM_RC_SUCCESS) > + return grub_error (GRUB_ERR_BAD_DEVICE, "could not create SRK > (TPM2_CreatePrimary: 0x%x)", rc); > + > + *srk_handle = tmp_handle; > + > + return GRUB_ERR_NONE; > +} > + > +/* > + * Load the SRK from the persistent handle or create one with a given type > of > + * template, and then associate the sealed key with the SRK > + * Return values: > + * - GRUB_ERR_NONE: Everything is fine. > + * - GRUB_ERR_BAD_ARGUMENT: The SRK doesn't match. Try another one. > + * - Other: Something went wrong. > + */ > +grub_err_t > +tpm2_protector_srk_load (const grub_srk_type_t srk_type, > + const tpm2_sealed_key_t *sealed_key, > + const TPM_HANDLE_t parent, > + TPM_HANDLE_t *sealed_handle, > + TPM_HANDLE_t *srk_handle) > +{ > + TPMS_AUTH_COMMAND_t authCmd = {0}; > + TPM2B_NAME_t name = {0}; > + TPM_RC_t rc; > + grub_err_t err; > + > + if (srk_handle == NULL) > + return GRUB_ERR_BUG; > + > + if (*srk_handle != 0) > + { > + err = tpm2_protector_srk_check (*srk_handle); > + if (err != GRUB_ERR_NONE) > + return err; > + } > + else > + { > + err = tpm2_protector_srk_get (srk_type, parent, srk_handle); > + if (err != GRUB_ERR_NONE) > + return err; > + } > + > + /* Load the sealed key and associate it with the SRK */ > + authCmd.sessionHandle = TPM_RS_PW; > + rc = grub_tpm2_load (*srk_handle, &authCmd, &sealed_key->private, > &sealed_key->public, > + sealed_handle, &name, NULL); > + /* > + * If TPM2_Load returns (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1), then it > + * implies the wrong SRK is used. > + */ > + if (rc == (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1)) > + { > + err = grub_error (GRUB_ERR_BAD_ARGUMENT, "SRK not matched"); > + goto error; > + } > + else if (rc != TPM_RC_SUCCESS) > + { > + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to load sealed key > (TPM2_Load: 0x%x)", rc); > + goto error; > + } > + > + return GRUB_ERR_NONE; > + > + error: > + if (!TPM_HT_IS_PERSISTENT (*srk_handle)) > + grub_tpm2_flushcontext (*srk_handle); > + > + return err; > +} > + > +const char * > +srk_type_to_name (grub_srk_type_t srk_type) > +{ > + if (srk_type.type == TPM_ALG_ECC && srk_type.detail.ecc_curve == > TPM_ECC_NIST_P256) > + return "ECC_NIST_P256"; > + else if (srk_type.type == TPM_ALG_RSA && srk_type.detail.rsa_bits == > 2048) > + return "RSA2048"; > + > + return "Unknown"; > +} > \ No newline at end of file > diff --git a/include/grub/luks2.h b/include/grub/luks2.h > new file mode 100644 > index 000000000..494307398 > --- /dev/null > +++ b/include/grub/luks2.h > @@ -0,0 +1,148 @@ > +/* luks2.h - On disk structures for LUKS2. */ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2006,2007 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef GRUB_LUKS2_H > +#define GRUB_LUKS2_H 1 > + > +#include <grub/disk.h> > +#include <grub/err.h> > + > +enum grub_luks2_kdf_type > +{ > + LUKS2_KDF_TYPE_ARGON2I, > + LUKS2_KDF_TYPE_PBKDF2 > +}; > +typedef enum grub_luks2_kdf_type grub_luks2_kdf_type_t; > + > +struct grub_luks2_keyslot > +{ > + /* The integer key to the associative array of keyslots. */ > + grub_uint64_t idx; > + grub_int64_t key_size; > + grub_int64_t priority; > + struct > + { > + const char *encryption; > + grub_uint64_t offset; > + grub_uint64_t size; > + grub_int64_t key_size; > + } area; > + struct > + { > + const char *hash; > + grub_int64_t stripes; > + } af; > + struct > + { > + grub_luks2_kdf_type_t type; > + const char *salt; > + union > + { > + struct > + { > + grub_int64_t time; > + grub_int64_t memory; > + grub_int64_t cpus; > + } argon2i; > + struct > + { > + const char *hash; > + grub_int64_t iterations; > + } pbkdf2; > + } u; > + } kdf; > +}; > +typedef struct grub_luks2_keyslot grub_luks2_keyslot_t; > + > +struct grub_luks2_segment > +{ > + grub_uint64_t idx; > + grub_uint64_t offset; > + const char *size; > + const char *encryption; > + grub_int64_t sector_size; > +}; > +typedef struct grub_luks2_segment grub_luks2_segment_t; > + > +struct grub_luks2_digest > +{ > + grub_uint64_t idx; > + /* Both keyslots and segments are interpreted as bitfields here */ > + grub_uint64_t keyslots; > + grub_uint64_t segments; > + const char *salt; > + const char *digest; > + const char *hash; > + grub_int64_t iterations; > +}; > +typedef struct grub_luks2_digest grub_luks2_digest_t; > + > + > +enum grub_luks2_token_type > +{ > + LUKS2_TOKEN_TYPE_NONE, > + LUKS2_TOKEN_TYPE_SYSTEMD_TPM2 > +}; > + > +typedef enum grub_luks2_token_type grub_luks2_token_type_t; > + > +enum grub_luks2_token_systemd_tpm2_algo_type > +{ > + LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_ECC, > + LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_RSA > +}; > + > +typedef enum grub_luks2_token_systemd_tpm2_algo_type > grub_luks2_token_systemd_tpm2_algo_type_t; > + > +enum grub_luks2_token_systemd_tpm2_pcr_bank_type > +{ > + LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA256, > + LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA1 > +}; > + > +typedef enum grub_luks2_token_systemd_tpm2_pcr_bank_type > grub_luks2_token_systemd_tpm2_pcr_bank_type_t; > + > +struct grub_luks2_token > +{ > + grub_uint64_t idx; > + grub_luks2_token_type_t type; > + grub_uint64_t keyslots; > + union > + { > + struct > + { > + grub_uint32_t pcr_mask; > + grub_luks2_token_systemd_tpm2_pcr_bank_type_t pcr_bank; > + grub_luks2_token_systemd_tpm2_algo_type_t primary_alg; > + const char *base64_blob; > + const char *hex_policy_hash; > + } systemd_tpm2; > + } u; > +}; > +typedef struct grub_luks2_token grub_luks2_token_t; > + > +typedef void (*luks2_iterate_fct_t)(grub_luks2_keyslot_t *k, > grub_luks2_digest_t *d, grub_luks2_segment_t *s, grub_luks2_token_t *t); > + > +#define LUKS2_ITERATE_FLAGS_NONE 0 > +#define LUKS2_ITERATE_FLAGS_WITH_TOKEN 1 << 0 > + > +extern grub_err_t > +luks2_iterate_keyslot(grub_disk_t source, grub_uint32_t flags, > luks2_iterate_fct_t fct); > + > +#endif /* ! GRUB_LUKS2_H */ > \ No newline at end of file > diff --git a/grub-core/commands/tpm2_key_protector/tpm2.h > b/include/grub/tpm2.h > similarity index 85% > rename from grub-core/commands/tpm2_key_protector/tpm2.h > rename to include/grub/tpm2.h > index 1c1d871b4..1e25a9bdd 100644 > --- a/grub-core/commands/tpm2_key_protector/tpm2.h > +++ b/include/grub/tpm2.h > @@ -33,4 +33,15 @@ struct tpm2_sealed_key { > }; > typedef struct tpm2_sealed_key tpm2_sealed_key_t; > > +struct grub_srk_type > +{ > + TPMI_ALG_PUBLIC_t type; > + union { > + TPM_KEY_BITS_t rsa_bits; > + TPM_ECC_CURVE_t ecc_curve; > + } detail; > + bool noDA; > +}; > +typedef struct grub_srk_type grub_srk_type_t; > + > #endif /* ! GRUB_TPM2_TPM2_HEADER */ > diff --git a/include/grub/tpm2srk.h b/include/grub/tpm2srk.h > new file mode 100644 > index 000000000..684d89bba > --- /dev/null > +++ b/include/grub/tpm2srk.h > @@ -0,0 +1,44 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2022 Microsoft Corporation > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#ifndef GRUB_TPM2_INTERNAL_SRK_HEADER > +#define GRUB_TPM2_INTERNAL_SRK_HEADER 1 > + > +#include <grub/err.h> > +#include <grub/tpm2.h> > + > +grub_err_t > +tpm2_protector_srk_check (const TPM_HANDLE_t srk_handle); > + > +grub_err_t > +tpm2_protector_srk_get (const grub_srk_type_t srk_type, > + const TPM_HANDLE_t parent, > + TPM_HANDLE_t *srk_handle); > + > +grub_err_t > +tpm2_protector_srk_load (const grub_srk_type_t srk_type, > + const tpm2_sealed_key_t *sealed_key, > + const TPM_HANDLE_t parent, > + TPM_HANDLE_t *sealed_handle, > + TPM_HANDLE_t *srk_handle); > + > +const char * > +srk_type_to_name (grub_srk_type_t srk_type); > + > +#endif //GRUB_TPM2_INTERNAL_SRK_HEADER > diff --git a/util/grub-protect.c b/util/grub-protect.c > index 40d4a3fc5..c565daf5e 100644 > --- a/util/grub-protect.c > +++ b/util/grub-protect.c > @@ -31,12 +31,14 @@ > #include <grub/emu/misc.h> > > #include <grub/util/misc.h> > +#include <grub/tpm2.h> > +#include <grub/tpm2srk.h> > > #include <tss2_buffer.h> > #include <tss2_mu.h> > #include <tcg2.h> > #include <tpm2_args.h> > -#include <tpm2.h> > +#include <base64.h> > > #pragma GCC diagnostic ignored "-Wmissing-prototypes" > #pragma GCC diagnostic ignored "-Wmissing-declarations" > @@ -534,18 +536,10 @@ protect_tpm2_get_policy_digest (protect_args_t *args, > TPM2B_DIGEST_t *digest) > static grub_err_t > protect_tpm2_get_srk (protect_args_t *args, TPM_HANDLE_t *srk) > { > + grub_err_t ret; > TPM_RC_t rc; > TPM2B_PUBLIC_t public; > TPMS_AUTH_COMMAND_t authCommand = {0}; > - TPM2B_SENSITIVE_CREATE_t inSensitive = {0}; > - TPM2B_PUBLIC_t inPublic = {0}; > - TPM2B_DATA_t outsideInfo = {0}; > - TPML_PCR_SELECTION_t creationPcr = {0}; > - TPM2B_PUBLIC_t outPublic = {0}; > - TPM2B_CREATION_DATA_t creationData = {0}; > - TPM2B_DIGEST_t creationHash = {0}; > - TPMT_TK_CREATION_t creationTicket = {0}; > - TPM2B_NAME_t srkName = {0}; > TPM_HANDLE_t srkHandle; > > if (args->tpm2_srk != 0) > @@ -567,50 +561,11 @@ protect_tpm2_get_srk (protect_args_t *args, > TPM_HANDLE_t *srk) > } > } > > - /* Create SRK */ > authCommand.sessionHandle = TPM_RS_PW; > - inPublic.publicArea.type = args->srk_type.type; > - inPublic.publicArea.nameAlg = TPM_ALG_SHA256; > - inPublic.publicArea.objectAttributes.restricted = 1; > - inPublic.publicArea.objectAttributes.userWithAuth = 1; > - inPublic.publicArea.objectAttributes.decrypt = 1; > - inPublic.publicArea.objectAttributes.fixedTPM = 1; > - inPublic.publicArea.objectAttributes.fixedParent = 1; > - inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; > - inPublic.publicArea.objectAttributes.noDA = 1; > - > - switch (args->srk_type.type) > - { > - case TPM_ALG_RSA: > - inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = > TPM_ALG_AES; > - inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; > - inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = > TPM_ALG_CFB; > - inPublic.publicArea.parameters.rsaDetail.scheme.scheme = > TPM_ALG_NULL; > - inPublic.publicArea.parameters.rsaDetail.keyBits = > args->srk_type.detail.rsa_bits; > - inPublic.publicArea.parameters.rsaDetail.exponent = 0; > - break; > - > - case TPM_ALG_ECC: > - inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = > TPM_ALG_AES; > - inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; > - inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = > TPM_ALG_CFB; > - inPublic.publicArea.parameters.eccDetail.scheme.scheme = > TPM_ALG_NULL; > - inPublic.publicArea.parameters.eccDetail.curveID = > args->srk_type.detail.ecc_curve; > - inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; > - break; > - > - default: > - return GRUB_ERR_BAD_ARGUMENT; > - } > - > - rc = grub_tpm2_createprimary (TPM_RH_OWNER, &authCommand, &inSensitive, > &inPublic, > - &outsideInfo, &creationPcr, &srkHandle, > &outPublic, > - &creationData, &creationHash, > &creationTicket, > - &srkName, NULL); > - if (rc != TPM_RC_SUCCESS) > + ret = tpm2_protector_srk_get(args->srk_type, TPM_RH_OWNER, &srkHandle); > + if (ret != GRUB_ERR_NONE) > { > - fprintf (stderr, "Failed to create SRK (TPM2_CreatePrimary: > 0x%x).\n", rc); > - return GRUB_ERR_BAD_DEVICE; > + return ret; > } > > /* Persist SRK */ > @@ -1274,6 +1229,7 @@ protect_tpm2_args_verify (protect_args_t *args) > { > args->srk_type.type = TPM_ALG_ECC; > args->srk_type.detail.ecc_curve = TPM_ECC_NIST_P256; > + args->srk_type.noDA = true; > } > > if (args->tpm2_bank == TPM_ALG_ERROR) > -- > 2.39.5 > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel