[PATCH] efi: make sure EFI disk controllers are connected when, discovering devices

2022-02-01 Thread Renaud Métrich
When efi.quickboot is enabled on VMWare (which is the default for 
hardware release 16 and later), it may happen that not all EFI devices 
are connected.


Due to this, browsing the devices in make_devices() just fails to find 
devices, in particular partitions for a given disk.
This typically happens when network booting, then trying to chainload to 
local disk (this is used in deployment tools such as Red Hat Satellite).


This patch makes sure all controllers are connected before enumerating 
the disks.


It blindly calls the EFI ConnectController function with recursive 
option and just ignores the result, which is 0 (EFI_SUCCESS) or 14 
(EFI_NOT_FOUND) when the handle is not a controller.


Example of "grub.cfg" file used to chainload when system boots over the 
network:


~~~

menuentry 'Chainload Grub2 EFI from ESP' --id local {

  unset root

  search --file --no-floppy --efidisk-only --set=root /EFI/BOOT/BOOTX64.EFI

  if [ -f ($root)/EFI/BOOT/grubx64.efi ]; then

    chainloader ($root)/EFI/BOOT/grubx64.efi

  elif [ -f ($root)/EFI/redhat/shimx64.efi ]; then

    chainloader ($root)/EFI/redhat/shimx64.efi

  elif [ -f ($root)/EFI/redhat/grubx64.efi ]; then

    chainloader ($root)/EFI/redhat/grubx64.efi

  fi

}

~~~

This patch has been tested on QEMU/KVM systems (for non regression) and 
VMWare VMs (at hardware level 6.7 and 7.0u2, with and without quickboot 
for functionality testing).



From eadff21ce781430ed699e7279871a71534257502 Mon Sep 17 00:00:00 2001
From: Fedora Ninjas 
Date: Mon, 31 Jan 2022 15:21:41 +0100
Subject: [PATCH] efi: make sure EFI disk controllers are connected when
 discovering devices
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When efi.quickboot is enabled on VMWare (which is the default for
hardware release 16 and later), it may happen that not all EFI devices
are connected. Due to this, browsing the devices in make_devices() just
fails to find devices, in particular partitions for a given disk.
This typically happens when network booting, then trying to chainload to
local disk (this is used in deployment tools such as Red Hat Satellite).

This patch makes sure all controllers are connected before enumerating
the disks. It blindly calls the EFI ConnectController function with
recursive option and just ignores the result, which is 0 (EFI_SUCCESS)
or 14 (EFI_NOT_FOUND) when the handle is not a controller.

Signed-off-by: Renaud Métrich 

diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index f077b5f55..0b16c3868 100644
--- a/grub-core/disk/efi/efidisk.c
+++ b/grub-core/disk/efi/efidisk.c
@@ -387,6 +387,16 @@ static void
 enumerate_disks (void)
 {
   struct grub_efidisk_data *devices;
+  unsigned i;
+  grub_efi_handle_t *handles;
+  grub_efi_uintn_t num_handles;
+
+  /* Prior to enumerating, make sure all EFI devices are connected */
+
+  handles = grub_efi_locate_handle (GRUB_EFI_ALL_HANDLES,
+NULL, NULL, &num_handles);
+  for (i = 0; i < num_handles; i++)
+(void) grub_efi_connect_controller(handles[i], NULL, NULL, 1);
 
   devices = make_devices ();
   if (! devices)
diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c
index 18858c327..bdfff3dd0 100644
--- a/grub-core/kern/efi/efi.c
+++ b/grub-core/kern/efi/efi.c
@@ -95,6 +95,19 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
   return buffer;
 }
 
+grub_efi_status_t
+grub_efi_connect_controller (grub_efi_handle_t controller_handle,
+			 grub_efi_handle_t *driver_image_handle,
+			 grub_efi_device_path_protocol_t *remaining_device_path,
+			 grub_efi_boolean_t recursive)
+{
+  grub_efi_boot_services_t *b;
+
+  b = grub_efi_system_table->boot_services;
+  return efi_call_4 (b->connect_controller, controller_handle,
+		 driver_image_handle, remaining_device_path, recursive);
+}
+
 void *
 grub_efi_open_protocol (grub_efi_handle_t handle,
 			grub_efi_guid_t *protocol,
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index fc723962d..62dbd9788 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -32,6 +32,11 @@ EXPORT_FUNC(grub_efi_locate_handle) (grub_efi_locate_search_type_t search_type,
  grub_efi_guid_t *protocol,
  void *search_key,
  grub_efi_uintn_t *num_handles);
+grub_efi_status_t
+EXPORT_FUNC(grub_efi_connect_controller) (grub_efi_handle_t controller_handle,
+	  grub_efi_handle_t *driver_image_handle,
+	  grub_efi_device_path_protocol_t *remaining_device_path,
+	  grub_efi_boolean_t recursive);
 void *EXPORT_FUNC(grub_efi_open_protocol) (grub_efi_handle_t handle,
 	   grub_efi_guid_t *protocol,
 	   grub_efi_uint32_t attributes);
-- 
2.34.1



OpenPGP_signature
Description: OpenPGP digital signature
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH] search: new --efidisk-only option on EFI systems

2022-02-01 Thread Renaud Métrich
When using 'search' on EFI systems, we sometimes want to exclude devices 
that are not EFI disks (e.g. md, lvm).
This is typically used when wanting to chainload when having a software 
raid (md) for EFI partition:


with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar 
to 'md/boot_efi' which cannot be used for chainloading since there is no 
effective EFI device behind.


Example of "grub.cfg" file used to chainload when system boots over the 
network:


~~~

menuentry 'Chainload Grub2 EFI from ESP' --id local {

  unset root

  search --file --no-floppy --efidisk-only --set=root /EFI/BOOT/BOOTX64.EFI

  if [ -f ($root)/EFI/BOOT/grubx64.efi ]; then

    chainloader ($root)/EFI/BOOT/grubx64.efi

  elif [ -f ($root)/EFI/redhat/shimx64.efi ]; then

    chainloader ($root)/EFI/redhat/shimx64.efi

  elif [ -f ($root)/EFI/redhat/grubx64.efi ]; then

    chainloader ($root)/EFI/redhat/grubx64.efi

  fi

}

~~~


This patch has been tested on QEMU/KVM systems and VMWare VMs (at 
hardware level 6.7 and 7.0u2).


Related Red Hat BZ (public): 
https://bugzilla.redhat.com/show_bug.cgi?id=2048904


From 46a869395e08fd2df4f722483b8db0f7da62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= 
Date: Tue, 1 Feb 2022 07:17:24 +0100
Subject: [PATCH] search: new --efidisk-only option on EFI systems
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When using 'search' on EFI systems, we sometimes want to exclude devices
that are not EFI disks (e.g. md, lvm).
This is typically used when wanting to chainload when having a software
raid (md) for EFI partition:
with no option, 'search --file /EFI/redhat/shimx64.efi' sets root envvar
to 'md/boot_efi' which cannot be used for chainloading since there is no
effective EFI device behind.

Signed-off-by: Renaud Métrich 

diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
index ed090b3af..5e1e88643 100644
--- a/grub-core/commands/search.c
+++ b/grub-core/commands/search.c
@@ -48,6 +48,9 @@ struct search_ctx
   const char *key;
   const char *var;
   int no_floppy;
+#ifdef GRUB_MACHINE_EFI
+  int efidisk_only;
+#endif
   char **hints;
   unsigned nhints;
   int count;
@@ -64,7 +67,28 @@ iterate_device (const char *name, void *data)
   /* Skip floppy drives when requested.  */
   if (ctx->no_floppy &&
   name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
-return 1;
+return 0;
+
+#ifdef GRUB_MACHINE_EFI
+  /* Limit to EFI disks when requested.  */
+  if (ctx->efidisk_only)
+{
+  grub_device_t dev;
+  dev = grub_device_open (name);
+  if (! dev)
+	{
+	  grub_errno = GRUB_ERR_NONE;
+	  return 0;
+	}
+  if (! dev->disk || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID)
+	{
+	  grub_device_close (dev);
+	  grub_errno = GRUB_ERR_NONE;
+	  return 0;
+	}
+  grub_device_close (dev);
+}
+#endif
 
 #ifdef DO_SEARCH_FS_UUID
 #define compare_fn grub_strcasecmp
@@ -262,12 +286,18 @@ try (struct search_ctx *ctx)
 
 void
 FUNC_NAME (const char *key, const char *var, int no_floppy,
+#ifdef GRUB_MACHINE_EFI
+	   int efidisk_only,
+#endif
 	   char **hints, unsigned nhints)
 {
   struct search_ctx ctx = {
 .key = key,
 .var = var,
 .no_floppy = no_floppy,
+#ifdef GRUB_MACHINE_EFI
+.efidisk_only = efidisk_only,
+#endif
 .hints = hints,
 .nhints = nhints,
 .count = 0,
@@ -303,8 +333,12 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
   if (argc == 0)
 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
 
-  FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
-	 argc > 2 ? argc - 2 : 0);
+  FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0,
+#ifdef GRUB_MACHINE_EFI
+	 /* efidisk_only */
+	 0,
+#endif
+	 (args + 2), argc > 2 ? argc - 2 : 0);
 
   return grub_errno;
 }
diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c
index 47fc8eb99..aed75b236 100644
--- a/grub-core/commands/search_wrap.c
+++ b/grub-core/commands/search_wrap.c
@@ -40,6 +40,9 @@ static const struct grub_arg_option options[] =
  N_("Set a variable to the first device found."), N_("VARNAME"),
  ARG_TYPE_STRING},
 {"no-floppy",	'n', 0, N_("Do not probe any floppy drive."), 0, 0},
+#ifdef GRUB_MACHINE_EFI
+{"efidisk-only",	0, 0, N_("Only probe EFI disks."), 0, 0},
+#endif
 {"hint",	'h', GRUB_ARG_OPTION_REPEATABLE,
  N_("First try the device HINT. If HINT ends in comma, "
 	"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
@@ -73,6 +76,9 @@ enum options
 SEARCH_FS_UUID,
 SEARCH_SET,
 SEARCH_NO_FLOPPY,
+#ifdef GRUB_MACHINE_EFI
+SEARCH_EFIDISK_ONLY,
+#endif
 SEARCH_HINT,
 SEARCH_HINT_IEEE1275,
 SEARCH_HINT_BIOS,
@@ -182,12 +188,21 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
 
   if (state[SEARCH_LABEL].set)
 grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, 
+

[PATCH v2 3/5] protectors: Add TPM2 Key Protector

2022-02-01 Thread Hernan Gatta
The TPM2 key protector is a module that enables the automatic retrieval of a
fully-encrypted disk's unlocking key from a TPM 2.0.

The theory of operation is such that the module accepts various arguments, most
of which are optional and therefore possess reasonable defaults. One of these
arguments is the keyfile parameter, which is mandatory.

The value of this parameter must be a path to a sealed key file (e.g.,
(hd0,gpt1)/boot/grub2/sealed_key). This sealed key file is created via the
grub-protect tool. The tool utilizes the TPM's sealing functionality to seal
(i.e., encrypt) an unlocking key using a Storage Root Key (SRK) to the values of
various Platform Configuration Registers (PCRs). These PCRs reflect the state of
the system as it boots. If the values are as expected, the system may be
considered trustworthy, at which point the TPM allows for a caller to utilize
the private component of the SRK to unseal (i.e., decrypt) the sealed key file.
The caller, in this case, is this key protector.

The TPM2 key protector registers two commands:

- tpm2_key_protector_init: Initializes the state of the TPM2 key protector for
   later usage, clearing any previous state, too, if
   any.

- tpm2_key_protector_clear: Clears any state set by tpm2_key_protector_init.

The way this is expected to be used requires the user to, either interactively
or, normally, via a boot script, initialize (i.e., configure) the key protector
and then specify that it be used by the cryptomount command (modifications to
this command are in a different patch).

For instance:

tpm2_key_protector_init --keyfile=KEYFILE1
cryptomount DISK1 -k tpm2

tpm2_key_protector_init --keyfile=KEYFILE2 --pcrs=7,11
cryptomount DISK2 -k tpm2

If a user does not initialize the key protector and attempts to use it anyway,
the protector returns an error.

Signed-off-by: Hernan Gatta 
---
 grub-core/Makefile.core.def   |  10 +
 grub-core/tpm2/args.c | 129 +++
 grub-core/tpm2/module.c   | 710 ++
 include/grub/tpm2/internal/args.h |  39 +++
 4 files changed, 888 insertions(+)
 create mode 100644 grub-core/tpm2/args.c
 create mode 100644 grub-core/tpm2/module.c
 create mode 100644 include/grub/tpm2/internal/args.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index e4ae78b..78d09d9 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2498,6 +2498,16 @@ module = {
 };
 
 module = {
+  name = tpm2;
+  common = tpm2/args.c;
+  common = tpm2/buffer.c;
+  common = tpm2/module.c;
+  common = tpm2/mu.c;
+  common = tpm2/tpm2.c;
+  efi = tpm2/tcg2.c;
+};
+
+module = {
   name = tr;
   common = commands/tr.c;
 };
diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c
new file mode 100644
index 000..90c7cd8
--- /dev/null
+++ b/grub-core/tpm2/args.c
@@ -0,0 +1,129 @@
+/*
+ *  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 .
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+grub_err_t
+grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs,
+grub_uint8_t *pcr_count)
+{
+  char *current_pcr = value;
+  char *next_pcr;
+  unsigned long pcr;
+  grub_uint8_t i;
+
+  if (grub_strlen (value) == 0)
+return GRUB_ERR_BAD_ARGUMENT;
+
+  *pcr_count = 0;
+  for (i = 0; i < TPM_MAX_PCRS; i++)
+{
+  next_pcr = grub_strchr (current_pcr, ',');
+  if (next_pcr == current_pcr)
+return grub_error (GRUB_ERR_BAD_ARGUMENT,
+   N_("Empty entry in PCR list"));
+  if (next_pcr)
+*next_pcr = '\0';
+
+  grub_errno = GRUB_ERR_NONE;
+  pcr = grub_strtoul (current_pcr, NULL, 10);
+  if (grub_errno != GRUB_ERR_NONE)
+return grub_error (grub_errno,
+   N_("Entry '%s' in PCR list is not a number"),
+   current_pcr);
+
+  if (pcr > TPM_MAX_PCRS)
+return grub_error (GRUB_ERR_OUT_OF_RANGE,
+   N_("Entry %lu in PCR list is too large to be a PCR "
+  "number, PCR numbers range from 0 to %u"),
+   pcr, TPM_MAX_PCRS);
+
+  pcrs[i] = (grub_uint8_t)pcr;
+  *pcr_count += 1;
+
+  if (!next_pcr)
+break;
+

[PATCH v2 5/5] util/grub-protect: Add new tool

2022-02-01 Thread Hernan Gatta
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 key protector (-k) parameter.

Sample usage:

$ dd if=/dev/urandom of=key bs=1 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

Then, in the boot script:

tpm2_key_protector_init -k (hd0,gpt1)/boot/grub2/sealed_key
cryptomount -u b20f95d0834842bc9197bd78b36732f8 -k tpm2

where the UUID corresponds to /dev/sdb1.

Signed-off-by: Hernan Gatta 
---
 .gitignore  |1 +
 Makefile.util.def   |   18 +
 configure.ac|1 +
 util/grub-protect.c | 1314 +++
 4 files changed, 1334 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..be2d6f4 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -207,6 +207,24 @@ program = {
 };
 
 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 = 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 000..23ee78d
--- /dev/null
+++ b/util/grub-protect.c
@@ -0,0 +1,1314 @@
+/*
+ *  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 .
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#include 
+#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_PERSIST,
+  GRUB_PROTECT_OPT_TPM2_EVICT
+} grub_protect_opt;
+
+/* Option flags to keep track of specified arguments */
+typedef enum grub_protect_arg
+{
+

[PATCH v2 1/5] protectors: Add key protectors framework

2022-02-01 Thread Hernan Gatta
A key protector encapsulates functionality to retrieve an unlocking key for a
fully-encrypted disk from a specific source. A key protector module registers
itself with the key protectors framework when it is loaded and unregisters when
unloaded. Additionally, a key protector may accept parameters that describe how
it should operate.

The key protectors framework, besides offering registration and unregistration
functions, also offers a one-stop routine for finding and invoking a key
protector by name. If a key protector with the specified name exists and if an
unlocking key is successfully retrieved by it, the function returns to the
caller the retrieved key and its length.

Signed-off-by: Hernan Gatta 
---
 grub-core/Makefile.am   |  1 +
 grub-core/Makefile.core.def |  1 +
 grub-core/kern/protectors.c | 75 +
 include/grub/protector.h| 48 +
 4 files changed, 125 insertions(+)
 create mode 100644 grub-core/kern/protectors.c
 create mode 100644 include/grub/protector.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index ee88e44..f78cd9d 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -90,6 +90,7 @@ endif
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/protector.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 8022e1c..e4ae78b 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -138,6 +138,7 @@ kernel = {
   common = kern/misc.c;
   common = kern/parser.c;
   common = kern/partition.c;
+  common = kern/protectors.c;
   common = kern/rescue_parser.c;
   common = kern/rescue_reader.c;
   common = kern/term.c;
diff --git a/grub-core/kern/protectors.c b/grub-core/kern/protectors.c
new file mode 100644
index 000..21954df
--- /dev/null
+++ b/grub-core/kern/protectors.c
@@ -0,0 +1,75 @@
+/*
+ *  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 .
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+struct grub_key_protector *grub_key_protectors = NULL;
+
+grub_err_t
+grub_key_protector_register (struct grub_key_protector *protector)
+{
+  if (!protector || !protector->name || !grub_strlen(protector->name))
+return GRUB_ERR_BAD_ARGUMENT;
+
+  if (grub_key_protectors &&
+  grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+protector->name))
+return GRUB_ERR_BAD_ARGUMENT;
+
+  grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors),
+  GRUB_AS_LIST (protector));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_unregister (struct grub_key_protector *protector)
+{
+  if (!protector)
+return GRUB_ERR_BAD_ARGUMENT;
+
+  grub_list_remove (GRUB_AS_LIST (protector));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_recover_key (const char *protector, grub_uint8_t **key,
+grub_size_t *key_size)
+{
+  struct grub_key_protector *kp = NULL;
+
+  if (!grub_key_protectors)
+return GRUB_ERR_OUT_OF_RANGE;
+
+  if (!protector || !grub_strlen (protector))
+return GRUB_ERR_BAD_ARGUMENT;
+
+  kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector);
+  if (!kp)
+return grub_error (GRUB_ERR_OUT_OF_RANGE,
+   N_("A key protector with name '%s' could not be found. "
+  "Is the name spelled correctly and is the "
+  "corresponding module loaded?"), protector);
+
+  return kp->recover_key (key, key_size);
+}
diff --git a/include/grub/protector.h b/include/grub/protector.h
new file mode 100644
index 000..179020a
--- /dev/null
+++ b/include/grub/protector.h
@@ -0,0 +1,48 @@
+/*
+ *  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 Licen

[PATCH v2 4/5] cryptodisk: Support key protectors

2022-02-01 Thread Hernan Gatta
Add a new parameter to cryptomount to support the key protectors framework: -k.
The parameter is used to automatically retrieve a key from specified key
protectors. The parameter may be repeated to specify any number of key
protectors. These are tried in order until one provides a usable key for any
given disk.

Signed-off-by: 
---
 Makefile.util.def   |   1 +
 grub-core/disk/cryptodisk.c | 166 
 include/grub/cryptodisk.h   |  14 
 3 files changed, 151 insertions(+), 30 deletions(-)

diff --git a/Makefile.util.def b/Makefile.util.def
index f8b356c..39b53b3 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -35,6 +35,7 @@ library = {
   common = grub-core/kern/list.c;
   common = grub-core/kern/misc.c;
   common = grub-core/kern/partition.c;
+  common = grub-core/kern/protectors.c;
   common = grub-core/lib/crypto.c;
   common = grub-core/lib/json/json.c;
   common = grub-core/disk/luks.c;
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 4970973..00c4477 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef GRUB_UTIL
 #include 
@@ -42,6 +43,8 @@ static const struct grub_arg_option options[] =
 {"all", 'a', 0, N_("Mount all."), 0, 0},
 {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
 {"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
+{"protector", 'k', GRUB_ARG_OPTION_REPEATABLE,
+ N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
 {0, 0, 0, 0, 0, 0}
   };
 
@@ -1000,7 +1003,8 @@ grub_cryptodisk_scan_device_real (const char *name,
 {
   grub_err_t ret = GRUB_ERR_NONE;
   grub_cryptodisk_t dev;
-  grub_cryptodisk_dev_t cr;
+  grub_cryptodisk_dev_t cr, crd = NULL;
+  int i;
   int askpass = 0;
   char *part = NULL;
 
@@ -1016,39 +1020,108 @@ grub_cryptodisk_scan_device_real (const char *name,
   return NULL;
 if (!dev)
   continue;
+crd = cr;
+  }
 
-if (!cargs->key_len)
-  {
-   /* Get the passphrase from the user, if no key data. */
-   askpass = 1;
-   part = grub_partition_get_name (source->partition);
-   grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
-source->partition != NULL ? "," : "",
-part != NULL ? part : N_("UNKNOWN"),
-dev->uuid);
-   grub_free (part);
-
-   cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
-   if (cargs->key_data == NULL)
- return NULL;
-
-   if (!grub_password_get ((char *) cargs->key_data, 
GRUB_CRYPTODISK_MAX_PASSPHRASE))
- {
-   grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
-   goto error;
- }
-   cargs->key_len = grub_strlen ((char *) cargs->key_data);
-  }
+  if (!dev)
+{
+  grub_error (GRUB_ERR_BAD_MODULE,
+  "no cryptodisk module can handle this device");
+  return NULL;  
+}
 
-ret = cr->recover_key (source, dev, cargs);
-if (ret != GRUB_ERR_NONE)
+  if (cargs->protectors)
+{
+  for (i = 0; cargs->protectors[i]; i++)
+{
+  if (cargs->key_cache[i].invalid)
+continue;
+
+  if (!cargs->key_cache[i].key)
+{
+  ret = grub_key_protector_recover_key (cargs->protectors[i],
+&cargs->key_cache[i].key,
+
&cargs->key_cache[i].key_len);
+  if (ret)
+{
+  if (grub_errno)
+{
+  grub_print_error ();
+  grub_errno = GRUB_ERR_NONE;
+}
+
+  grub_dprintf ("cryptodisk",
+"failed to recover a key from key protector "
+"%s, will not try it again for any other "
+"disks, if any, during this invocation of "
+"cryptomount\n",
+cargs->protectors[i]);
+
+  cargs->key_cache[i].invalid = 1;
+  continue;
+}
+}
+
+  cargs->key_data = cargs->key_cache[i].key;
+  cargs->key_len = cargs->key_cache[i].key_len;
+
+  ret = crd->recover_key (source, dev, cargs);
+  if (ret)
+{
+  part = grub_partition_get_name (source->partition);
+  grub_dprintf ("cryptodisk",
+"recovered a key from key protector %s but it "
+"failed to unlock %s%s%s (%s)\n",
+ cargs->protectors[i], source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), d

[PATCH v2 0/5] Automatic TPM Disk Unlock

2022-02-01 Thread Hernan Gatta
Updates since v1:

1. One key can unlock multiple disks:
   It is now possible to use key protectors with cryptomount's -a and -b
   options.

2. No passphrase prompt on error if key protector(s) specified:
   cryptomount no longer prompts for a passphrase if key protectors are
   specified but fail to provide a working unlock key seeing as the user
   explicitly requested unlocking via key protectors.

3. Key protector parameterization is separate:
   Previously, one would parameterize a key protector via a colon-separated
   argument list nested within a cryptomount argument. Now, key protectors are
   expected to provide an initialization function, if necessary.

   As such, instead of:

   cryptomount -k tpm2:mode=srk:keyfile=KEYFILE:pcrs=7,11...

   one now writes:

   tpm2_key_protector_init --mode=srk --keyfile=KEYFILE --pcrs=7,11 ...
   cryptomount -k tpm2

   Additionally, one may write:

   cryptomount -k protector_1 -k protector_2 ...

   where cryptomount will try each in order on failure.

4. Standard argument parsing:
   The TPM2 key protector now uses 'struct grub_arg_option' and the grub-protect
   tool uses 'struct argp_option'. Additionally, common argument parsing
   functionality is now shared between the module and the tool.

5. More useful messages:
   Both the TPM2 module and the grub-protect tool now provide more useful
   messages to help the user learn how to use their functionality (--help and
   --usage) as well as to determine what is wrong, if anything. Furthermore, the
   module now prints additional debug output to help diagnose problems.

I forgot to mention last time that this patch series intends to address:
https://bugzilla.redhat.com/show_bug.cgi?id=1854177

Previous series:
https://lists.gnu.org/archive/html/grub-devel/2022-01/msg00125.html

Thank you,
Hernan

Signed-off-by: Hernan Gatta 

Hernan Gatta (5):
  protectors: Add key protectors framework
  tpm2: Add TPM Software Stack (TSS)
  protectors: Add TPM2 Key Protector
  cryptodisk: Support key protectors
  util/grub-protect: Add new tool

 .gitignore |1 +
 Makefile.util.def  |   19 +
 configure.ac   |1 +
 grub-core/Makefile.am  |1 +
 grub-core/Makefile.core.def|   11 +
 grub-core/disk/cryptodisk.c|  166 +++-
 grub-core/kern/protectors.c|   75 ++
 grub-core/tpm2/args.c  |  129 
 grub-core/tpm2/buffer.c|  145 
 grub-core/tpm2/module.c|  710 +
 grub-core/tpm2/mu.c|  807 
 grub-core/tpm2/tcg2.c  |  143 
 grub-core/tpm2/tpm2.c  |  711 +
 include/grub/cryptodisk.h  |   14 +
 include/grub/protector.h   |   48 ++
 include/grub/tpm2/buffer.h |   65 ++
 include/grub/tpm2/internal/args.h  |   39 +
 include/grub/tpm2/internal/functions.h |  117 +++
 include/grub/tpm2/internal/structs.h   |  675 
 include/grub/tpm2/internal/types.h |  372 +
 include/grub/tpm2/mu.h |  292 +++
 include/grub/tpm2/tcg2.h   |   34 +
 include/grub/tpm2/tpm2.h   |   38 +
 util/grub-protect.c| 1314 
 24 files changed, 5897 insertions(+), 30 deletions(-)
 create mode 100644 grub-core/kern/protectors.c
 create mode 100644 grub-core/tpm2/args.c
 create mode 100644 grub-core/tpm2/buffer.c
 create mode 100644 grub-core/tpm2/module.c
 create mode 100644 grub-core/tpm2/mu.c
 create mode 100644 grub-core/tpm2/tcg2.c
 create mode 100644 grub-core/tpm2/tpm2.c
 create mode 100644 include/grub/protector.h
 create mode 100644 include/grub/tpm2/buffer.h
 create mode 100644 include/grub/tpm2/internal/args.h
 create mode 100644 include/grub/tpm2/internal/functions.h
 create mode 100644 include/grub/tpm2/internal/structs.h
 create mode 100644 include/grub/tpm2/internal/types.h
 create mode 100644 include/grub/tpm2/mu.h
 create mode 100644 include/grub/tpm2/tcg2.h
 create mode 100644 include/grub/tpm2/tpm2.h
 create mode 100644 util/grub-protect.c

-- 
1.8.3.1


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH 0/2] Support plain encryption mode.

2022-02-01 Thread Maxim Fomin
--- Original Message ---

On Monday, January 31st, 2022 at 23:40, Glenn Washburn 
 wrote:

> On Sun, 30 Jan 2022 19:40:37 +
>
> Maxim Fomin ma...@fomin.one wrote:
>
> > This patch adds support for plain encryption mode (plain dm-crypt) via new
> >
> > module/command named 'plainmount'. This is an extension of previous patch
> >
> > (member of crypto enhancement patch series) sent to grub-devel by John Lane.
> >
> > The plain mode patch was fully reworked, the most important changes are:
> >
> > 1.  The code is rewritten as a separate 'plainmount' module and command. 
> > This
> >
> > change addresses several issues raised in previous patch discussion: 
> > complex
> >
> > implementation and expanding too much cryptomount parameter list. 
> > Plainmount
> >
> > module still depends on several functions in cryptodisk module just 
> > like LUKS,
> >
> > LUKS2 and geli modules. I tried to minimize link to cryptodisk, but 
> > some link
> >
> > is unavoidable.
> >
> > 2.  Plainmount now uses GPT partition unique UUID to point to exact 
> > partition.
> >
> > Plain mode does not have special header (as LUKS/LUKS2 does), so it 
> > does not
> >
> > have any UUID. Absence of UUID was key issue in discussions of original 
> > plain
> >
> > mode patch - without UUID any link like 'hdX,gptY' in grub.cfg can be 
> > broken
> >
> > in multiboot setup because hdX can map to different disks each boot.
> >
>
> So plain mount can only be used for volumes located on GPT partitions,
>
> leaving out MBR or any other partitioning format, full-disk encryption,
>
> and loopback file encryption. I think this is an undesirable and
>
> unnecessary limitation.
>
> Instead, I suggest assuming the user knows what they are doing in the
>
> GRUB shell/script and letting them do it. This should not be allowed
>
> when automatically generating the grub.cfg using GRUB user-space tools.
>
> GRUB should fail to automagically install to a device hosted on a plain
>
> encrypted container (unless perhaps an override is given). I suspect
>
> that this is the default, but worth mentioning.
>
> Glenn

Plainmount can work with '(hdX,gptY)' syntax in config or shell (actually, this
is the base syntax) and thus it is not limited to GPT paritions, what is limited
is the ability to use UUID - currently only on GPT. If partition scheme does not
have UUID then UUID as a convenience feature cannot be supported - inconvenient,
but technically fair. I will take a look at MBR UUID and see whether they can be
supported. Possible situations (under current implementaion) are follows:

a) GPT disk, multi-disk environment, disks map unpredictably: can name 
partitions
   by GPT UUID in config file/shell, no problem, ability to name by UUID has 
value
b) GPT disk, single disk environment: no problem, UUID feature has less value
b) not GPT, single disk environment: no problem, config like 'plainmount 
(hd0,gpt2)'
   always works
d) not GPT, multi-disk environment, disks map unpredictably: worst case, link
   '(hd0,gpt2)' can randomly fail, but user can type manually in shell
e) cannot mount plain mode device in grub shell <- this is impossible, 
plainmount
   can always be called in shell.

Best regards,
Maxim Fomin

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v3 0/4] Update gnulib and drop some patches

2022-02-01 Thread Glenn Washburn
On Thu, 27 Jan 2022 14:39:56 -0500
Robbie Harwood  wrote:

> Changes in this version:
> - Make the version of bootstrap match what it's supposed to
> - Restore fix-width.patch at dkiper's request
> 
> Be well,
> --Robbie

I presume this has been build tested, right?

I'm getting the following compiler error with gcc 10.1.0:

In file included from
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/disk /luks2.c:30:
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/disk/luks2.c: In
function ‘luks2_verify_key’:
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/disk/luks2.c:398:75:
error: pointer targets in passing argument 5 of ‘base64_decode_ctx’
differ in signedness [-Werror=pointer-sign] 398 |   if (!base64_decode
(d->digest, grub_strlen (d->digest), (char *)digest, &digestlen)) |
  ^~
|
| |
  grub_size_t * {aka long unsigned int *}
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/lib/gnulib/base64.h:59:50:
note: in definition of macro ‘base64_decode’ 59 |
base64_decode_ctx (NULL, in, inlen, out, outlen) |
^~
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/lib/gnulib/base64.h:52:59:
note: expected ‘idx_t *’ {aka ‘long int *’} but argument is of type
‘grub_size_t *’ {aka ‘long unsigned int *’}
   52 |char *restrict out, idx_t
