On Fri, Apr 12, 2024 at 04:52:02PM -0400, Stefan Berger wrote: > > > On 4/12/24 04:39, Gary Lin via Grub-devel wrote: > > From: Hernan Gatta <hega...@linux.microsoft.com> > > > > To utilize the key protectors framework, there must be a way to protect > > full-disk encryption keys in the first place. The grub-protect tool > > includes support for the TPM2 key protector but other protectors that > > require setup ahead of time can be supported in the future. > > > > For the TPM2 key protector, the intended flow is for a user to have a > > LUKS 1 or LUKS 2-protected fully-encrypted disk. The user then creates a > > new LUKS key file, say by reading /dev/urandom into a file, and creates > > a new LUKS key slot for this key. Then, the user invokes the grub-protect > > tool to seal this key file to a set of PCRs using the system's TPM 2.0. > > The resulting sealed key file is stored in an unencrypted partition such > > as the EFI System Partition (ESP) so that GRUB may read it. The user also > > has to ensure the cryptomount command is included in GRUB's boot script > > and that it carries the requisite key protector (-P) parameter. > > > > Sample usage: > > > > $ dd if=/dev/urandom of=luks-key bs=1 count=32 > > $ sudo cryptsetup luksAddKey /dev/sdb1 luks-key --pbkdf=pbkdf2 --hash=sha512 > > > > To seal the key with TPM 2.0 Key File (recommended): > > > > $ sudo grub-protect --action=add \ > > --protector=tpm2 \ > > --tpm2-pcrs=0,2,4,7,9 \ > > --tpm2key \ > > --tpm2-keyfile=luks-key \ > > --tpm2-outfile=/boot/efi/boot/grub2/sealed.tpm > > > > Or, to seal the key with the raw sealed key: > > > > $ sudo grub-protect --action=add \ > > --protector=tpm2 \ > > --tpm2-pcrs=0,2,4,7,9 \ > > --tpm2-keyfile=luks-key \ > > --tpm2-outfile=/boot/efi/boot/grub2/sealed.key > > > > Then, in the boot script, for TPM 2.0 Key File: > > > > tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm > > cryptomount -u <SDB1_UUID> -P tpm2 > > > > Or, for the raw sealed key: > > > > tpm2_key_protector_init --keyfile=(hd0,gpt1)/boot/grub2/sealed.key > > --pcrs=0,2,4,7,9 > > cryptomount -u <SDB1_UUID> -P tpm2 > > > > The benefit of using TPM 2.0 Key File is that the PCR set is already > > written in the key file, so there is no need to specify PCRs when > > invoking tpm2_key_protector_init. > > > > Signed-off-by: Hernan Gatta <hega...@linux.microsoft.com> > > Signed-off-by: Gary Lin <g...@suse.com> > > --- > > .gitignore | 2 + > > Makefile.util.def | 22 + > > configure.ac | 30 + > > util/grub-protect.c | 1396 +++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 1450 insertions(+) > > create mode 100644 util/grub-protect.c > > > > diff --git a/.gitignore b/.gitignore > > index 4d0dfb700..d7b7c22d6 100644 > > --- a/.gitignore > > +++ b/.gitignore > > @@ -169,6 +169,8 @@ widthspec.bin > > /grub-ofpathname.exe > > /grub-probe > > /grub-probe.exe > > +/grub-protect > > +/grub-protect.exe > > /grub-reboot > > /grub-render-label > > /grub-render-label.exe > > diff --git a/Makefile.util.def b/Makefile.util.def > > index 19ad5a96f..a0a3e2cd5 100644 > > --- a/Makefile.util.def > > +++ b/Makefile.util.def > > @@ -207,6 +207,28 @@ program = { > > ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; > > }; > > +program = { > > + name = grub-protect; > > + > > + common = grub-core/osdep/init.c; > > + common = grub-core/tpm2/args.c; > > + common = grub-core/tpm2/buffer.c; > > + common = grub-core/tpm2/mu.c; > > + common = grub-core/tpm2/tpm2.c; > > + common = grub-core/tpm2/tpm2key_asn1_tab.c; > > + common = util/grub-protect.c; > > + common = util/probe.c; > > + > > + ldadd = libgrubmods.a; > > + ldadd = libgrubgcry.a; > > + ldadd = libgrubkern.a; > > + ldadd = grub-core/lib/gnulib/libgnu.a; > > + ldadd = '$(LIBTASN1)'; > > + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) > > $(LIBGEOM)'; > > + > > + condition = COND_GRUB_PROTECT; > > +}; > > + > > program = { > > name = grub-mkrelpath; > > mansection = 1; > > diff --git a/configure.ac b/configure.ac > > index 84a202c6e..3a07ab570 100644 > > --- a/configure.ac > > +++ b/configure.ac > > @@ -76,6 +76,7 @@ grub_TRANSFORM([grub-mkpasswd-pbkdf2]) > > grub_TRANSFORM([grub-mkrelpath]) > > grub_TRANSFORM([grub-mkrescue]) > > grub_TRANSFORM([grub-probe]) > > +grub_TRANSFORM([grub-protect]) > > grub_TRANSFORM([grub-reboot]) > > grub_TRANSFORM([grub-script-check]) > > grub_TRANSFORM([grub-set-default]) > > @@ -2057,6 +2058,29 @@ fi > > AC_SUBST([LIBZFS]) > > AC_SUBST([LIBNVPAIR]) > > +AC_ARG_ENABLE([grub-protect], > > + [AS_HELP_STRING([--enable-grub-protect], > > + [build and install the `grub-protect' utility > > (default=guessed)])]) > > +if test x"$enable_grub_protect" = xno ; then > > + grub_protect_excuse="explicitly disabled" > > +fi > > + > > +LIBTASN1= > > +if test x"$grub_protect_excuse" = x ; then > > + AC_CHECK_LIB([tasn1], [asn1_write_value], [LIBTASN1="-ltasn1"], > > [grub_protect_excuse="need libtasn1 library"]) > > +fi > > +AC_SUBST([LIBTASN1]) > > + > > +if test x"$enable_grub_protect" = xyes && test x"$grub_protect_excuse" != > > x ; then > > + AC_MSG_ERROR([grub-protect was explicitly requested but can't be > > compiled ($grub_protect_excuse)]) > > +fi > > +if test x"$grub_protect_excuse" = x ; then > > +enable_grub_protect=yes > > +else > > +enable_grub_protect=no > > +fi > > +AC_SUBST([enable_grub_protect]) > > + > > LIBS="" > > AC_SUBST([FONT_SOURCE]) > > @@ -2173,6 +2197,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test > > x$enable_grub_emu_sdl = xyes]) > > AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) > > AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) > > AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes]) > > +AM_CONDITIONAL([COND_GRUB_PROTECT], [test x$enable_grub_protect = xyes]) > > AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) > > if test x$FONT_SOURCE != x ; then > > HAVE_FONT_SOURCE=1 > > @@ -2300,6 +2325,11 @@ echo grub-mount: Yes > > else > > echo grub-mount: No "($grub_mount_excuse)" > > fi > > +if [ x"$grub_protect_excuse" = x ]; then > > +echo grub-protect: Yes > > +else > > +echo grub-protect: No "($grub_protect_excuse)" > > +fi > > if [ x"$starfield_excuse" = x ]; then > > echo starfield theme: Yes > > echo With DejaVuSans font from $DJVU_FONT_SOURCE > > diff --git a/util/grub-protect.c b/util/grub-protect.c > > new file mode 100644 > > index 000000000..7e2f80455 > > --- /dev/null > > +++ b/util/grub-protect.c > > @@ -0,0 +1,1396 @@ > > +/* > > + * GRUB -- GRand Unified Bootloader > > + * Copyright (C) 2022 Microsoft Corporation > > + * Copyright (C) 2023 SUSE LLC > > + * > > + * 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 <config.h> > > + > > +#include <errno.h> > > +#include <fcntl.h> > > +#include <libtasn1.h> > > +#include <stdio.h> > > +#include <string.h> > > +#include <unistd.h> > > + > > +#include <grub/crypto.h> > > +#include <grub/emu/getroot.h> > > +#include <grub/emu/hostdisk.h> > > +#include <grub/emu/misc.h> > > +#include <grub/tpm2/buffer.h> > > +#include <grub/tpm2/internal/args.h> > > +#include <grub/tpm2/mu.h> > > +#include <grub/tpm2/tcg2.h> > > +#include <grub/tpm2/tpm2.h> > > +#include <grub/util/misc.h> > > + > > +#pragma GCC diagnostic ignored "-Wmissing-prototypes" > > +#pragma GCC diagnostic ignored "-Wmissing-declarations" > > +#include <argp.h> > > +#pragma GCC diagnostic error "-Wmissing-prototypes" > > +#pragma GCC diagnostic error "-Wmissing-declarations" > > + > > +#include "progname.h" > > + > > +/* Unprintable option keys for argp */ > > +typedef enum grub_protect_opt > > +{ > > + /* General */ > > + GRUB_PROTECT_OPT_ACTION = 'a', > > + GRUB_PROTECT_OPT_PROTECTOR = 'p', > > + /* TPM2 */ > > + GRUB_PROTECT_OPT_TPM2_DEVICE = 0x100, > > + GRUB_PROTECT_OPT_TPM2_PCRS, > > + GRUB_PROTECT_OPT_TPM2_ASYMMETRIC, > > + GRUB_PROTECT_OPT_TPM2_BANK, > > + GRUB_PROTECT_OPT_TPM2_SRK, > > + GRUB_PROTECT_OPT_TPM2_KEYFILE, > > + GRUB_PROTECT_OPT_TPM2_OUTFILE, > > + GRUB_PROTECT_OPT_TPM2_EVICT, > > + GRUB_PROTECT_OPT_TPM2_TPM2KEY > > +} grub_protect_opt; > > + > > +/* Option flags to keep track of specified arguments */ > > +typedef enum grub_protect_arg > > +{ > > + /* General */ > > + GRUB_PROTECT_ARG_ACTION = 1 << 0, > > + GRUB_PROTECT_ARG_PROTECTOR = 1 << 1, > > + /* TPM2 */ > > + GRUB_PROTECT_ARG_TPM2_DEVICE = 1 << 2, > > + GRUB_PROTECT_ARG_TPM2_PCRS = 1 << 3, > > + GRUB_PROTECT_ARG_TPM2_ASYMMETRIC = 1 << 4, > > + GRUB_PROTECT_ARG_TPM2_BANK = 1 << 5, > > + GRUB_PROTECT_ARG_TPM2_SRK = 1 << 6, > > + GRUB_PROTECT_ARG_TPM2_KEYFILE = 1 << 7, > > + GRUB_PROTECT_ARG_TPM2_OUTFILE = 1 << 8, > > + GRUB_PROTECT_ARG_TPM2_EVICT = 1 << 9, > > + GRUB_PROTECT_ARG_TPM2_TPM2KEY = 1 << 10 > > +} grub_protect_arg_t; > > + > > +typedef enum grub_protect_protector > > +{ > > + GRUB_PROTECT_TYPE_ERROR, > > + GRUB_PROTECT_TYPE_TPM2 > > +} grub_protect_protector_t; > > + > > +typedef enum grub_protect_action > > +{ > > + GRUB_PROTECT_ACTION_ERROR, > > + GRUB_PROTECT_ACTION_ADD, > > + GRUB_PROTECT_ACTION_REMOVE > > +} grub_protect_action_t; > > + > > +struct grub_protect_args > > +{ > > + grub_protect_arg_t args; > > + grub_protect_action_t action; > > + grub_protect_protector_t protector; > > + > > + const char *tpm2_device; > > + grub_uint8_t tpm2_pcrs[TPM_MAX_PCRS]; > > + grub_uint8_t tpm2_pcr_count; > > + grub_srk_type_t srk_type; > > + TPM_ALG_ID tpm2_bank; > > + TPM_HANDLE tpm2_srk; > > + const char *tpm2_keyfile; > > + const char *tpm2_outfile; > > + int tpm2_evict; > > + int tpm2_tpm2key; > > +}; > > + > > +static struct argp_option grub_protect_options[] = > > + { > > + /* Top-level options */ > > + { > > + .name = "action", > > + .key = 'a', > > + .arg = "add|remove", > > + .flags = 0, > > + .doc = > > + N_("Add or remove a key protector to or from a key."), > > + .group = 0 > > + }, > > + { > > + .name = "protector", > > + .key = 'p', > > + .arg = "tpm2", > > + .flags = 0, > > + .doc = > > + N_("Key protector to use (only tpm2 is currently supported)."), > > + .group = 0 > > + }, > > + /* TPM2 key protector options */ > > + { > > + .name = "tpm2-device", > > + .key = GRUB_PROTECT_OPT_TPM2_DEVICE, > > + .arg = "FILE", > > + .flags = 0, > > + .doc = > > + N_("Path to the TPM2 device (default is /dev/tpm0)."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-pcrs", > > + .key = GRUB_PROTECT_OPT_TPM2_PCRS, > > + .arg = "0[,1]...", > > + .flags = 0, > > + .doc = > > + N_("Comma-separated list of PCRs used to authorize key release " > > + "(e.g., '7,11', default is 7."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-bank", > > + .key = GRUB_PROTECT_OPT_TPM2_BANK, > > + .arg = "ALG", > > + .flags = 0, > > + .doc = > > + N_("Bank of PCRs used to authorize key release: " > > + "SHA1, SHA256 (default), or SHA512."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-keyfile", > > + .key = GRUB_PROTECT_OPT_TPM2_KEYFILE, > > + .arg = "FILE", > > + .flags = 0, > > + .doc = > > + N_("Path to a file that contains the cleartext key to protect."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-outfile", > > + .key = GRUB_PROTECT_OPT_TPM2_OUTFILE, > > + .arg = "FILE", > > + .flags = 0, > > + .doc = > > + N_("Path to the file that will contain the key after sealing (must be " > > + "accessible to GRUB during boot)."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-srk", > > + .key = GRUB_PROTECT_OPT_TPM2_SRK, > > + .arg = "NUM", > > + .flags = 0, > > + .doc = > > + N_("The SRK handle if the SRK is to be made persistent."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-asymmetric", > > + .key = GRUB_PROTECT_OPT_TPM2_ASYMMETRIC, > > + .arg = "TYPE", > > + .flags = 0, > > + .doc = > > + N_("The type of SRK: RSA (RSA2048), RSA3072, RSA4096, " > > + "ECC (ECC_NIST_P256), ECC_NIST_P384, ECC_NIST_P521, " > > + "ECC_BN_P256, ECC_BN_P638, and ECC_SM2_P256. " > > + "(default is ECC_NIST_P256)"), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2-evict", > > + .key = GRUB_PROTECT_OPT_TPM2_EVICT, > > + .arg = NULL, > > + .flags = 0, > > + .doc = > > + N_("Evict a previously persisted SRK from the TPM, if any."), > > + .group = 0 > > + }, > > + { > > + .name = "tpm2key", > > + .key = GRUB_PROTECT_OPT_TPM2_TPM2KEY, > > + .arg = NULL, > > + .flags = 0, > > + .doc = > > + N_("Use TPM 2.0 Key File format instead of the raw format."), > > + .group = 0 > > + }, > > + /* End of list */ > > + { 0, 0, 0, 0, 0, 0 } > > + }; > > + > > +static int grub_protector_tpm2_fd = -1; > > + > > +static grub_err_t > > +grub_protect_read_file (const char *filepath, void **buffer, > > + size_t *buffer_size) > > +{ > > + grub_err_t err; > > + FILE *f; > > + long len; > > + void *buf; > > + > > + f = fopen (filepath, "rb"); > > + if (f == NULL) > > + return GRUB_ERR_FILE_NOT_FOUND; > > + > > + if (fseek (f, 0, SEEK_END)) > > + { > > + err = GRUB_ERR_FILE_READ_ERROR; > > + goto exit1; > > + } > > + > > + len = ftell (f); > > + if (len <= 0) > > + { > > + err = GRUB_ERR_FILE_READ_ERROR; > > + goto exit1; > > + } > > + > > + rewind (f); > > + > > + buf = grub_malloc (len); > > + if (buf == NULL) > > + { > > + err = GRUB_ERR_OUT_OF_MEMORY; > > + goto exit1; > > + } > > + > > + if (fread (buf, len, 1, f) != 1) > > + { > > + err = GRUB_ERR_FILE_READ_ERROR; > > + goto exit2; > > + } > > + > > + *buffer = buf; > > + *buffer_size = len; > > + > > + buf = NULL; > > + err = GRUB_ERR_NONE; > > + > > +exit2: > > + grub_free (buf); > > + > > +exit1: > > + fclose (f); > > + > > + return err; > > +} > > + > > +static grub_err_t > > +grub_protect_write_file (const char *filepath, void *buffer, size_t > > buffer_size) > > +{ > > + grub_err_t err; > > + FILE *f; > > + > > + f = fopen (filepath, "wb"); > > + if (f == NULL) > > + return GRUB_ERR_FILE_NOT_FOUND; > > + > > + if (fwrite (buffer, buffer_size, 1, f) != 1) > > + { > > + err = GRUB_ERR_WRITE_ERROR; > > + goto exit1; > > + } > > + > > + err = GRUB_ERR_NONE; > > + > > +exit1: > > + fclose (f); > > + > > + return err; > > +} > > + > > +grub_err_t > > +grub_tcg2_get_max_output_size (grub_size_t *size) > > +{ > > + if (size == NULL) > > + return GRUB_ERR_BAD_ARGUMENT; > > + > > + *size = GRUB_TPM2_BUFFER_CAPACITY; > > + > > + return GRUB_ERR_NONE; > > +} > > + > > +grub_err_t > > +grub_tcg2_submit_command (grub_size_t input_size, grub_uint8_t *input, > > + grub_size_t output_size, grub_uint8_t *output) > > +{ > > + static const grub_size_t header_size = sizeof (grub_uint16_t) + > > + (2 * sizeof(grub_uint32_t)); > > + > > + if (write (grub_protector_tpm2_fd, input, input_size) != input_size) > > + return GRUB_ERR_BAD_DEVICE; > > + > > + if (read (grub_protector_tpm2_fd, output, output_size) < header_size) > > + return GRUB_ERR_BAD_DEVICE; > > + > > + return GRUB_ERR_NONE; > > +} > > + > > +static grub_err_t > > +grub_protect_tpm2_open_device (const char *dev_node) > > +{ > > + if (grub_protector_tpm2_fd != -1) > > + return GRUB_ERR_NONE; > > + > > + grub_protector_tpm2_fd = open (dev_node, O_RDWR); > > + if (grub_protector_tpm2_fd == -1) > > + { > > + fprintf (stderr, _("Could not open TPM device (%s).\n"), strerror > > (errno)); > > + return GRUB_ERR_FILE_NOT_FOUND; > > + } > > + > > + return GRUB_ERR_NONE; > > +} > > + > > +static grub_err_t > > +grub_protect_tpm2_close_device (void) > > +{ > > + int err; > > + > > + if (grub_protector_tpm2_fd == -1) > > + return GRUB_ERR_NONE; > > + > > + err = close (grub_protector_tpm2_fd); > > + if (err != GRUB_ERR_NONE) > > + { > > + fprintf (stderr, _("Could not close TPM device (Error: %u).\n"), > > errno); > > + return GRUB_ERR_IO; > > + } > > + > > + grub_protector_tpm2_fd = -1; > > + return GRUB_ERR_NONE; > > +} > > + > > +static grub_err_t > > +grub_protect_tpm2_get_policy_digest (struct grub_protect_args *args, > > + TPM2B_DIGEST *digest) > > +{ > > + TPM_RC rc; > > + TPML_PCR_SELECTION pcr_sel = { > > + .count = 1, > > + .pcrSelections = { > > + { > > + .hash = args->tpm2_bank, > > + .sizeOfSelect = 3, > > + .pcrSelect = { 0 } > > + }, > > + } > > + }; > > + TPML_PCR_SELECTION pcr_sel_out = { 0 }; > > + TPML_DIGEST pcr_values = { 0 }; > > + grub_uint8_t *pcr_digest; > > + grub_size_t pcr_digest_len; > > + grub_uint8_t *pcr_concat; > > + grub_size_t pcr_concat_len; > > + grub_uint8_t *pcr_cursor; > > + const gcry_md_spec_t *hash_spec; > > + TPM2B_NONCE nonce = { 0 }; > > + TPM2B_ENCRYPTED_SECRET salt = { 0 }; > > + TPMT_SYM_DEF symmetric = { 0 }; > > + TPMI_SH_AUTH_SESSION session = 0; > > + TPM2B_DIGEST pcr_digest_in = { > > + .size = TPM_SHA256_DIGEST_SIZE, > > + .buffer = { 0 } > > + }; > > + TPM2B_DIGEST policy_digest = { 0 }; > > + grub_uint8_t i; > > + grub_err_t err; > > + > > + /* PCR Read */ > > + for (i = 0; i < args->tpm2_pcr_count; i++) > > + TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], > > args->tpm2_pcrs[i]); > > + > > + rc = TPM2_PCR_Read (NULL, &pcr_sel, NULL, &pcr_sel_out, &pcr_values, > > NULL); > > + if (rc != TPM_RC_SUCCESS) > > + { > > + fprintf (stderr, _("Failed to read PCRs (TPM2_PCR_Read: 0x%x).\n"), > > rc); > > + return GRUB_ERR_BAD_DEVICE; > > + } > > + > > + if ((pcr_sel_out.count != pcr_sel.count) || > > + (pcr_sel.pcrSelections[0].sizeOfSelect != > > + pcr_sel_out.pcrSelections[0].sizeOfSelect)) > > + { > > + fprintf (stderr, _("Could not read all the specified PCRs.\n")); > > + return GRUB_ERR_BAD_DEVICE; > > + } > > + > > + /* Compute PCR Digest */ > > + switch (args->tpm2_bank) > > + { > > + case TPM_ALG_SHA1: > > + pcr_digest_len = TPM_SHA1_DIGEST_SIZE; > > + hash_spec = GRUB_MD_SHA1; > > + break; > > + case TPM_ALG_SHA256: > > + pcr_digest_len = TPM_SHA256_DIGEST_SIZE; > > + hash_spec = GRUB_MD_SHA256; > > + break; > > + case TPM_ALG_SHA512: > > + pcr_digest_len = TPM_SHA512_DIGEST_SIZE; > > + hash_spec = GRUB_MD_SHA512; > > + break; > > + /* Although SHA384 can be parsed by grub_tpm2_protector_parse_bank(), > > + it's not supported by the built-in libgcrypt, and we won't be able > > to > > + calculate the PCR digest, so SHA384 is marked as unsupported. */ > > + default: > > + return GRUB_ERR_BAD_ARGUMENT; > > + } > > + > > + pcr_digest = grub_malloc (pcr_digest_len); > > + if (!pcr_digest) > > + { > > + fprintf (stderr, _("Failed to allocate PCR digest buffer.\n")); > > + return GRUB_ERR_OUT_OF_MEMORY; > > + } > > + > > + pcr_concat_len = pcr_digest_len * args->tpm2_pcr_count; > > + pcr_concat = grub_malloc (pcr_concat_len); > > + if (pcr_concat == NULL) > > + { > > + err = GRUB_ERR_OUT_OF_MEMORY; > > + fprintf (stderr, _("Failed to allocate PCR concatenation > > buffer.\n")); > > + goto exit1; > > + } > > + > > + pcr_cursor = pcr_concat; > > + for (i = 0; i < args->tpm2_pcr_count; i++) > > + { > > + if (pcr_values.digests[i].size != pcr_digest_len) > > + { > > + fprintf (stderr, > > + _("Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but > > got %u bytes.\n"), > > + pcr_digest_len, pcr_values.digests[i].size); > > + goto exit2; > > + } > > + > > + grub_memcpy (pcr_cursor, pcr_values.digests[i].buffer, > > pcr_digest_len); > > + pcr_cursor += pcr_digest_len; > > + } > > + > > + grub_crypto_hash (hash_spec, pcr_digest, pcr_concat, pcr_concat_len); > > + > > + /* Start Trial Session */ > > + nonce.size = TPM_SHA256_DIGEST_SIZE; > > + symmetric.algorithm = TPM_ALG_NULL; > > + > > + rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonce, &salt, > > + TPM_SE_TRIAL, &symmetric, TPM_ALG_SHA256, > > + &session, NULL, 0); > > + if (rc != TPM_RC_SUCCESS) > > + { > > + fprintf (stderr, > > + _("Failed to start trial policy session (TPM2_StartAuthSession: > > 0x%x).\n"), > > + rc); > > + err = GRUB_ERR_BAD_DEVICE; > > + goto exit2; > > + } > > + > > + /* PCR Policy */ > > + memcpy (pcr_digest_in.buffer, pcr_digest, TPM_SHA256_DIGEST_SIZE); > > + > > + rc = TPM2_PolicyPCR (session, NULL, &pcr_digest_in, &pcr_sel, NULL); > > + if (rc != TPM_RC_SUCCESS) > > + { > > + fprintf (stderr, _("Failed to submit PCR policy (TPM2_PolicyPCR: > > 0x%x).\n"), > > + rc); > > + err = GRUB_ERR_BAD_DEVICE; > > + goto exit3; > > + } > > + > > + /* Retrieve Policy Digest */ > > + rc = TPM2_PolicyGetDigest (session, NULL, &policy_digest, NULL); > > + if (rc != TPM_RC_SUCCESS) > > + { > > + fprintf (stderr, _("Failed to get policy digest > > (TPM2_PolicyGetDigest: 0x%x).\n"), > > + rc); > > + err = GRUB_ERR_BAD_DEVICE; > > + goto exit3; > > + } > > + > > + /* Epilogue */ > > + *digest = policy_digest; > > + err = GRUB_ERR_NONE; > > + > > +exit3: > > + TPM2_FlushContext (session); > > + > > +exit2: > > + grub_free (pcr_concat); > > + > > +exit1: > > + grub_free (pcr_digest); > > + > > + return err; > > +} > > + > > +static grub_err_t > > +grub_protect_tpm2_get_srk (struct grub_protect_args *args, TPM_HANDLE *srk) > > +{ > > + TPM_RC rc; > > + TPM2B_PUBLIC public; > > + TPMS_AUTH_COMMAND authCommand = { 0 }; > > + TPM2B_SENSITIVE_CREATE inSensitive = { 0 }; > > + TPM2B_PUBLIC inPublic = { 0 }; > > + TPM2B_DATA outsideInfo = { 0 }; > > + TPML_PCR_SELECTION creationPcr = { 0 }; > > + TPM2B_PUBLIC outPublic = { 0 }; > > + TPM2B_CREATION_DATA creationData = { 0 }; > > + TPM2B_DIGEST creationHash = { 0 }; > > + TPMT_TK_CREATION creationTicket = { 0 }; > > + TPM2B_NAME srkName = { 0 }; > > + TPM_HANDLE srkHandle; > > + > > + if (args->tpm2_srk != 0) > > + { > > + /* Find SRK */ > > + rc = TPM2_ReadPublic (args->tpm2_srk, NULL, &public); > > + if (rc == TPM_RC_SUCCESS) > > + { > > + printf (_("Read SRK from 0x%x\n"), args->tpm2_srk); > > + *srk = args->tpm2_srk; > > + return GRUB_ERR_NONE; > > + } > > + > > + /* The handle exists but its public area could not be read. */ > > + if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE) > > + { > > + fprintf (stderr, > > + _("Failed to retrieve SRK from 0x%x (TPM2_ReadPublic: > > 0x%x).\n"), > > + args->tpm2_srk, rc); > > + return GRUB_ERR_BAD_DEVICE; > > + } > > + } > > + > > + /* 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; > > Same comment here about pairing RSA3072 with AES-256 and SHA-512 maybe > (since SHA 384 isn't supported here). > It's sad that we don't have native SHA384 support due to the outdated libgcrypt :(
> Rest LGTM. > Thanks for reviewing the patch! Gary Lin _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel