[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 5/5] util/grub-protect: Add new tool
From: |
Glenn Washburn |
Subject: |
Re: [PATCH 5/5] util/grub-protect: Add new tool |
Date: |
Mon, 24 Jan 2022 23:45:55 -0600 |
On Mon, 24 Jan 2022 06:12:18 -0800
Hernan Gatta <hegatta@linux.microsoft.com> wrote:
> From: Hernan Gatta <hegatta@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 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 ensures the cryptomount command is included in GRUB's
> boot script and that it carries the requisite --protector (or -p) parameter.
I think you mean '-k' instead of '-p' here.
>
> Sample usage:
>
> $ dd if=/dev/urandom of=key count=32
> $ sudo cryptsetup luksAddKey /dev/sdb1 key --pbkdf=pbkdf2 --hash=sha512
>
> $ sudo grub-protect --action=add
> --protector=tpm2
> --tpm2-keyfile=key
> --tpm2-outfile=/boot/efi/boot/grub2/sealed_key
Why not have a syntax that is similar to whats given to cryptomount?
(eg. $ sudo grub-protect --action=add
--protector=tpm2:keyfile=/boot/efi/boot/grub2/sealed_key ) This would
allow you to re-use the parsing code from patch #3. Yes, its less
UNIXy, but I think could be more intuitive and cuts down on code size.
I'm not completely wedded to this idea either.
>
> Then, in the boot script (wrapped for display):
>
> cryptomount -u b20f95d0834842bc9197bd78b36732f8
> -p tpm2:keyfile=(hd0,gpt1)/boot/grub2/sealed_key
Also, -k here.
>
> where the UUID corresponds to /dev/sdb1.
>
> Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
> ---
> .gitignore | 1 +
> Makefile.util.def | 16 +
> configure.ac | 1 +
> util/grub-protect.c | 1344
> +++++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 1362 insertions(+)
> create mode 100644 util/grub-protect.c
>
> diff --git a/.gitignore b/.gitignore
> index f6a1bd0..852327d 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -167,6 +167,7 @@ widthspec.bin
> /grub-ofpathname.exe
> /grub-probe
> /grub-probe.exe
> +/grub-protect
> /grub-reboot
> /grub-render-label
> /grub-render-label.exe
> diff --git a/Makefile.util.def b/Makefile.util.def
> index 39b53b3..05f9f09 100644
> --- a/Makefile.util.def
> +++ b/Makefile.util.def
> @@ -52,6 +52,9 @@ library = {
> common = grub-core/partmap/msdos.c;
> common = grub-core/fs/proc.c;
> common = grub-core/fs/archelp.c;
> + common = grub-core/tpm2/buffer.c;
> + common = grub-core/tpm2/mu.c;
> + common = grub-core/tpm2/tpm2.c;
> };
>
> library = {
> @@ -207,6 +210,19 @@ program = {
> };
>
> program = {
> + name = grub-protect;
> + common = grub-core/osdep/init.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 = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR)
> $(LIBGEOM)';
> +};
> +
> +program = {
> name = grub-mkrelpath;
> mansection = 1;
>
> diff --git a/configure.ac b/configure.ac
> index 4f649ed..3a4dc5a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -71,6 +71,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])
> diff --git a/util/grub-protect.c b/util/grub-protect.c
> new file mode 100644
> index 0000000..4e4bbd7
> --- /dev/null
> +++ b/util/grub-protect.c
> @@ -0,0 +1,1344 @@
> +/*
> + * GRUB -- GRand Unified Bootloader
> + * Copyright (C) 2022 Microsoft Corporation
> + *
> + * 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 <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/mu.h>
> +#include <grub/tpm2/tcg2.h>
> +#include <grub/tpm2/tpm2.h>
> +#include <grub/util/misc.h>
> +
> +#include "progname.h"
> +
> +typedef enum grub_protect_arg
> +{
> + GRUB_PROTECT_ARG_ACTION = 1 << 0,
> + GRUB_PROTECT_ARG_PROTECTOR = 1 << 1,
> + 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_PERSIST = 1 << 9,
> + GRUB_PROTECT_ARG_TPM2_EVICT = 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;
> + TPM_ALG_ID tpm2_asymmetric;
> + TPM_ALG_ID tpm2_bank;
> + TPM_HANDLE tpm2_srk;
> + const char *tpm2_keyfile;
> + const char *tpm2_outfile;
> + int tpm2_persist;
> + int tpm2_evict;
> +};
> +
> +static int 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)
> + 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)
> + {
> + err = GRUB_ERR_FILE_READ_ERROR;
> + goto exit1;
> + }
> +
> + rewind (f);
> +
> + buf = grub_malloc (len);
> + if (!buf)
> + {
> + 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)
> + 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;
> +}
> +
> +static grub_err_t
> +grub_protect_get_grub_drive_for_file (const char *filepath, char **drive)
> +{
> + grub_err_t err = GRUB_ERR_IO;
> + char *disk;
> + char **devices;
> + char *grub_dev;
> + char *grub_path;
> + char *efi_drive;
> + char *partition;
> + char *grub_drive;
> + grub_device_t dev;
> + grub_size_t grub_drive_len;
> + int n;
> +
> + grub_path = grub_canonicalize_file_name (filepath);
> + if (!grub_path)
> + goto exit1;
> +
> + devices = grub_guess_root_devices (grub_path);
> + if (!devices || !devices[0])
> + goto exit2;
> +
> + disk = devices[0];
> +
> + grub_util_pull_device (disk);
> +
> + grub_dev = grub_util_get_grub_dev (disk);
> + if (!grub_dev)
> + goto exit3;
> +
> + dev = grub_device_open (grub_dev);
> + if (!dev)
> + goto exit4;
> +
> + efi_drive = grub_util_guess_efi_drive (disk);
> + if (!efi_drive)
> + goto exit5;
> +
> + partition = grub_partition_get_name (dev->disk->partition);
> + if (!partition)
> + goto exit6;
> +
> + grub_drive_len = grub_strlen (efi_drive) + grub_strlen (partition) + 3;
> + grub_drive = grub_malloc (grub_drive_len + 1);
> + if (!grub_drive)
> + goto exit7;
> +
> + n = grub_snprintf (grub_drive, grub_drive_len + 1, "(%s,%s)", efi_drive,
> + partition);
> + if (n != grub_drive_len)
> + goto exit8;
> +
> + *drive = grub_drive;
> + grub_drive = NULL;
> + err = GRUB_ERR_NONE;
> +
> +exit8:
> + grub_free (grub_drive);
> +
> +exit7:
> + grub_free (partition);
> +
> +exit6:
> + grub_free (efi_drive);
> +
> +exit5:
> + grub_device_close (dev);
> +
> +exit4:
> + grub_free (grub_dev);
> +
> +exit3:
> + grub_free (devices);
> +
> +exit2:
> + grub_free (grub_path);
> +
> +exit1:
> + return err;
> +}
> +
> +grub_err_t
> +grub_tcg2_get_max_output_size (grub_size_t *size)
> +{
> + if (!size)
> + 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 (tpm2_fd, input, input_size) != input_size)
> + return GRUB_ERR_BAD_DEVICE;
> +
> + if (read (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 (tpm2_fd != -1)
> + return GRUB_ERR_NONE;
> +
> + tpm2_fd = open (dev_node, O_RDWR);
> + if (tpm2_fd == -1)
> + {
> + fprintf (stderr, _("Could not open TPM device (Error: %u).\n"), errno);
> + return GRUB_ERR_FILE_NOT_FOUND;
> + }
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_close_device (void)
> +{
> + int err;
> +
> + if (tpm2_fd == -1)
> + return GRUB_ERR_NONE;
> +
> + err = close (tpm2_fd);
> + if (err)
> + {
> + fprintf (stderr, _("Could not close TPM device (Error: %u).\n"), errno);
> + return GRUB_ERR_IO;
> + }
> +
> + 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++)
> + pcr_sel
> + .pcrSelections[0]
> + .pcrSelect[TPM2_PCR_TO_SELECT(args->tpm2_pcrs[i])]
> + |= TPM2_PCR_TO_BIT(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 (TPM error: 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;
> + 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)
> + {
> + 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 %lu 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 (TPM error:
> 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 (TPM error: 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 (TPM error: 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;
> +
> + /* Find SRK */
> + rc = TPM2_ReadPublic (args->tpm2_srk, NULL, &public);
> + if (rc == TPM_RC_SUCCESS)
> + {
> + if (args->tpm2_persist)
> + fprintf (stderr,
> + _("Warning: --tpm2-persist was specified but the SRK
> already exists on the TPM. Continuing anyway...\n"));
> +
> + *srk = TPM2_SRK_HANDLE;
> + 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,
> + _("The SRK exists on the TPM but its public area cannot be
> read (TPM error: 0x%x).\n"),
> + rc);
> + return GRUB_ERR_BAD_DEVICE;
> + }
> +
> + /* Create SRK */
> + authCommand.sessionHandle = TPM_RS_PW;
> + inPublic.publicArea.type = args->tpm2_asymmetric;
> + 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->tpm2_asymmetric)
> + {
> + 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 = 2048;
> + 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 = TPM_ECC_NIST_P256;
> + inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
> + break;
> +
> + default:
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + rc = TPM2_CreatePrimary (TPM_RH_OWNER, &authCommand, &inSensitive,
> &inPublic,
> + &outsideInfo, &creationPcr, &srkHandle,
> &outPublic,
> + &creationData, &creationHash, &creationTicket,
> + &srkName, NULL);
> + if (rc != TPM_RC_SUCCESS)
> + {
> + fprintf (stderr, _("Failed to create SRK (TPM error: 0x%x).\n"), rc);
> + return GRUB_ERR_BAD_DEVICE;
> + }
> +
> + /* Persist SRK */
> + if (args->tpm2_persist)
> + {
> + rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, args->tpm2_srk,
> + &authCommand, NULL);
> + if (rc == TPM_RC_SUCCESS)
> + {
> + TPM2_FlushContext (srkHandle);
> + srkHandle = args->tpm2_srk;
> + }
> + else
> + fprintf (stderr,
> + _("Warning: Failed to persist SRK (TPM error: 0x%x\n).
> Continuing anyway...\n"),
> + rc);
> + }
> +
> + /* Epilogue */
> + *srk = srkHandle;
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_seal (TPM2B_DIGEST *policyDigest, TPM_HANDLE srk,
> + grub_uint8_t *clearText, grub_size_t clearTextLength,
> + TPM2_SEALED_KEY *sealed_key)
> +{
> + TPM_RC rc;
> + TPMS_AUTH_COMMAND authCommand = { 0 };
> + TPM2B_SENSITIVE_CREATE inSensitive = { 0 };
> + TPM2B_PUBLIC inPublic = { 0 };
> + TPM2B_DATA outsideInfo = { 0 };
> + TPML_PCR_SELECTION pcr_sel = { 0 };
> + TPM2B_PRIVATE outPrivate = { 0 };
> + TPM2B_PUBLIC outPublic = { 0 };
> +
> + /* Seal Data */
> + authCommand.sessionHandle = TPM_RS_PW;
> +
> + inSensitive.sensitive.data.size = clearTextLength;
> + memcpy(inSensitive.sensitive.data.buffer, clearText, clearTextLength);
> +
> + inPublic.publicArea.type = TPM_ALG_KEYEDHASH;
> + inPublic.publicArea.nameAlg = TPM_ALG_SHA256;
> + inPublic.publicArea.parameters.keyedHashDetail.scheme.scheme =
> TPM_ALG_NULL;
> + inPublic.publicArea.authPolicy = *policyDigest;
> +
> + rc = TPM2_Create (srk, &authCommand, &inSensitive, &inPublic, &outsideInfo,
> + &pcr_sel, &outPrivate, &outPublic, NULL, NULL, NULL,
> NULL);
> + if (rc != TPM_RC_SUCCESS)
> + {
> + fprintf (stderr, _("Failed to seal key (TPM error: 0x%x).\n"), rc);
> + return GRUB_ERR_BAD_DEVICE;
> + }
> +
> + /* Epilogue */
> + sealed_key->public = outPublic;
> + sealed_key->private = outPrivate;
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_export_sealed_key (const char *filepath,
> + TPM2_SEALED_KEY *sealed_key)
> +{
> + grub_err_t err;
> + struct grub_tpm2_buffer buf;
> +
> + grub_tpm2_buffer_init (&buf);
> + grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&buf, &sealed_key->public);
> + grub_tpm2_mu_TPM2B_Marshal (&buf, sealed_key->private.size,
> + sealed_key->private.buffer);
> + if (buf.error)
> + return GRUB_ERR_BAD_ARGUMENT;
> +
> + err = grub_protect_write_file (filepath, buf.data, buf.size);
> + if (err)
> + fprintf (stderr, _("Could not write sealed key file (Error: %u).\n"),
> + errno);
> +
> + return err;
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_add (struct grub_protect_args *args)
> +{
> + grub_err_t err;
> + grub_uint8_t *key;
> + grub_size_t key_size;
> + TPM_HANDLE srk;
> + TPM2B_DIGEST policy_digest;
> + TPM2_SEALED_KEY sealed_key;
> + char *grub_drive = NULL;
> +
> + grub_protect_get_grub_drive_for_file (args->tpm2_outfile, &grub_drive);
> +
> + err = grub_protect_tpm2_open_device (args->tpm2_device);
> + if (err)
> + return err;
> +
> + err = grub_protect_read_file (args->tpm2_keyfile, (void **)&key,
> &key_size);
> + if (err)
> + goto exit1;
> +
> + if (key_size > TPM_MAX_SYM_DATA)
> + {
> + fprintf (stderr,
> + _("Input key is too long, maximum allowed size is %u bytes.\n"),
> + TPM_MAX_SYM_DATA);
> + return GRUB_ERR_OUT_OF_RANGE;
> + }
> +
> + err = grub_protect_tpm2_get_srk (args, &srk);
> + if (err)
> + goto exit2;
> +
> + err = grub_protect_tpm2_get_policy_digest (args, &policy_digest);
> + if (err)
> + goto exit3;
> +
> + err = grub_protect_tpm2_seal (&policy_digest, srk, key, key_size,
> + &sealed_key);
> + if (err)
> + goto exit3;
> +
> + err = grub_protect_tpm2_export_sealed_key (args->tpm2_outfile,
> &sealed_key);
> + if (err)
> + goto exit3;
> +
> + if (grub_drive)
> + {
> + printf (_("GRUB drive for the sealed key file: %s\n"), grub_drive);
> + grub_free (grub_drive);
> + }
> + else
> + {
> + fprintf (stderr,
> + _("Warning: Could not determine GRUB drive for sealed key
> file.\n"));
> + err = GRUB_ERR_NONE;
> + }
> +
> +exit3:
> + TPM2_FlushContext (srk);
> +
> +exit2:
> + grub_free (key);
> +
> +exit1:
> + grub_protect_tpm2_close_device ();
> +
> + return err;
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_remove (struct grub_protect_args *args)
> +{
> + TPM_RC rc;
> + TPM2B_PUBLIC public;
> + TPMS_AUTH_COMMAND authCommand = { 0 };
> + grub_err_t err;
> +
> + if (!args->tpm2_evict)
> + {
> + printf (_("--tpm2-evict not specified, nothing to do.\n"));
> + return GRUB_ERR_NONE;
> + }
> +
> + err = grub_protect_tpm2_open_device (args->tpm2_device);
> + if (err)
> + return err;
> +
> + /* Find SRK */
> + rc = TPM2_ReadPublic (args->tpm2_srk, NULL, &public);
> + if (rc != TPM_RC_SUCCESS)
> + {
> + fprintf (stderr, _("SRK with handle 0x%x not found.\n"),
> args->tpm2_srk);
> + err = GRUB_ERR_BAD_ARGUMENT;
> + goto exit1;
> + }
> +
> + /* Evict SRK */
> + authCommand.sessionHandle = TPM_RS_PW;
> +
> + rc = TPM2_EvictControl (TPM_RH_OWNER, args->tpm2_srk, args->tpm2_srk,
> + &authCommand, NULL);
> + if (rc != TPM_RC_SUCCESS)
> + {
> + fprintf (stderr,
> + _("Failed to evict SRK with handle 0x%x (TPM Error:
> 0x%x).\n"),
> + args->tpm2_srk, rc);
> + err = GRUB_ERR_BAD_DEVICE;
> + goto exit2;
> + }
> +
> + err = GRUB_ERR_NONE;
> +
> +exit2:
> + TPM2_FlushContext (args->tpm2_srk);
> +
> +exit1:
> + grub_protect_tpm2_close_device ();
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_run (struct grub_protect_args *args)
> +{
> + switch (args->action)
> + {
> + case GRUB_PROTECT_ACTION_ADD:
> + return grub_protect_tpm2_add (args);
> +
> + case GRUB_PROTECT_ACTION_REMOVE:
> + return grub_protect_tpm2_remove (args);
> +
> + default:
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +}
> +
> +static grub_err_t
> +grub_protect_tpm2_args_verify (struct grub_protect_args *args)
> +{
I'm wondering if it wouldn't be a good idea to merge this function with
grub_tpm2_protector_check_args from patch #3. This is probably only
manageable if the protector argument looks like the one from grub as
well, so they can share error messages.
> + switch (args->action)
> + {
> + case GRUB_PROTECT_ACTION_ADD:
> + if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT)
> + {
> + fprintf (stderr,
> + _("--tpm2-evict is invalid when --action is 'add'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!args->tpm2_keyfile)
> + {
> + fprintf (stderr, _("--tpm2-keyfile must be specified.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!args->tpm2_outfile)
> + {
> + fprintf (stderr, _("--tpm2-outfile must be specified.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!args->tpm2_device)
> + args->tpm2_device = "/dev/tpm0";
Seems like this...
> +
> + if (!args->tpm2_pcr_count)
> + {
> + args->tpm2_pcrs[0] = 7;
> + args->tpm2_pcr_count = 1;
> + }
> +
> + if (!args->tpm2_srk)
> + args->tpm2_srk = TPM2_SRK_HANDLE;
and maybe this, can be done outside the switch since they are common to
both cases.
> +
> + if (!args->tpm2_asymmetric)
> + args->tpm2_asymmetric = TPM_ALG_RSA;
> +
> + if (!args->tpm2_bank)
> + args->tpm2_bank = TPM_ALG_SHA256;
> +
> + break;
> +
> + case GRUB_PROTECT_ACTION_REMOVE:
> + if (args->args & GRUB_PROTECT_ARG_TPM2_ASYMMETRIC)
> + {
> + fprintf (stderr,
> + _("--tpm2-asymmetric is invalid when --action is
> 'remove'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (args->args & GRUB_PROTECT_ARG_TPM2_BANK)
> + {
> + fprintf (stderr,
> + _("--tpm2-bank is invalid when --action is 'remove'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (args->args & GRUB_PROTECT_ARG_TPM2_KEYFILE)
> + {
> + fprintf (stderr,
> + _("--tpm2-keyfile is invalid when --action is
> 'remove'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (args->args & GRUB_PROTECT_ARG_TPM2_OUTFILE)
> + {
> + fprintf (stderr,
> + _("--tpm2-outfile is invalid when --action is
> 'remove'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (args->args & GRUB_PROTECT_ARG_TPM2_PCRS)
> + {
> + fprintf (stderr,
> + _("--tpm2-pcrs is invalid when --action is 'remove'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST)
> + {
> + fprintf (stderr,
> + _("--tpm2-persist is invalid when --action is
> 'remove'.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!args->tpm2_device)
> + args->tpm2_device = "/dev/tpm0";
> +
> + if (!args->tpm2_srk)
> + args->tpm2_srk = TPM2_SRK_HANDLE;
> +
> + break;
> +
> + default:
> + fprintf (stderr,
> + _("The TPM2 key protector only supports the following
> actions: add, remove.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protector_args_kvp_parse (char *kvp, const char **key, char **value)
> +{
> + char divider;
> + char *separator;
> + grub_size_t len;
> +
> + if (!kvp)
> + return GRUB_ERR_BAD_ARGUMENT;
> +
> + len = grub_strlen (kvp);
> + if (!len || len < 2)
> + return GRUB_ERR_BAD_ARGUMENT;
> +
> + if (kvp[0] == '-' && kvp[1] != '-')
> + divider = ' ';
> + else if (kvp[0] == '-' && kvp[1] == '-')
> + divider = '=';
> + else
> + return GRUB_ERR_BAD_ARGUMENT;
> +
> + separator = grub_strchr (kvp, divider);
> + if (!separator)
> + goto exit;
> +
> + *separator = '\0';
> + separator += 1;
> +
> + if (separator - kvp >= len)
> + {
> + separator = NULL;
> + goto exit;
> + }
> +
> +exit:
> + *key = kvp;
> + *value = separator;
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_args_parse (int argc, char *argv[],
> + struct grub_protect_args *args)
> +{
> + grub_err_t err;
> + char *current_arg;
> + const char *key;
> + char *value;
> + int i;
> +
> + for (i = 1; i < argc; i++)
> + {
> + current_arg = argv[i];
> +
> + err = grub_protector_args_kvp_parse (current_arg, &key, &value);
> + if (err)
> + return err;
> +
> + if (grub_strcmp (key, "--action") == 0 ||
> + grub_strcmp (key, "-a") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_ACTION)
> + {
> + fprintf (stderr,
> + _("Argument %s was already specified.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (grub_strcmp (value, "add") == 0)
> + args->action = GRUB_PROTECT_ACTION_ADD;
> + else if (grub_strcmp (value, "remove") == 0)
> + args->action = GRUB_PROTECT_ACTION_REMOVE;
> + else
> + {
> + fprintf (stderr, _("'%s' is not a valid action.\n"), value);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->args |= GRUB_PROTECT_ARG_ACTION;
> + }
> + else if (grub_strcmp (key, "--protector") == 0 ||
> + grub_strcmp (key, "-p") == 0)
This might be confusing because its -p here but -k to cryptomount.
> + {
> + if (args->args & GRUB_PROTECT_ARG_PROTECTOR)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (grub_strcmp (value, "tpm2") == 0)
> + args->protector = GRUB_PROTECT_TYPE_TPM2;
> + else
> + {
> + fprintf (stderr, _("'%s' is not a valid protector.\n"), value);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->args |= GRUB_PROTECT_ARG_PROTECTOR;
> + }
> + else if (grub_strcmp (key, "--tpm2-device") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_DEVICE)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->tpm2_device = value;
> + args->args |= GRUB_PROTECT_ARG_TPM2_DEVICE;
> + }
> + else if (grub_strcmp (key, "--tpm2-pcrs") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_PCRS)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + grub_size_t len = grub_strlen (value);
> + grub_size_t dist;
> +
> + long pcr;
> + char *next_pcr;
> + char *current_pcr = value;
> + grub_uint8_t pcr_u8;
> + grub_uint8_t j;
> + grub_uint8_t k;
> +
> + for (j = 0;; j++)
> + {
> + next_pcr = grub_strchr (current_pcr, ',');
> + if (next_pcr)
> + *next_pcr = '\0';
> +
> + grub_errno = GRUB_ERR_NONE;
> + pcr = grub_strtoul (current_pcr, NULL, 0);
> + if (grub_errno != GRUB_ERR_NONE)
> + {
> + fprintf (stderr, _("'%s' is not a valid PCR number.\n"),
> + current_pcr);
> + return grub_errno;
> + }
> +
> + if (pcr > TPM_MAX_PCRS)
> + {
> + fprintf (stderr,
> + _("%lu larger than the maximum number of
> PCRs.\n"),
> + pcr);
> + return GRUB_ERR_OUT_OF_RANGE;
> + }
> +
> + pcr_u8 = (grub_uint8_t)pcr;
> +
> + for (k = 0; k < args->tpm2_pcr_count; k++)
> + {
> + if (args->tpm2_pcrs[k] == pcr_u8)
> + {
> + fprintf (stderr, _("PCR %u was already specified.\n"),
> + pcr_u8);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> + }
> +
> + args->tpm2_pcrs[j] = pcr_u8;
> + args->tpm2_pcr_count++;
> +
> + if (!next_pcr)
> + break;
> +
> + current_pcr = next_pcr + 1;
> +
> + dist = (current_pcr - value);
> + if (dist >= len)
> + break;
> + }
> +
> + args->args |= GRUB_PROTECT_ARG_TPM2_PCRS;
> + }
> + else if (grub_strcmp (key, "--tpm2-srk") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_SRK)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + long srk;
> +
> + grub_errno = GRUB_ERR_NONE;
> + srk = grub_strtoul (value, NULL, 0);
> + if (grub_errno != GRUB_ERR_NONE)
> + {
> + fprintf (stderr, _("'%s' is not a valid SRK handle.\n"),
> value);
> + return grub_errno;
> + }
> +
> + if (srk > GRUB_UINT_MAX)
> + {
> + fprintf (stderr,
> + _("%lu is too large to be a valid SRK handle.\n"),
> srk);
> + return GRUB_ERR_OUT_OF_RANGE;
> + }
> +
> + args->tpm2_srk = (TPM_HANDLE)srk;
> + args->args |= GRUB_PROTECT_ARG_TPM2_SRK;
> + }
> + else if (grub_strcmp (key, "--tpm2-asymmetric") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_ASYMMETRIC)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (grub_strcasecmp (value, "ECC") == 0)
> + args->tpm2_asymmetric = TPM_ALG_ECC;
> + else if (grub_strcasecmp (value, "RSA") == 0)
> + args->tpm2_asymmetric = TPM_ALG_RSA;
> + else
> + {
> + fprintf (stderr, _("'%s' is not a valid asymmetric
> algorithm.\n"),
> + value);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->args |= GRUB_PROTECT_ARG_TPM2_ASYMMETRIC;
> + }
> + else if (grub_strcmp (key, "--tpm2-bank") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_BANK)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (grub_strcasecmp (value, "SHA1") == 0)
> + args->tpm2_bank = TPM_ALG_SHA1;
> + else if (grub_strcasecmp (value, "SHA256") == 0)
> + args->tpm2_bank = TPM_ALG_SHA256;
> + else
> + {
> + fprintf (stderr, _("'%s' is not a valid PCR bank.\n"), value);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->args |= GRUB_PROTECT_ARG_TPM2_BANK;
> + }
> + else if (grub_strcmp (key, "--tpm2-keyfile") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_KEYFILE)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->tpm2_keyfile = value;
> + args->args |= GRUB_PROTECT_ARG_TPM2_KEYFILE;
> + }
> + else if (grub_strcmp (key, "--tpm2-outfile") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_OUTFILE)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (!value)
> + {
> + fprintf (stderr, _("Argument %s requires a value.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->tpm2_outfile = value;
> + args->args |= GRUB_PROTECT_ARG_TPM2_OUTFILE;
> + }
> + else if (grub_strcmp (key, "--tpm2-persist") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (value)
> + {
> + fprintf (stderr, _("Argument %s does not accept a value.\n"),
> + key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->tpm2_persist = 1;
> + args->args |= GRUB_PROTECT_ARG_TPM2_PERSIST;
> + }
> + else if (grub_strcmp (key, "--tpm2-evict") == 0)
> + {
> + if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT)
> + {
> + fprintf (stderr, _("Argument %s was already specified.\n"),
> key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + if (value)
> + {
> + fprintf (stderr, _("Argument %s does not accept a value.\n"),
> + key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + args->tpm2_evict = 1;
> + args->args |= GRUB_PROTECT_ARG_TPM2_EVICT;
> + }
> + else
> + {
> + fprintf (stderr, _("'%s' is not a valid argument.\n"), key);
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> + }
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_args_verify (struct grub_protect_args *args)
> +{
> + if (args->action == GRUB_PROTECT_ACTION_ERROR)
> + {
> + fprintf (stderr, "--action is mandatory.\n");
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + /* At the moment, the only configurable key protector is the TPM2 one, so
> it
> + * is the only keu protector supported by this tool. */
> + if (args->protector != GRUB_PROTECT_TYPE_TPM2)
> + {
> + fprintf (stderr,
> + _("--protector is mandatory and only 'tpm2' is currently
> supported.\n"));
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + switch (args->protector)
> + {
> + case GRUB_PROTECT_TYPE_TPM2:
> + return grub_protect_tpm2_args_verify (args);
> + default:
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +
> + return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_protect_dispatch (struct grub_protect_args *args)
> +{
> + switch (args->protector)
> + {
> + case GRUB_PROTECT_TYPE_TPM2:
> + return grub_protect_tpm2_run (args);
> + default:
> + return GRUB_ERR_BAD_ARGUMENT;
> + }
> +}
> +
> +static void
> +grub_protect_init (int *argc, char **argv[])
> +{
> + grub_util_host_init (argc, argv);
> +
> + grub_util_biosdisk_init (NULL);
> +
> + grub_init_all ();
> + grub_gcry_init_all ();
> +
> + grub_lvm_fini ();
> + grub_mdraid09_fini ();
> + grub_mdraid1x_fini ();
> + grub_diskfilter_fini ();
> + grub_diskfilter_init ();
> + grub_mdraid09_init ();
> + grub_mdraid1x_init ();
> + grub_lvm_init ();
> +}
> +
> +static void
> +grub_protect_fini (void)
> +{
> + grub_gcry_fini_all ();
> + grub_fini_all ();
> + grub_util_biosdisk_fini ();
> +}
> +
> +int
> +main (int argc, char *argv[])
> +{
> + grub_err_t err;
> + struct grub_protect_args args = { 0 };
> +
> + grub_protect_init (&argc, &argv);
> +
> + err = grub_protect_args_parse (argc, argv, &args);
> + if (err)
> + goto exit;
> +
> + err = grub_protect_args_verify (&args);
> + if (err)
> + goto exit;
> +
> + err = grub_protect_dispatch (&args);
> + if (err)
> + goto exit;
> +
> +exit:
> + grub_protect_fini ();
> +
> + return err;
> +}
It would be nice to take arguments --help and -h and spit out something
useful.
Glenn
[PATCH 2/5] tpm2: Add TPM Software Stack (TSS), Hernan Gatta, 2022/01/24
Re: [PATCH 0/5] Automatic TPM Disk Unlock, Didier Spaier, 2022/01/24
Re: [PATCH 0/5] Automatic TPM Disk Unlock, Glenn Washburn, 2022/01/25