*outlen); |
~~~^~
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/disk/luks2.c:400:69:
error: pointer targets in passing argument 5 of ‘base64_decode_ctx’
differ in signedness [-Werror=pointer-sign] 400 |   if (!base64_decode
(d->salt, grub_strlen (d->salt), (char *)salt, &saltlen)) |
^~~~ |
   | |
   grub_size_t
* {aka long unsigned int *}
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/lib/gnulib/base64.h:59:50:
note: in definition of macro ‘base64_decode’ 59 |
base64_decode_ctx (NULL, in, inlen, out, outlen) |
^~
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/lib/gnulib/base64.h:52:59:
note: expected ‘idx_t *’ {aka ‘long int *’} but argument is of type
‘grub_size_t *’ {aka ‘long unsigned int *’} 52 |
char *restrict out, idx_t *outlen); |
 ~~~^~
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/disk/luks2.c: In
function ‘luks2_decrypt_key’:
home/g10/grub-tests-uml-update-gnulib/grub/grub-core/disk/luks2.c:439:22:
error: pointer targets in passing argument 5 of ‘base64_decode_ctx’
differ in signedness [-Werror=pointer-sign] 439 |(char *)salt,
&saltlen)) |  ^~~~ |  |
  |  grub_size_t * {aka long unsigned int *}
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/lib/gnulib/base64.h:59:50:
note: in definition of macro ‘base64_decode’ 59 |
base64_decode_ctx (NULL, in, inlen, out, outlen) |
^~
/home/g10/grub-tests-uml-update-gnulib/grub/grub-core/lib/gnulib/base64.h:52:59:
note: expected ‘idx_t *’ {aka ‘long int *’} but argument is of type
‘grub_size_t *’ {aka ‘long unsigned int *’} 52 |
char *restrict out, idx_t *outlen); |
 ~~~^~
cc1: all warnings being treated as errors

Should be an easy fix. What compiler version are you using?

Glenn

> 
> Robbie Harwood (4):
>   Use visual indentation in config.h.in
>   Drop gnulib fix-base64.patch
>   Drop gnulib no-abort.patch
>   Update gnulib version and drop most gnulib patches
> 
>  bootstrap | 319 ++
>  bootstrap.conf|  18 +-
>  conf/Makefile.extra-dist  |   8 -
>  config.h.in   |  78 +++--
>  configure.ac  |   2 +-
>  grub-core/Makefile.core.def   |   1 +
>  grub-core/lib/gnulib-patches/fix-base64.patch |  21 --
>  .../lib/gnulib-patches/fix-null-deref.patch   |  13 -
>  .../gnulib-patches/fix-null-state-deref.patch |  12 -
>  .../fix-regcomp-uninit-token.patch|  15 -
>  .../fix-regexec-null-deref.patch  |  12 -
>  .../gnulib-patches/fix-uninit-structure.patch |  11 -
>  .../lib/gnulib-patches/fix-unused-value.patch |  14 -
>  grub-core/lib/gnulib-patches/no-abort.patch   |  26 --
>  grub-core/lib/posix_wrap/sys/types.h  |   7 +-
>  grub-core/lib/xzembed/xz.h|   5 +-
>  16 files changed, 248 insertions(+), 314 deletions(-)
>  delete mode 100644 grub-core/lib/gnulib-patches/fix-base64.patch
>  delete mode 100644 grub-core/lib/gnulib-patches/fix-null-deref.patch
>  delete mode 100644 grub-core/lib/gnulib-patches/fix-null-state-deref.patch
>  delete mode 100644 
> grub-core/lib/gnulib-patches/fix-regcomp-uninit-token

Re: [PATCH 0/2] Support plain encryption mode.

2022-02-01 Thread Glenn Washburn
On Tue, 01 Feb 2022 15:48:01 +
Maxim Fomin  wrote:

> --- Original Message ---
> 
> On Monday, January 31st, 2022 at 23:40, Glenn Washburn 
>  wrote:
> 
> > On Sun, 30 Jan 2022 19:40:37 +
> >
> > Maxim Fomin ma...@fomin.one wrote:
> >
> > > This patch adds support for plain encryption mode (plain dm-crypt) via new
> > >
> > > module/command named 'plainmount'. This is an extension of previous patch
> > >
> > > (member of crypto enhancement patch series) sent to grub-devel by John 
> > > Lane.
> > >
> > > The plain mode patch was fully reworked, the most important changes are:
> > >
> > > 1.  The code is rewritten as a separate 'plainmount' module and command. 
> > > This
> > >
> > > change addresses several issues raised in previous patch discussion: 
> > > complex
> > >
> > > implementation and expanding too much cryptomount parameter list. 
> > > Plainmount
> > >
> > > module still depends on several functions in cryptodisk module just 
> > > like LUKS,
> > >
> > > LUKS2 and geli modules. I tried to minimize link to cryptodisk, but 
> > > some link
> > >
> > > is unavoidable.
> > >
> > > 2.  Plainmount now uses GPT partition unique UUID to point to exact 
> > > partition.
> > >
> > > Plain mode does not have special header (as LUKS/LUKS2 does), so it 
> > > does not
> > >
> > > have any UUID. Absence of UUID was key issue in discussions of 
> > > original plain
> > >
> > > mode patch - without UUID any link like 'hdX,gptY' in grub.cfg can be 
> > > broken
> > >
> > > in multiboot setup because hdX can map to different disks each boot.
> > >
> >
> > So plain mount can only be used for volumes located on GPT partitions,
> >
> > leaving out MBR or any other partitioning format, full-disk encryption,
> >
> > and loopback file encryption. I think this is an undesirable and
> >
> > unnecessary limitation.
> >
> > Instead, I suggest assuming the user knows what they are doing in the
> >
> > GRUB shell/script and letting them do it. This should not be allowed
> >
> > when automatically generating the grub.cfg using GRUB user-space tools.
> >
> > GRUB should fail to automagically install to a device hosted on a plain
> >
> > encrypted container (unless perhaps an override is given). I suspect
> >
> > that this is the default, but worth mentioning.
> >
> > Glenn
> 
> Plainmount can work with '(hdX,gptY)' syntax in config or shell (actually, 
> this
> is the base syntax) and thus it is not limited to GPT paritions, what is 
> limited
> is the ability to use UUID - currently only on GPT. If partition scheme does 
> not
> have UUID then UUID as a convenience feature cannot be supported - 
> inconvenient,
> but technically fair. I will take a look at MBR UUID and see whether they can 
> be
> supported. Possible situations (under current implementaion) are follows:
> 
> a) GPT disk, multi-disk environment, disks map unpredictably: can name 
> partitions
>by GPT UUID in config file/shell, no problem, ability to name by UUID has 
> value

I agree that searching by partition UUID is useful and desirable.
However, I don't think this is the right approach. GRUB should have
generic searching by partition UUID. There is already a patch for
this[1]. Perhaps you can test/review this patch to help it gain more
visibility and advocate for it being accepted.

Glenn

[1] https://lists.gnu.org/archive/html/grub-devel/2021-04/msg00055.html

> b) GPT disk, single disk environment: no problem, UUID feature has less value
> b) not GPT, single disk environment: no problem, config like 'plainmount 
> (hd0,gpt2)'
>always works
> d) not GPT, multi-disk environment, disks map unpredictably: worst case, link
>'(hd0,gpt2)' can randomly fail, but user can type manually in shell
> e) cannot mount plain mode device in grub shell <- this is impossible, 
> plainmount
>can always be called in shell.
> 
> Best regards,
> Maxim Fomin
> 
> ___
> 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


Re: [PATCH v3] commands/search: Add support to search by PARTUUID

2022-02-01 Thread Glenn Washburn
Hi Vitaly,

Now that GRUB is out of a feature freeze, there's a chance this can
make it in.

On Thu, 15 Apr 2021 16:59:07 +0300
Vitaly Kuzmichev via Grub-devel  wrote:

> Improve 'search' grub-shell command with functionality to search for
> a partition by PARTUUID string. This is useful on systems where FSUUID
> is not guaranteed to be constant, e.g. it is not preserved between
> system updates, and modifying grub.cfg is undesired.
> 
> V2:
> This patch is based on Michael Grzeschik version from 27 May 2019 [1]
> with the following changes:
> 
> 1. Addressed review feedback from Daniel Kiper [2] and Nick Vinson [3].
> 
> 2. Added support for GPT PARTUUID.
> 
> 3. Moved MBR disk signature reading from partmap/msdos.c to
> commands/search.c to read it only when it is needed.
> 
> [1] https://lists.gnu.org/archive/html/grub-devel/2019-05/msg00124.html
> [2] https://lists.gnu.org/archive/html/grub-devel/2019-05/msg00131.html
> [3] https://lists.gnu.org/archive/html/grub-devel/2019-05/msg00134.html
> 
> V3:
> Minor coding style and spelling fixes.
> 
> Signed-off-by: Vitaly Kuzmichev 
> ---
>  grub-core/Makefile.core.def  |  5 ++
>  grub-core/commands/search.c  | 80 +++-
>  grub-core/commands/search_partuuid.c |  5 ++
>  grub-core/commands/search_wrap.c | 10 +++-
>  include/grub/search.h|  2 +
>  5 files changed, 98 insertions(+), 4 deletions(-)
>  create mode 100644 grub-core/commands/search_partuuid.c

There should be a documentation change as well to document the new
parameter.

> 
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 8022e1c0a..4568943e3 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -1063,6 +1063,11 @@ module = {
>common = commands/search_file.c;
>  };
>  
> +module = {
> +  name = search_partuuid;
> +  common = commands/search_partuuid.c;
> +};
> +
>  module = {
>name = search_fs_uuid;
>common = commands/search_uuid.c;
> diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c
> index ed090b3af..5014982fd 100644
> --- a/grub-core/commands/search.c
> +++ b/grub-core/commands/search.c
> @@ -54,6 +54,28 @@ struct search_ctx
>int is_cache;
>  };
>  
> +#ifdef DO_SEARCH_PARTUUID
> +#include 
> +#include 

These are better just put at the top with the rest of the includes. I
don't think they need to be ifdef'd, I wouldn't complain if they were
either.

> +
> +/* Helper for iterate_device. */
> +static char *
> +gpt_guid_to_str (grub_gpt_part_guid_t *gpt_guid)
> +{
> +  /* Convert mixed-endian UUID from bytes to string */
> +  return
> +grub_xasprintf (
> +  "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
> + grub_le_to_cpu32(gpt_guid->data1),
> + grub_le_to_cpu16(gpt_guid->data2),
> + grub_le_to_cpu16(gpt_guid->data3),
> + gpt_guid->data4[0], gpt_guid->data4[1],
> + gpt_guid->data4[2], gpt_guid->data4[3],
> + gpt_guid->data4[4], gpt_guid->data4[5],
> + gpt_guid->data4[6], gpt_guid->data4[7]);

I think its better to do the compare with dashes stripped out of both.
Or even better to use grub_uuidcascmp (which comes from my patch
series[1] that I hope to get accepted at some point).

> +}
> +#endif
> +
>  /* Helper for FUNC_NAME.  */
>  static int
>  iterate_device (const char *name, void *data)
> @@ -66,13 +88,63 @@ iterate_device (const char *name, void *data)
>name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
>  return 1;
>  
> -#ifdef DO_SEARCH_FS_UUID
> +#if defined (DO_SEARCH_FS_UUID) || defined (DO_SEARCH_PARTUUID)
>  #define compare_fn grub_strcasecmp
>  #else
>  #define compare_fn grub_strcmp
>  #endif
>  
> -#ifdef DO_SEARCH_FILE
> +#ifdef DO_SEARCH_PARTUUID
> +{
> +  struct grub_gpt_partentry gptdata;
> +  grub_uint32_t disk_sig;
> +  grub_disk_t ptdisk;
> +  grub_disk_t disk;
> +  char *part_uuid;
> +
> +  ptdisk = grub_disk_open (name);
> +  if (ptdisk && ptdisk->partition && ptdisk->partition->partmap)
> + {
> +   if (grub_strcmp (ptdisk->partition->partmap->name, "gpt") == 0)
> + {
> +   disk = grub_disk_open (ptdisk->name);
> +   if (disk && grub_disk_read (disk, ptdisk->partition->offset,
> +   ptdisk->partition->index,
> +   sizeof (gptdata), &gptdata) == 0)
> + {
> +   part_uuid = gpt_guid_to_str (&gptdata.guid);
> +
> +   if (part_uuid && compare_fn (part_uuid, ctx->key) == 0)
> + found = 1;
> +   if (part_uuid)
> + grub_free (part_uuid);
> + }
> +   if (disk)
> + grub_disk_close (disk);
> + }
> +   else if (grub_strcmp (ptdisk->partition->partmap->name, "msdos") == 0)
> + {
> +   disk = grub_disk_open (ptdisk->name);
> +   if (disk && grub_disk_read (disk, 0,
> + 

Re: [PATCH v2 0/5] Automatic TPM Disk Unlock

2022-02-01 Thread Didier Spaier
Hi,

pardon me to top post just once, the answer below was sent in reply to v1 but
seems not to have made through as I do not find it in the archives, and it is
about the proposal in general.

Here goes (initially posted on Tue, 25 Jan 2022):

Sorry for a newbie question (I plan to allow installing Slint on a Secure Boot
enabled machine if/when I can but know almost nothing yet on this topic).

Currently we allow in the "auto" mode of installation to install Slint in a
fully encrypted drive (minus the ESP and the BIOS Boot partition), the user
typing then a passphrase only once when politely requested by GRUB before
displaying its menu (without using LVM as we store a LUKS key in the initramfs).

The main purpose is to forbid access to the system when the machine is powered
off, for instance in case of a laptop stolen during a travel.

Would the feature you describe possibly allow to circumvent this protection?

Thanks,
Didier
--
Didier Spaier
Slint maintainer


Le 01/02/2022 à 14:02, Hernan Gatta a écrit :
> Updates since v1:
> 
> 1. One key can unlock multiple disks:
>It is now possible to use key protectors with cryptomount's -a and -b
>options.
> 
> 2. No passphrase prompt on error if key protector(s) specified:
>cryptomount no longer prompts for a passphrase if key protectors are
>specified but fail to provide a working unlock key seeing as the user
>explicitly requested unlocking via key protectors.
> 
> 3. Key protector parameterization is separate:
>Previously, one would parameterize a key protector via a colon-separated
>argument list nested within a cryptomount argument. Now, key protectors are
>expected to provide an initialization function, if necessary.
> 
>As such, instead of:
> 
>cryptomount -k tpm2:mode=srk:keyfile=KEYFILE:pcrs=7,11...
> 
>one now writes:
> 
>tpm2_key_protector_init --mode=srk --keyfile=KEYFILE --pcrs=7,11 ...
>cryptomount -k tpm2
> 
>Additionally, one may write:
> 
>cryptomount -k protector_1 -k protector_2 ...
> 
>where cryptomount will try each in order on failure.
> 
> 4. Standard argument parsing:
>The TPM2 key protector now uses 'struct grub_arg_option' and the 
> grub-protect
>tool uses 'struct argp_option'. Additionally, common argument parsing
>functionality is now shared between the module and the tool.
> 
> 5. More useful messages:
>Both the TPM2 module and the grub-protect tool now provide more useful
>messages to help the user learn how to use their functionality (--help and
>--usage) as well as to determine what is wrong, if anything. Furthermore, 
> the
>module now prints additional debug output to help diagnose problems.
> 
> I forgot to mention last time that this patch series intends to address:
> https://bugzilla.redhat.com/show_bug.cgi?id=1854177
> 
> Previous series:
> https://lists.gnu.org/archive/html/grub-devel/2022-01/msg00125.html
> 
> Thank you,
> Hernan
> 
> Signed-off-by: Hernan Gatta 
> 
> Hernan Gatta (5):
>   protectors: Add key protectors framework
>   tpm2: Add TPM Software Stack (TSS)
>   protectors: Add TPM2 Key Protector
>   cryptodisk: Support key protectors
>   util/grub-protect: Add new tool
> 
>  .gitignore |1 +
>  Makefile.util.def  |   19 +
>  configure.ac   |1 +
>  grub-core/Makefile.am  |1 +
>  grub-core/Makefile.core.def|   11 +
>  grub-core/disk/cryptodisk.c|  166 +++-
>  grub-core/kern/protectors.c|   75 ++
>  grub-core/tpm2/args.c  |  129 
>  grub-core/tpm2/buffer.c|  145 
>  grub-core/tpm2/module.c|  710 +
>  grub-core/tpm2/mu.c|  807 
>  grub-core/tpm2/tcg2.c  |  143 
>  grub-core/tpm2/tpm2.c  |  711 +
>  include/grub/cryptodisk.h  |   14 +
>  include/grub/protector.h   |   48 ++
>  include/grub/tpm2/buffer.h |   65 ++
>  include/grub/tpm2/internal/args.h  |   39 +
>  include/grub/tpm2/internal/functions.h |  117 +++
>  include/grub/tpm2/internal/structs.h   |  675 
>  include/grub/tpm2/internal/types.h |  372 +
>  include/grub/tpm2/mu.h |  292 +++
>  include/grub/tpm2/tcg2.h   |   34 +
>  include/grub/tpm2/tpm2.h   |   38 +
>  util/grub-protect.c| 1314 
> 
>  24 files changed, 5897 insertions(+), 30 deletions(-)
>  create mode 100644 grub-core/kern/protectors.c
>  create mode 100644 grub-core/tpm2/args.c
>  create mode 100644 grub-core/tpm2/buffer.c
>  create mode 100644 grub-core/tpm2/module.c
>  create mode 100644 grub-core/tpm2/mu.c
>  create mode 100644 grub-core/tpm2/tcg2.c
>  create mode 100644 grub-core/tpm2/tpm2.c
>  create mode 100644 include/grub/protector.h
>  create