Re: [PATCH V2] ieee1275/ofdisk: vscsi lun handling on lun len

2024-01-16 Thread Mukesh Kumar Chaurasiya


On 11/30/23 00:45, Daniel Kiper wrote:

On Mon, Nov 27, 2023 at 06:07:42PM +0530, Mukesh Kumar Chaurasiya wrote:

Signed-off-by: Mukesh Kumar Chaurasiya 
---
  grub-core/disk/ieee1275/ofdisk.c | 11 ---
  1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index c6cba0c8a..9cd8898f1 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -222,8 +222,12 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
grub_ieee1275_cell_t table;
}
args;
+  struct lun_buf {
+   grub_uint64_t *buf_addr;

This will not work on 32-bit architectures.


Umm...

 well i checked this and the definition for 32bit and 64bit are same. 
So the structure part should be fine.


+ ptr =(grub_uint64_t*)(grub_addr_t) tbl[i].buf_addr;
and this should handle the 32bit arch in terms of address.
for rest i'll send out a new version of patch
Regards,
Mukesh

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


Re: [PATCH] util/grub.d/30_os-prober.in: Skip drivemap for Windows 8 to 19, Server 2012 and later

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
On Sat, Jan 6, 2024 at 6:38 PM Pascal Hambourg  wrote:
>
> If Windows Vista, Seven and Server 2008 do not need drivemap,
> then later versions using bootmgr too should not need it either.
>
> Note:
> This patch checks Windows versions up to 19 because distinguishing 20
> from 2000 requires more complex logic. Hopefully Windows will drop
> BIOS/legacy boot support before version 20.
Frankly people though x86 would be long dead by now...

> case ${LONGNAME} in
> -   Windows\ Vista*|Windows\ 7*|Windows\ Server\ 2008*)
> +   Windows\ Vista*|Windows\ [781]*|Windows\ Server\ 2008*|Windows\ 
> Server\ 20[1-9]*)

What happens to Windows 1.01 ? Or is it detected as MS-DOS?
-- 
Regards
Vladimir 'phcoder' Serbinenko

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


Re: [PATCH] util/grub.d/30_os-prober.in: Conditionally show or hide chain and efi menu entries

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
>   onstr="$(gettext_printf "(on %s)" "${DEVICE}")"
> cat << EOF
> +if [ "\$grub_platform" != "efi" ]; then

This is not the right check. Only "pc" platform supports chainloadin
boot sector. All other: coreboot, qemu, emu, ieee1275, xen and
non-x86. The only one which might is xen_pvh but this needs to be
checked

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


Re: [PATCH v2] efi: Fix stack protector issues

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
Looks good. A small comment inline

> diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
> index 731c07c29..5db504e6e 100644
> --- a/grub-core/kern/main.c
> +++ b/grub-core/kern/main.c
> @@ -265,6 +265,11 @@ reclaim_module_space (void)
>  void __attribute__ ((noreturn))
>  grub_main (void)
>  {
> +#ifdef GRUB_STACK_PROTECTOR
> +  /* This call can only be made from a function that does not return. */
Please add a bit of reasoning here not just in the commit message


-- 
Regards
Vladimir 'phcoder' Serbinenko

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


Re: grub shell: unkown commands alwasy exit with zero code

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
On Tue, Jan 16, 2024 at 11:34 AM Michael Chang via Grub-devel
 wrote:
>
> On Fri, Jan 12, 2024 at 05:58:02PM +0100, Itxaka serrano wrote:
> > Hey all,
> >
> > I opened a bug because this behaviour doesnt seem correct to me:
> >
> > https://savannah.gnu.org/bugs/?65154
> >
> >
> > Example:
> >
> > grub> hello
> > error: ../../grub-core/script/function.c:119:can't find command `hello'.
> > grub> echo $?
> > 0
> >
> >
> > Kind of weird because on the code it seems like its returning a
> > GRUB_ERR_UNKNOWN_COMMAND which should not be zero. I had a quick look and
> > maybe its becuase on line 1018 of grub-core/script/execute.c we print the
> > error but always return 0
> > https://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/script/execute.c#n1018
> >
> > Is this expected behaviour or is it a mistake and we should not only print
> > the error but return the actual error?
>
> The behavior is expected:
>
> https://git.savannah.gnu.org/cgit/grub.git/commit/?id=bc028f2f86.
>
$? is set before clearing error so it should be set to unknown
command. So looks like there is more to it.

> Given the limited context, it remains unclear if the rationale behind
> this change can be easily retraced today.
>
> My take is that this modification may have been implemented to support
> the continued functionality of older `grub.cfg` files, even after
> certain commands have been removed. This ensures compatibility with the
> latest version of GRUB. Alternatively, it seems reasonable to halt
> execution when encountering a missing command, considering the potential
> consequence of such situations.
We can have an equivalent of "shopt -e" for those cases. Current
default matches default sh use.

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


Re: [PATCH v8 08/22] protectors: Add key protectors framework

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
Any strong reason to have it in kernel? It doesn't seem to be
necessary in non-crypto cases. Separate module or cryptodisk looks
like better places

On Tue, Jan 16, 2024 at 12:22 PM Gary Lin via Grub-devel
 wrote:
>
> From: 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 
> Signed-off-by: Gary Lin 
> ---
>  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 f18550c1c..af21fc72d 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 c9d81b56a..70d5e0e00 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -149,6 +149,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 0..5ee059565
> --- /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 == NULL || protector->name == NULL || 
> grub_strlen(protector->name) == 0)
> +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 (_key_protectors),
> + GRUB_AS_LIST (protector));
> +
> +  return GRUB_ERR_NONE;
> +}
> +
> +grub_err_t
> +grub_key_protector_unregister (struct grub_key_protector *protector)
> +{
> +  if (protector == NULL)
> +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 == NULL)
> +return GRUB_ERR_OUT_OF_RANGE;
> +
> +  if (protector == NULL || grub_strlen (protector) == 0)
> +return GRUB_ERR_BAD_ARGUMENT;
> +
> +  kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
> +protector);
> +  if (kp == NULL)
> +return grub_error (GRUB_ERR_OUT_OF_RANGE,
> +  N_("A key protector with name '%s' could not be found. 
> "
> + 

Re: [PATCH v8 07/22] libtasn1: Add the documentation

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
LGTM for doc. Patches reviewed separately

On Tue, Jan 16, 2024 at 12:23 PM Gary Lin via Grub-devel
 wrote:
>
> Document libtasn1 in docs/grub-dev.texi and add the upgrade steps.
> Also add the patches to make libtasn1 compatible with grub code.
>
> Signed-off-by: Gary Lin 
> ---
>  docs/grub-dev.texi|  27 ++
>  ...asn1-disable-code-not-needed-in-grub.patch | 311 ++
>  ...tasn1-changes-for-grub-compatibility.patch | 209 
>  3 files changed, 547 insertions(+)
>  create mode 100644 
> grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
>  create mode 100644 
> grub-core/lib/libtasn1-patches/0002-libtasn1-changes-for-grub-compatibility.patch
>
> diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
> index 1276c5930..80c6f6738 100644
> --- a/docs/grub-dev.texi
> +++ b/docs/grub-dev.texi
> @@ -596,6 +596,33 @@ cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
>  rm -r minilzo-2.10*
>  @end example
>
> +@node libtasn1
> +@section libtasn1
> +
> +libtasn1 is a library providing Abstract Syntax Notation One (ASN.1, as
> +specified by the X.680 ITU-T recommendation) parsing and structures 
> management,
> +and Distinguished Encoding Rules (DER, as per X.690) encoding and decoding
> +functions.
> +
> +To upgrade to a new version of the libtasn1 library, download the release
> +tarball and copy the files into the target directory:
> +
> +@example
> +curl -L -O https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.19.0.tar.gz
> +tar -zxf libtasn1-4.19.0.tar.gz
> +rm -r grub-core/lib/libtasn1/
> +mkdir libtasn1/lib
> +mkdir -p grub-core/lib/libtasn1/lib/
> +cp libtasn1-4.19.0/{README.md,COPYING} grub-core/lib/libtasn1/
> +cp 
> libtasn1-4.19.0/lib/{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h}
>  grub-core/lib/libtasn1/lib/
> +cp libtasn1-4.19.0/lib/includes/libtasn1.h include/grub/
> +rm -rf libtasn1-4.19.0
> +@end example
> +
> +After upgrading the library, it is necessary to apply the patches in
> +@file{grub-core/lib/libtasn1-patches/} to adjust the code to be compatible 
> with
> +grub.
> +
>  @node Debugging
>  @chapter Debugging
>
> diff --git 
> a/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
>  
> b/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
> new file mode 100644
> index 0..4f116dda5
> --- /dev/null
> +++ 
> b/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
> @@ -0,0 +1,311 @@
> +From c1c3459159d5d84e0d6da6eec6b86df5ccee1417 Mon Sep 17 00:00:00 2001
> +From: Daniel Axtens 
> +Date: Fri, 1 May 2020 17:12:23 +1000
> +Subject: [PATCH 1/2] libtasn1: disable code not needed in grub
> +
> +We don't expect to be able to write ASN.1, only read it,
> +so we can disable some code.
> +
> +Do that with #if 0/#endif, rather than deletion. This means
> +that the difference between upstream and grub is smaller,
> +which should make updating libtasn1 easier in the future.
> +
> +With these exclusions we also avoid the need for minmax.h,
> +which is convenient because it means we don't have to
> +import it from gnulib.
> +
> +Signed-off-by: Daniel Axtens 
> +Signed-off-by: Gary Lin 
> +---
> + grub-core/lib/libtasn1/lib/coding.c| 12 ++--
> + grub-core/lib/libtasn1/lib/decoding.c  |  2 ++
> + grub-core/lib/libtasn1/lib/element.c   |  4 ++--
> + grub-core/lib/libtasn1/lib/errors.c|  3 +++
> + grub-core/lib/libtasn1/lib/structure.c | 10 ++
> + include/grub/libtasn1.h| 15 +++
> + 6 files changed, 38 insertions(+), 8 deletions(-)
> +
> +diff --git a/grub-core/lib/libtasn1/lib/coding.c 
> b/grub-core/lib/libtasn1/lib/coding.c
> +index ea5bc370e..841fe47a9 100644
> +--- a/grub-core/lib/libtasn1/lib/coding.c
>  b/grub-core/lib/libtasn1/lib/coding.c
> +@@ -30,11 +30,11 @@
> + #include "parser_aux.h"
> + #include 
> + #include "element.h"
> +-#include "minmax.h"
> + #include 
> +
> + #define MAX_TAG_LEN 16
> +
> ++#if 0
> + /**/
> + /* Function : _asn1_error_description_value_not_found */
> + /* Description: creates the ErrorDescription string   */
> +@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
> +   Estrcat (ErrorDescription, "' not found");
> +
> + }
> ++#endif
> +
> + /**
> +  * asn1_length_der:
> +@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const 
> unsigned char *str,
> +   return ASN1_SUCCESS;
> + }
> +
> ++#if 0
> + /**/
> + /* Function : _asn1_time_der  */
> + /* Description: creates the DER coding for a TIME */
> +@@ -278,7 +280,7 @@ _asn1_time_der (unsigned char *str, int str_len, 
> unsigned char *der,
> +
> +   return ASN1_SUCCESS;
> + }
> +-
> ++#endif
> +
> + /*
> + void
> +@@ -519,6 +521,7 @@ asn1_bit_der (const unsigned 

Re: [PATCH v8 04/22] libtasn1: changes for grub compatibility

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
On Tue, Jan 16, 2024 at 12:23 PM Gary Lin via Grub-devel
 wrote:
>
> From: Daniel Axtens 
>
> Do a few things to make libtasn1 compile as part of grub:
>
>  - redefine _asn1_strcat. grub removed strcat so replace it with the
>appropriate calls to memcpy and strlen. Use this internally where
>strcat was used.
>
strcat is especially dangerous. If you can't easily replace it with
strncat/strlcat, you probably have a buffer overflow or potential to
have one after some code refactoring.strcpy isn't great either but a
bit better. memcpy+strlen isn't a good replacement. Maybe we can
upstream use of strncat, not based on GRUB needs but based on dangers
of strcat.
>  - replace c_isdigit with grub_isdigit (and don't import c-ctype from
>gnulib) grub_isdigit provides the same functionality as c_isdigit: it
>determines if the input is an ASCII digit without regard for locale.
Can we add c-ctype.h into posix compat?
>
>  - replace GL_ATTRIBUTE_PURE with __attribute__((pure)) which been
>supported since gcc-2.96. This avoids messing around with gnulib.
>
Why not add -DGL_ATTRIBUTE_PURE=... into cppflags? Or even to posix
wrap as long as we're not in gnulib? (e.g. #ifndef GNULIB ... #endif)
>  - adjust libtasn1.h: drop the ASN1_API logic, it's not needed for our
>modules. Unconditionally support const and pure attributes and adjust
>header paths.
Why not -DASN1_API= in cppflags?
const/pure logic seems ok as it was. Did you encounter any problems?>
  if (dest_tot_size > dest_size)
> {
> - strncat (dest, src, (dest_tot_size - dest_size) - 1);
> + memcpy (dest + dest_size, src, (dest_tot_size - dest_size) - 1);

Please add strncat into posix wrap instead. This is a bad change.

-- 
Regards
Vladimir 'phcoder' Serbinenko

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


Re: [PATCH v8 05/22] libtasn1: compile into asn1 module

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
LGTM
Reviewed-by: Vladimir Serbinenko 

Le mar. 16 janv. 2024, 12:22, Gary Lin via Grub-devel 
a écrit :

> From: Daniel Axtens 
>
> Create a wrapper file that specifies the module license.
> Set up the makefile so it is built.
>
> Signed-off-by: Daniel Axtens 
> Signed-off-by: Gary Lin 
> ---
>  grub-core/Makefile.core.def| 15 +++
>  grub-core/lib/libtasn1_wrap/wrap.c | 26 ++
>  2 files changed, 41 insertions(+)
>  create mode 100644 grub-core/lib/libtasn1_wrap/wrap.c
>
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 1571421d7..b1294e0f7 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -2595,3 +2595,18 @@ module = {
>efi = commands/bli.c;
>enable = efi;
>  };
> +
> +module = {
> +  name = asn1;
> +  common = lib/libtasn1/lib/decoding.c;
> +  common = lib/libtasn1/lib/coding.c;
> +  common = lib/libtasn1/lib/element.c;
> +  common = lib/libtasn1/lib/structure.c;
> +  common = lib/libtasn1/lib/parser_aux.c;
> +  common = lib/libtasn1/lib/gstr.c;
> +  common = lib/libtasn1/lib/errors.c;
> +  common = lib/libtasn1_wrap/wrap.c;
> +  cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
> +  // -Wno-type-limits comes from libtasn1's configure.ac
> +  cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)
> -I$(srcdir)/lib/libtasn1/lib -Wno-type-limits';
> +};
> diff --git a/grub-core/lib/libtasn1_wrap/wrap.c
> b/grub-core/lib/libtasn1_wrap/wrap.c
> new file mode 100644
> index 0..622ba942e
> --- /dev/null
> +++ b/grub-core/lib/libtasn1_wrap/wrap.c
> @@ -0,0 +1,26 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2020 IBM 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 
> +
> +/*
> + * libtasn1 is provided under LGPL2.1+, which is compatible
> + * with GPL3+. As Grub as a whole is under GPL3+, this module
> + * is therefore under GPL3+ also.
> + */
> +GRUB_MOD_LICENSE ("GPLv3+");
> --
> 2.35.3
>
>
> ___
> 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 v8 03/22] libtasn1: disable code not needed in grub

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
I would suggest something a bit more descriptive than if 0. What about
#ifdef GRUB_SKIPPED_IMPORTING ?

Le mar. 16 janv. 2024, 12:24, Gary Lin via Grub-devel 
a écrit :

> From: Daniel Axtens 
>
> We don't expect to be able to write ASN.1, only read it,
> so we can disable some code.
>
> Do that with #if 0/#endif, rather than deletion. This means
> that the difference between upstream and grub is smaller,
> which should make updating libtasn1 easier in the future.
>
> With these exclusions we also avoid the need for minmax.h,
> which is convenient because it means we don't have to
> import it from gnulib.
>
> Signed-off-by: Daniel Axtens 
> Signed-off-by: Gary Lin 
> ---
>  grub-core/lib/libtasn1/lib/coding.c| 12 ++--
>  grub-core/lib/libtasn1/lib/decoding.c  |  2 ++
>  grub-core/lib/libtasn1/lib/element.c   |  4 ++--
>  grub-core/lib/libtasn1/lib/errors.c|  3 +++
>  grub-core/lib/libtasn1/lib/structure.c | 10 ++
>  include/grub/libtasn1.h| 15 +++
>  6 files changed, 38 insertions(+), 8 deletions(-)
>
> diff --git a/grub-core/lib/libtasn1/lib/coding.c
> b/grub-core/lib/libtasn1/lib/coding.c
> index ea5bc370e..841fe47a9 100644
> --- a/grub-core/lib/libtasn1/lib/coding.c
> +++ b/grub-core/lib/libtasn1/lib/coding.c
> @@ -30,11 +30,11 @@
>  #include "parser_aux.h"
>  #include 
>  #include "element.h"
> -#include "minmax.h"
>  #include 
>
>  #define MAX_TAG_LEN 16
>
> +#if 0
>  /**/
>  /* Function : _asn1_error_description_value_not_found */
>  /* Description: creates the ErrorDescription string   */
> @@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
>Estrcat (ErrorDescription, "' not found");
>
>  }
> +#endif
>
>  /**
>   * asn1_length_der:
> @@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const
> unsigned char *str,
>return ASN1_SUCCESS;
>  }
>
> +#if 0
>  /**/
>  /* Function : _asn1_time_der  */
>  /* Description: creates the DER coding for a TIME */
> @@ -278,7 +280,7 @@ _asn1_time_der (unsigned char *str, int str_len,
> unsigned char *der,
>
>return ASN1_SUCCESS;
>  }
> -
> +#endif
>
>  /*
>  void
> @@ -519,6 +521,7 @@ asn1_bit_der (const unsigned char *str, int bit_len,
>  }
>
>
> +#if 0
>  /**/
>  /* Function : _asn1_complete_explicit_tag */
>  /* Description: add the length coding to the EXPLICIT */
> @@ -595,6 +598,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned
> char *der,
>
>return ASN1_SUCCESS;
>  }
> +#endif
>
>  const tag_and_class_st _asn1_tags[] = {
>[ASN1_ETYPE_GENERALSTRING] =
> @@ -647,6 +651,8 @@ const tag_and_class_st _asn1_tags[] = {
>
>  unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof
> (_asn1_tags[0]);
>
> +
> +#if 0
>  /**/
>  /* Function : _asn1_insert_tag_der*/
>  /* Description: creates the DER coding of tags of one */
> @@ -1423,3 +1429,5 @@ error:
>asn1_delete_structure ();
>return err;
>  }
> +
> +#endif
> \ No newline at end of file
> diff --git a/grub-core/lib/libtasn1/lib/decoding.c
> b/grub-core/lib/libtasn1/lib/decoding.c
> index b9245c486..92fc87c23 100644
> --- a/grub-core/lib/libtasn1/lib/decoding.c
> +++ b/grub-core/lib/libtasn1/lib/decoding.c
> @@ -1620,6 +1620,7 @@ asn1_der_decoding (asn1_node * element, const void
> *ider, int ider_len,
>return asn1_der_decoding2 (element, ider, _len, 0,
> errorDescription);
>  }
>
> +#if 0
>  /**
>   * asn1_der_decoding_element:
>   * @structure: pointer to an ASN1 structure
> @@ -1650,6 +1651,7 @@ asn1_der_decoding_element (asn1_node * structure,
> const char *elementName,
>  {
>return asn1_der_decoding (structure, ider, len, errorDescription);
>  }
> +#endif
>
>  /**
>   * asn1_der_decoding_startEnd:
> diff --git a/grub-core/lib/libtasn1/lib/element.c
> b/grub-core/lib/libtasn1/lib/element.c
> index d4c558e10..5c7941e53 100644
> --- a/grub-core/lib/libtasn1/lib/element.c
> +++ b/grub-core/lib/libtasn1/lib/element.c
> @@ -191,7 +191,7 @@ _asn1_append_sequence_set (asn1_node node, struct
> node_tail_cache_st *pcache)
>return ASN1_SUCCESS;
>  }
>
> -
> +#if 0
>  /**
>   * asn1_write_value:
>   * @node_root: pointer to a structure
> @@ -646,7 +646,7 @@ asn1_write_value (asn1_node node_root, const char
> *name,
>
>return ASN1_SUCCESS;
>  }
> -
> +#endif
>
>  #define PUT_VALUE( ptr, ptr_size, data, data_size) \
> *len = data_size; \
> diff --git a/grub-core/lib/libtasn1/lib/errors.c
> b/grub-core/lib/libtasn1/lib/errors.c
> index aef5dfe6f..0175ddedb 100644
> --- a/grub-core/lib/libtasn1/lib/errors.c
> +++ b/grub-core/lib/libtasn1/lib/errors.c
> @@ -57,6 +57,8 @@ static const libtasn1_error_entry error_algorithms[] = {
>{0, 0}
>  };
>
> +
> +#if 0
>  /**
>   * asn1_perror:
>   * @error: is an error 

Re: [PATCH v8 01/22] posix_wrap: tweaks in preparation for libtasn1

2024-01-16 Thread Vladimir 'phcoder' Serbinenko
LGTM
Reviewed-by: Vladimir Serbinenko 

On Tue, Jan 16, 2024 at 12:22 PM Gary Lin via Grub-devel
 wrote:
>
> From: Daniel Axtens 
>
>  - Define SIZEOF_UNSIGNED_LONG_INT, it's the same as
>SIZEOF_UNSIGNED_LONG.
>
>  - Define WORD_BIT, the size in bits of an int. This is a defined
>in the Single Unix Specification and in gnulib's limits.h. gnulib
>assumes it's 32 bits on all our platforms, including 64 bit
>platforms, so we also use that value.
>
>  - Provide strto[u]l[l] preprocessor macros that resolve to
>grub_strto[u]l[l]. To avoid gcrypt redefining strtoul, we
>also define HAVE_STRTOUL here.
>
> Signed-off-by: Daniel Axtens 
> Signed-off-by: Gary Lin 
> ---
>  grub-core/lib/posix_wrap/limits.h| 1 +
>  grub-core/lib/posix_wrap/stdlib.h| 8 
>  grub-core/lib/posix_wrap/sys/types.h | 1 +
>  3 files changed, 10 insertions(+)
>
> diff --git a/grub-core/lib/posix_wrap/limits.h 
> b/grub-core/lib/posix_wrap/limits.h
> index 26918c8a0..4be7b4080 100644
> --- a/grub-core/lib/posix_wrap/limits.h
> +++ b/grub-core/lib/posix_wrap/limits.h
> @@ -41,5 +41,6 @@
>  #define LONG_MAX GRUB_LONG_MAX
>
>  #define CHAR_BIT 8
> +#define WORD_BIT 32
>
>  #endif
> diff --git a/grub-core/lib/posix_wrap/stdlib.h 
> b/grub-core/lib/posix_wrap/stdlib.h
> index f5279756a..14e4efdd0 100644
> --- a/grub-core/lib/posix_wrap/stdlib.h
> +++ b/grub-core/lib/posix_wrap/stdlib.h
> @@ -64,4 +64,12 @@ abort (void)
>grub_abort ();
>  }
>
> +#define strtol grub_strtol
> +
> +/* for libgcrypt */
> +#define HAVE_STRTOUL
> +#define strtoul grub_strtoul
> +
> +#define strtoull grub_strtoull
> +
>  #endif
> diff --git a/grub-core/lib/posix_wrap/sys/types.h 
> b/grub-core/lib/posix_wrap/sys/types.h
> index eeda543c4..2f3e86549 100644
> --- a/grub-core/lib/posix_wrap/sys/types.h
> +++ b/grub-core/lib/posix_wrap/sys/types.h
> @@ -50,6 +50,7 @@ typedef grub_uint8_t byte;
>  typedef grub_addr_t uintptr_t;
>
>  #define SIZEOF_UNSIGNED_LONG GRUB_CPU_SIZEOF_LONG
> +#define SIZEOF_UNSIGNED_LONG_INT GRUB_CPU_SIZEOF_LONG
>  #define SIZEOF_UNSIGNED_INT 4
>  #define SIZEOF_UNSIGNED_LONG_LONG 8
>  #define SIZEOF_UNSIGNED_SHORT 2
> --
> 2.35.3
>
>
> ___
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



-- 
Regards
Vladimir 'phcoder' Serbinenko

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


Re: [PATCH v8 16/22] tpm2: Support authorized policy

2024-01-16 Thread James Bottomley
On Tue, 2024-01-16 at 17:20 +0800, Gary Lin via Grub-devel wrote:
[...]
> (*1) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
> (*2) https://github.com/okirch/pcr-oracle

Just a curiosity question, but have you tested the interoperability of
pcr-oracle keys?  It looks like you got the ASN header straight from
openssl_tpm2_engine, so it should all just work, but verifying that the
seal/unseal and sign_tpm2_policy commands from openssl_tpm2_engine:

https://build.opensuse.org/package/show/security:tls/openssl_tpm2_engine

can be used to create sealed keys for this code would nicely verify
that.

James


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


Re: Strange failure during de_CH.po generation with make -j

2024-01-16 Thread Steve McIntyre
Hi!

On Sun, Jan 14, 2024 at 03:58:42PM +0800, Xinhui Yang via Grub-devel wrote:
>
>Recently we observed a strange failure while packaging GRUB 2.12 for
>our distro. The translation file generation process might fail if
>parallelism was enabled (e.g. `make -j', or with `-j16' and larger
>numbers).
>
>We found that the build always failed whilst generating de_CH
>translation data from de.po, complaining about syntax errors or a
>premature EOF whilst processing the strings. The exact line numbers
>msgfilter complained about were random. If we remove de_CH from
>linguas.sh, the build passes every time, even with parallelism
>enabled - of course, with parallelism disabled, we did not observe
>this issue.
>
>This issue has been reproduced on:
>
>- AOSC OS, the aforementioned distro that I work on.
>- Debian Bookworm.
>
>I propose the following solutions:
>
>- Tell the distro maintainers not to use -j.
>- Patch po/gettext-patches to add a .NOTPARALLEL directive in Makefile.in.in.
>
>We have opted to temporarily disable parallelism in po/Makefile, since we
>could not find the culprit to this issue.

I've seen this before when hacking on the Debian packaging too. IIRC
it's because the po build does not use separated-out build dirs like
the binary builds, and that would the right way to fix this.

-- 
Steve McIntyre, Cambridge, UK.st...@einval.com
"The problem with defending the purity of the English language is that
 English is about as pure as a cribhouse whore. We don't just borrow words; on
 occasion, English has pursued other languages down alleyways to beat them
 unconscious and rifle their pockets for new vocabulary."  -- James D. Nicoll


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


[PATCH v8 20/22] diskfilter: look up cryptodisk devices first

2024-01-16 Thread Gary Lin via Grub-devel
When using disk auto-unlocking with TPM 2.0, the typical grub.cfg may
look like this:

  tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
  cryptomount -u  -P tpm2
  search --fs-uuid --set=root 

Since the disk search order is based on the order of module loading, the
attacker could insert a malicious disk with the same FS-UUID root to
trick grub2 to boot into th malicious root and further dump memory to
steal the unsealed key.

To defend such attack, we can specify the hint provided by 'grub-probe'
to search the encrypted partition first:

search --fs-uuid --set=root --hint='cryptouuid/' 

However, for LVM on a encrypted partition, the search hint provided by
'grub-probe' is:

  --hint='lvmid//'

It doesn't guarantee to look up the logical volume from the encrypted
partition, so the attacker may have the chance to fool grub2 to boot
into the malicious disk.

To mininize the attack surface, this commit tweaks the disk device search
in diskfilter to look up cryptodisk devices first and then others, so
that the auto-unlocked disk will be found first, not the attacker's disk.

Signed-off-by: Gary Lin 
Cc: Fabian Vogt 
---
 grub-core/disk/diskfilter.c | 35 ++-
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 21e239511..df1992305 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -226,15 +226,32 @@ scan_devices (const char *arname)
   int need_rescan;
 
   for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
-for (p = grub_disk_dev_list; p; p = p->next)
-  if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
- && p->disk_iterate)
-   {
- if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
-   return;
- if (arname && is_lv_readable (find_lv (arname), 1))
-   return;
-   }
+{
+  /* look up the crytodisk devices first */
+  for (p = grub_disk_dev_list; p; p = p->next)
+   if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID
+   && p->disk_iterate)
+ {
+   if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
+ return;
+   if (arname && is_lv_readable (find_lv (arname), 1))
+ return;
+   break;
+ }
+
+  /* check the devices other than crytodisk */
+  for (p = grub_disk_dev_list; p; p = p->next)
+   if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ continue;
+   else if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
+   && p->disk_iterate)
+ {
+   if ((p->disk_iterate) (scan_disk_hook, NULL, pull))
+ return;
+   if (arname && is_lv_readable (find_lv (arname), 1))
+ return;
+ }
+}
 
   scan_depth = 0;
   need_rescan = 1;
-- 
2.35.3


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


[PATCH v8 03/22] libtasn1: disable code not needed in grub

2024-01-16 Thread Gary Lin via Grub-devel
From: Daniel Axtens 

We don't expect to be able to write ASN.1, only read it,
so we can disable some code.

Do that with #if 0/#endif, rather than deletion. This means
that the difference between upstream and grub is smaller,
which should make updating libtasn1 easier in the future.

With these exclusions we also avoid the need for minmax.h,
which is convenient because it means we don't have to
import it from gnulib.

Signed-off-by: Daniel Axtens 
Signed-off-by: Gary Lin 
---
 grub-core/lib/libtasn1/lib/coding.c| 12 ++--
 grub-core/lib/libtasn1/lib/decoding.c  |  2 ++
 grub-core/lib/libtasn1/lib/element.c   |  4 ++--
 grub-core/lib/libtasn1/lib/errors.c|  3 +++
 grub-core/lib/libtasn1/lib/structure.c | 10 ++
 include/grub/libtasn1.h| 15 +++
 6 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/grub-core/lib/libtasn1/lib/coding.c 
b/grub-core/lib/libtasn1/lib/coding.c
index ea5bc370e..841fe47a9 100644
--- a/grub-core/lib/libtasn1/lib/coding.c
+++ b/grub-core/lib/libtasn1/lib/coding.c
@@ -30,11 +30,11 @@
 #include "parser_aux.h"
 #include 
 #include "element.h"
-#include "minmax.h"
 #include 
 
 #define MAX_TAG_LEN 16
 
+#if 0
 /**/
 /* Function : _asn1_error_description_value_not_found */
 /* Description: creates the ErrorDescription string   */
@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
   Estrcat (ErrorDescription, "' not found");
 
 }
+#endif
 
 /**
  * asn1_length_der:
@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned 
char *str,
   return ASN1_SUCCESS;
 }
 
+#if 0
 /**/
 /* Function : _asn1_time_der  */
 /* Description: creates the DER coding for a TIME */
@@ -278,7 +280,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned 
char *der,
 
   return ASN1_SUCCESS;
 }
-
+#endif
 
 /*
 void
@@ -519,6 +521,7 @@ asn1_bit_der (const unsigned char *str, int bit_len,
 }
 
 
+#if 0
 /**/
 /* Function : _asn1_complete_explicit_tag */
 /* Description: add the length coding to the EXPLICIT */
@@ -595,6 +598,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char 
*der,
 
   return ASN1_SUCCESS;
 }
+#endif
 
 const tag_and_class_st _asn1_tags[] = {
   [ASN1_ETYPE_GENERALSTRING] =
@@ -647,6 +651,8 @@ const tag_and_class_st _asn1_tags[] = {
 
 unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
 
+
+#if 0
 /**/
 /* Function : _asn1_insert_tag_der*/
 /* Description: creates the DER coding of tags of one */
@@ -1423,3 +1429,5 @@ error:
   asn1_delete_structure ();
   return err;
 }
+
+#endif
\ No newline at end of file
diff --git a/grub-core/lib/libtasn1/lib/decoding.c 
b/grub-core/lib/libtasn1/lib/decoding.c
index b9245c486..92fc87c23 100644
--- a/grub-core/lib/libtasn1/lib/decoding.c
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -1620,6 +1620,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int ider_len,
   return asn1_der_decoding2 (element, ider, _len, 0, errorDescription);
 }
 
+#if 0
 /**
  * asn1_der_decoding_element:
  * @structure: pointer to an ASN1 structure
@@ -1650,6 +1651,7 @@ asn1_der_decoding_element (asn1_node * structure, const 
char *elementName,
 {
   return asn1_der_decoding (structure, ider, len, errorDescription);
 }
+#endif
 
 /**
  * asn1_der_decoding_startEnd:
diff --git a/grub-core/lib/libtasn1/lib/element.c 
b/grub-core/lib/libtasn1/lib/element.c
index d4c558e10..5c7941e53 100644
--- a/grub-core/lib/libtasn1/lib/element.c
+++ b/grub-core/lib/libtasn1/lib/element.c
@@ -191,7 +191,7 @@ _asn1_append_sequence_set (asn1_node node, struct 
node_tail_cache_st *pcache)
   return ASN1_SUCCESS;
 }
 
-
+#if 0
 /**
  * asn1_write_value:
  * @node_root: pointer to a structure
@@ -646,7 +646,7 @@ asn1_write_value (asn1_node node_root, const char *name,
 
   return ASN1_SUCCESS;
 }
-
+#endif
 
 #define PUT_VALUE( ptr, ptr_size, data, data_size) \
*len = data_size; \
diff --git a/grub-core/lib/libtasn1/lib/errors.c 
b/grub-core/lib/libtasn1/lib/errors.c
index aef5dfe6f..0175ddedb 100644
--- a/grub-core/lib/libtasn1/lib/errors.c
+++ b/grub-core/lib/libtasn1/lib/errors.c
@@ -57,6 +57,8 @@ static const libtasn1_error_entry error_algorithms[] = {
   {0, 0}
 };
 
+
+#if 0
 /**
  * asn1_perror:
  * @error: is an error returned by a libtasn1 function.
@@ -73,6 +75,7 @@ asn1_perror (int error)
   const char *str = asn1_strerror (error);
   fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)");
 }
+#endif
 
 /**
  * asn1_strerror:
diff --git a/grub-core/lib/libtasn1/lib/structure.c 
b/grub-core/lib/libtasn1/lib/structure.c
index 512dd601f..3e1e35ba5 100644
--- a/grub-core/lib/libtasn1/lib/structure.c
+++ b/grub-core/lib/libtasn1/lib/structure.c
@@ -76,7 

[PATCH v8 22/22] tests: Add tpm2_test

2024-01-16 Thread Gary Lin via Grub-devel
For TPM 2.0 TSS stack, the TCG2 command sending function is the only
difference between the a QEMU instance and grub-emu. To test TPM key
unsealing with a QEMU instance, it requires an extra OS image to invoke
grub-protect to seal the LUKS key, not only a simple grub-shell rescue
CD image. On the other hand, grub-emu can share the emulated TPM device
with the host, so that we can seal the LUKS key on host and test key
unsealing with grub-emu.

This test script firstly creates a simple LUKS image to be loaded as a
loopback device in grub-emu. Then an emulated TPM device is created by
swtpm_cuse and PCR 0 and 1 are extended. The LUKS password is sealed by
grub-protect against PCR 0 and 1. The last step is to launch grub-emu to
load the LUKS image, try to mount the image with tpm2_key_protector_init
and cryptomount, and verify the result.

Based on the idea from Michael Chang.

Cc: Michael Chang 
Signed-off-by: Gary Lin 
---
 Makefile.util.def|   6 ++
 tests/tpm2_test.in   | 179 +++
 tests/util/grub-shell.in |   6 +-
 3 files changed, 190 insertions(+), 1 deletion(-)
 create mode 100644 tests/tpm2_test.in

diff --git a/Makefile.util.def b/Makefile.util.def
index 89ceeec0e..dd6c18f76 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -1279,6 +1279,12 @@ script = {
   common = tests/test_asn1.in;
 };
 
+script = {
+  testcase = native;
+  name = tpm2_test;
+  common = tests/tpm2_test.in;
+};
+
 program = {
   testcase = native;
   name = example_unit_test;
diff --git a/tests/tpm2_test.in b/tests/tpm2_test.in
new file mode 100644
index 0..8edc49780
--- /dev/null
+++ b/tests/tpm2_test.in
@@ -0,0 +1,179 @@
+#! @BUILD_SHEBANG@ -e
+
+# Test GRUBs ability to unseal a LUKS key with TPM 2.0
+# Copyright (C) 2024  Free Software Foundation, Inc.
+#
+# GRUB is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# GRUB is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GRUB.  If not, see .
+
+grubshell=@builddir@/grub-shell
+
+. "@builddir@/grub-core/modinfo.sh"
+
+if [ x$grub_modinfo_platform != xemu ]; then
+  exit 77
+fi
+
+builddir="@builddir@"
+
+# Force build directory components
+PATH="${builddir}:$PATH"
+export PATH
+
+if [ "x$EUID" = "x" ] ; then
+  EUID=`id -u`
+fi
+
+if [ "$EUID" != 0 ] ; then
+   echo "not root; cannot test tpm2."
+   exit 99
+fi
+
+if ! which cryptsetup >/dev/null 2>&1; then
+   echo "cryptsetup not installed; cannot test tpm2."
+   exit 99
+fi
+
+if ! which swtpm >/dev/null 2>&1; then
+   echo "swtpm not installed; cannot test tpm2."
+   exit 99
+fi
+
+if ! which tpm2_startup >/dev/null 2>&1; then
+   echo "tpm2-tools not installed; cannot test tpm2."
+   exit 99
+fi
+
+tpm2testdir="`mktemp -d "${TMPDIR:-/tmp}/$(basename "$0").XX"`" || 
exit 20
+
+disksize=20M
+
+luksfile=$tpm2testdir/luks.disk
+lukskeyfile=${tpm2testdir}/password.txt
+
+# Choose a low iteration number to reduce the time to decrypt the disk
+csopt="--type luks2 --pbkdf pbkdf2 --iter-time 1000"
+
+tpm2devname="vtpm-test0"
+tpm2statedir=${tpm2testdir}/tpm
+tpm2dev="/dev/${tpm2devname}"
+
+sealedkey=${tpm2testdir}/sealed.tpm
+
+timeout=20
+
+testoutput=$tpm2testdir/testoutput
+
+vtext="TEST VERIFIED"
+
+# Create the password file
+echo -n "top secret" > ${lukskeyfile}
+
+# Setup LUKS2 image
+truncate -s ${disksize} ${luksfile} || exit 21
+cryptsetup luksFormat -q ${csopt} ${luksfile} ${lukskeyfile} || exit 22
+
+# Shutdown the swtpm instance on exit
+cleanup() {
+if [ -e "$tpm2dev" ]; then
+swtpm_ioctl -s ${tpm2dev}
+fi
+if [ "${RET:-1}" -eq 0 ]; then
+rm -rf "$tpm2testdir" || :
+fi
+}
+trap cleanup EXIT INT TERM KILL QUIT
+
+# Shutdown the previous swtpm instance if exists
+if [ -c "${tpm2dev}" ]; then
+swtpm_ioctl -s ${tpm2dev}
+fi
+
+# Create the swtpm cuse instannce
+swtpm_cuse -n ${tpm2devname} --tpm2 --tpmstate dir=${tpm2statedir}
+ret=$?
+if [ "$ret" -ne 0 ]; then
+exit $ret
+fi
+
+# Initialize swtpm device
+swtpm_ioctl -i ${tpm2dev}
+ret=$?
+if [ "$ret" -ne 0 ]; then
+exit $ret
+fi
+
+# Export the TCTI variable for tpm2-tools
+export TPM2TOOLS_TCTI="device:${tpm2dev}"
+
+# Send the startup command
+tpm2_startup -c
+ret=$?
+if [ "$ret" -ne 0 ]; then
+exit $ret
+fi
+
+# Extend PCR 0
+tpm2_pcrextend 0:sha256=$(sha256sum <<< "test0" | cut -d ' ' -f 1)
+ret=$?
+if [ "$ret" -ne 0 ]; then
+exit $ret
+fi
+
+# Extend PCR 1
+tpm2_pcrextend 1:sha256=$(sha256sum <<< "test1" | cut -d ' ' -f 1)
+ret=$?
+if [ "$ret" -ne 0 ]; then
+exit 

[PATCH v8 10/22] protectors: Add TPM2 Key Protector

2024-01-16 Thread Gary Lin via Grub-devel
From: 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/tpm2key parameter, which
is mandatory. There are two supported key formats:

1. Raw Sealed Key (--keyfile)
   When sealing a key with TPM2_Create, the public portion of the sealed
   key is stored in TPM2B_PUBLIC, and the private portion is in
   TPM2B_PRIVATE. The raw sealed key glues the fully marshalled
   TPM2B_PUBLIC and TPM2B_PRIVATE into one file.

2. TPM 2.0 Key (--tpm2key)
   The following is the ASN.1 definition of TPM 2.0 Key File:

   TPMPolicy ::= SEQUENCE {
 CommandCode   [0] EXPLICIT INTEGER
 CommandPolicy [1] EXPLICIT OCTET STRING
   }

   TPMAuthPolicy ::= SEQUENCE {
 Name[0] EXPLICIT UTF8STRING OPTIONAL
 Policy  [1] EXPLICIT SEQUENCE OF TPMPolicy
   }

   TPMKey ::= SEQUENCE {
 typeOBJECT IDENTIFIER
 emptyAuth   [0] EXPLICIT BOOLEAN OPTIONAL
 policy  [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL
 secret  [2] EXPLICIT OCTET STRING OPTIONAL
 authPolicy  [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL
 parent  INTEGER
 pubkey  OCTET STRING
 privkey OCTET STRING
   }

  The TPM2 key protector only expects a "sealed" key in DER encoding,
  so 'type' is always 2.23.133.10.1.5, 'emptyAuth' is 'TRUE', and
  'secret' is empty. 'policy' and 'authPolicy' are the possible policy
  command sequences to construst the policy digest to unseal the key.
  Similar to the raw sealed key, the public portion (TPM2B_PUBLIC) of
  the sealed key is stored in 'pubkey', and the private portion
  (TPM2B_PRIVATE) is in 'privkey'.

  For more details: 
https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html

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/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, to unseal the raw sealed key file:

tpm2_key_protector_init --keyfile=(hd0,gpt1)/efi/grub2/sealed-1.key
cryptomount -u  -P tpm2

tpm2_key_protector_init --keyfile=(hd0,gpt1)/efi/grub2/sealed-2.key --pcrs=7,11
cryptomount -u  -P tpm2

Or, to unseal the TPM 2.0 Key file:

tpm2_key_protector_init --tpm2key=(hd0,gpt1)/efi/grub2/sealed-1.tpm
cryptomount -u  -P tpm2

tpm2_key_protector_init --tpm2key=(hd0,gpt1)/efi/grub2/sealed-2.tpm --pcrs=7,11
cryptomount -u  -P tpm2

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

Before unsealing the key, the TPM2 key protector follows the "TPMPolicy"
sequences to enforce the TPM policy commands to construct a valid policy
digest to unseal the key.

For the TPM 2.0 Key files, 'authPolicy' may contain multiple "TPMPolicy"
sequences, the TPM2 key protector iterates 'authPolicy' to find a valid
sequence to unseal key. If 'authPolicy' is empty or all sequences in
'authPolicy' fail, the protector tries the one from 'policy'. In case
'policy' is also empty, the protector creates a "TPMPolicy" sequence
based on the given PCR selection.

For the raw sealed key, the TPM2 key protector treats the key file as a
TPM 2.0 Key file without 'authPolicy' and 'policy', so the "TPMPolicy"
sequence is always based on the PCR selection from the command
parameters.

Currently, there is only one supported policy command: TPM2_PolicyPCR.
The command set can be extended to support advanced features, such as
authorized policy, in the future.

Signed-off-by: Hernan Gatta 
Signed-off-by: Gary Lin 
---
 grub-core/Makefile.core.def   |   13 +
 grub-core/tpm2/args.c |  177 +
 grub-core/tpm2/module.c   | 1028 +
 grub-core/tpm2/tpm2key.asn|   31 +
 grub-core/tpm2/tpm2key.c  |  447 +
 grub-core/tpm2/tpm2key_asn1_tab.c 

[PATCH v8 18/22] cryptodisk: Fallback to passphrase

2024-01-16 Thread Gary Lin via Grub-devel
From: Patrick Colp 

If a protector is specified, but it fails to unlock the disk, fall back
to asking for the passphrase. However, an error was set indicating that
the protector(s) failed. Later code (e.g., LUKS code) fails as
`grub_errno` is now set. Print the existing errors out first, before
proceeding with the passphrase.

Signed-off-by: Patrick Colp 
Signed-off-by: Gary Lin 
---
 grub-core/disk/cryptodisk.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index dba5efa61..bbb9a56b5 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1191,11 +1191,16 @@ grub_cryptodisk_scan_device_real (const char *name,
  source->name, source->partition != NULL ? "," : "",
  part != NULL ? part : N_("UNKNOWN"), dev->uuid);
   grub_free (part);
-  goto error;
 }
 
   if (!cargs->key_len)
 {
+  if (grub_errno)
+   {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+   }
+
   /* Get the passphrase from the user, if no key data. */
   askpass = 1;
   part = grub_partition_get_name (source->partition);
-- 
2.35.3


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


[PATCH v8 07/22] libtasn1: Add the documentation

2024-01-16 Thread Gary Lin via Grub-devel
Document libtasn1 in docs/grub-dev.texi and add the upgrade steps.
Also add the patches to make libtasn1 compatible with grub code.

Signed-off-by: Gary Lin 
---
 docs/grub-dev.texi|  27 ++
 ...asn1-disable-code-not-needed-in-grub.patch | 311 ++
 ...tasn1-changes-for-grub-compatibility.patch | 209 
 3 files changed, 547 insertions(+)
 create mode 100644 
grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
 create mode 100644 
grub-core/lib/libtasn1-patches/0002-libtasn1-changes-for-grub-compatibility.patch

diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index 1276c5930..80c6f6738 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -596,6 +596,33 @@ cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
 rm -r minilzo-2.10*
 @end example
 
+@node libtasn1
+@section libtasn1
+
+libtasn1 is a library providing Abstract Syntax Notation One (ASN.1, as
+specified by the X.680 ITU-T recommendation) parsing and structures management,
+and Distinguished Encoding Rules (DER, as per X.690) encoding and decoding
+functions.
+
+To upgrade to a new version of the libtasn1 library, download the release
+tarball and copy the files into the target directory:
+
+@example
+curl -L -O https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.19.0.tar.gz
+tar -zxf libtasn1-4.19.0.tar.gz
+rm -r grub-core/lib/libtasn1/
+mkdir libtasn1/lib
+mkdir -p grub-core/lib/libtasn1/lib/
+cp libtasn1-4.19.0/{README.md,COPYING} grub-core/lib/libtasn1/
+cp 
libtasn1-4.19.0/lib/{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h}
 grub-core/lib/libtasn1/lib/
+cp libtasn1-4.19.0/lib/includes/libtasn1.h include/grub/
+rm -rf libtasn1-4.19.0
+@end example
+
+After upgrading the library, it is necessary to apply the patches in
+@file{grub-core/lib/libtasn1-patches/} to adjust the code to be compatible with
+grub.
+
 @node Debugging
 @chapter Debugging
 
diff --git 
a/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
 
b/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
new file mode 100644
index 0..4f116dda5
--- /dev/null
+++ 
b/grub-core/lib/libtasn1-patches/0001-libtasn1-disable-code-not-needed-in-grub.patch
@@ -0,0 +1,311 @@
+From c1c3459159d5d84e0d6da6eec6b86df5ccee1417 Mon Sep 17 00:00:00 2001
+From: Daniel Axtens 
+Date: Fri, 1 May 2020 17:12:23 +1000
+Subject: [PATCH 1/2] libtasn1: disable code not needed in grub
+
+We don't expect to be able to write ASN.1, only read it,
+so we can disable some code.
+
+Do that with #if 0/#endif, rather than deletion. This means
+that the difference between upstream and grub is smaller,
+which should make updating libtasn1 easier in the future.
+
+With these exclusions we also avoid the need for minmax.h,
+which is convenient because it means we don't have to
+import it from gnulib.
+
+Signed-off-by: Daniel Axtens 
+Signed-off-by: Gary Lin 
+---
+ grub-core/lib/libtasn1/lib/coding.c| 12 ++--
+ grub-core/lib/libtasn1/lib/decoding.c  |  2 ++
+ grub-core/lib/libtasn1/lib/element.c   |  4 ++--
+ grub-core/lib/libtasn1/lib/errors.c|  3 +++
+ grub-core/lib/libtasn1/lib/structure.c | 10 ++
+ include/grub/libtasn1.h| 15 +++
+ 6 files changed, 38 insertions(+), 8 deletions(-)
+
+diff --git a/grub-core/lib/libtasn1/lib/coding.c 
b/grub-core/lib/libtasn1/lib/coding.c
+index ea5bc370e..841fe47a9 100644
+--- a/grub-core/lib/libtasn1/lib/coding.c
 b/grub-core/lib/libtasn1/lib/coding.c
+@@ -30,11 +30,11 @@
+ #include "parser_aux.h"
+ #include 
+ #include "element.h"
+-#include "minmax.h"
+ #include 
+ 
+ #define MAX_TAG_LEN 16
+ 
++#if 0
+ /**/
+ /* Function : _asn1_error_description_value_not_found */
+ /* Description: creates the ErrorDescription string   */
+@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
+   Estrcat (ErrorDescription, "' not found");
+ 
+ }
++#endif
+ 
+ /**
+  * asn1_length_der:
+@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned 
char *str,
+   return ASN1_SUCCESS;
+ }
+ 
++#if 0
+ /**/
+ /* Function : _asn1_time_der  */
+ /* Description: creates the DER coding for a TIME */
+@@ -278,7 +280,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned 
char *der,
+ 
+   return ASN1_SUCCESS;
+ }
+-
++#endif
+ 
+ /*
+ void
+@@ -519,6 +521,7 @@ asn1_bit_der (const unsigned char *str, int bit_len,
+ }
+ 
+ 
++#if 0
+ /**/
+ /* Function : _asn1_complete_explicit_tag */
+ /* Description: add the length coding to the EXPLICIT */
+@@ -595,6 +598,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char 
*der,
+ 
+   return ASN1_SUCCESS;
+ }
++#endif
+ 
+ const tag_and_class_st 

[PATCH v8 04/22] libtasn1: changes for grub compatibility

2024-01-16 Thread Gary Lin via Grub-devel
From: Daniel Axtens 

Do a few things to make libtasn1 compile as part of grub:

 - redefine _asn1_strcat. grub removed strcat so replace it with the
   appropriate calls to memcpy and strlen. Use this internally where
   strcat was used.

 - replace c_isdigit with grub_isdigit (and don't import c-ctype from
   gnulib) grub_isdigit provides the same functionality as c_isdigit: it
   determines if the input is an ASCII digit without regard for locale.

 - replace GL_ATTRIBUTE_PURE with __attribute__((pure)) which been
   supported since gcc-2.96. This avoids messing around with gnulib.

 - adjust libtasn1.h: drop the ASN1_API logic, it's not needed for our
   modules. Unconditionally support const and pure attributes and adjust
   header paths.

 - adjust header paths to "grub/libtasn1.h".

 - replace a 64 bit division with a call to grub_divmod64, preventing
   creation of __udivdi3 calls on 32 bit platforms.

Signed-off-by: Daniel Axtens 
Signed-off-by: Gary Lin 
---
 grub-core/lib/libtasn1/lib/decoding.c   | 11 +-
 grub-core/lib/libtasn1/lib/element.c|  3 ++-
 grub-core/lib/libtasn1/lib/gstr.c   |  4 ++--
 grub-core/lib/libtasn1/lib/int.h|  4 ++--
 grub-core/lib/libtasn1/lib/parser_aux.c |  7 +++---
 include/grub/libtasn1.h | 29 +++--
 6 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/grub-core/lib/libtasn1/lib/decoding.c 
b/grub-core/lib/libtasn1/lib/decoding.c
index 92fc87c23..4fd5f0ce6 100644
--- a/grub-core/lib/libtasn1/lib/decoding.c
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -32,7 +32,8 @@
 #include 
 #include 
 #include 
-#include "c-ctype.h"
+
+#define c_isdigit grub_isdigit
 
 #ifdef DEBUG
 # define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
@@ -2016,8 +2017,8 @@ asn1_expand_octet_string (asn1_node_const definitions, 
asn1_node * element,
  (p2->type & CONST_ASSIGN))
{
  strcpy (name, definitions->name);
- strcat (name, ".");
- strcat (name, p2->name);
+ _asn1_strcat (name, ".");
+ _asn1_strcat (name, p2->name);
 
  len = sizeof (value);
  result = asn1_read_value (definitions, name, value, );
@@ -2034,8 +2035,8 @@ asn1_expand_octet_string (asn1_node_const definitions, 
asn1_node * element,
  if (p2)
{
  strcpy (name, definitions->name);
- strcat (name, ".");
- strcat (name, p2->name);
+ _asn1_strcat (name, ".");
+ _asn1_strcat (name, p2->name);
 
  result = asn1_create_element (definitions, name, );
  if (result == ASN1_SUCCESS)
diff --git a/grub-core/lib/libtasn1/lib/element.c 
b/grub-core/lib/libtasn1/lib/element.c
index 5c7941e53..822a1b6ab 100644
--- a/grub-core/lib/libtasn1/lib/element.c
+++ b/grub-core/lib/libtasn1/lib/element.c
@@ -30,9 +30,10 @@
 #include "parser_aux.h"
 #include 
 #include "structure.h"
-#include "c-ctype.h"
 #include "element.h"
 
+#define c_isdigit grub_isdigit
+
 void
 _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size)
 {
diff --git a/grub-core/lib/libtasn1/lib/gstr.c 
b/grub-core/lib/libtasn1/lib/gstr.c
index eef419554..bc507d3d8 100644
--- a/grub-core/lib/libtasn1/lib/gstr.c
+++ b/grub-core/lib/libtasn1/lib/gstr.c
@@ -36,13 +36,13 @@ _asn1_str_cat (char *dest, size_t dest_tot_size, const char 
*src)
 
   if (dest_tot_size - dest_size > str_size)
 {
-  strcat (dest, src);
+  _asn1_strcat (dest, src);
 }
   else
 {
   if (dest_tot_size > dest_size)
{
- strncat (dest, src, (dest_tot_size - dest_size) - 1);
+ memcpy (dest + dest_size, src, (dest_tot_size - dest_size) - 1);
  dest[dest_tot_size - 1] = 0;
}
 }
diff --git a/grub-core/lib/libtasn1/lib/int.h b/grub-core/lib/libtasn1/lib/int.h
index d94d51c8c..07dd669ac 100644
--- a/grub-core/lib/libtasn1/lib/int.h
+++ b/grub-core/lib/libtasn1/lib/int.h
@@ -35,7 +35,7 @@
 #  include 
 # endif
 
-# include 
+# include "grub/libtasn1.h"
 
 # define ASN1_SMALL_VALUE_SIZE 16
 
@@ -115,7 +115,7 @@ extern const tag_and_class_st _asn1_tags[];
 # define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b)
 # define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b)
 # define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b)
-# define _asn1_strcat(a,b) strcat((char *)a, (const char *)b)
+# define _asn1_strcat(a,b) memcpy((char *)a + strlen((const char *)a), (const 
char *)b, strlen((const char *)b) + 1)
 
 # if SIZEOF_UNSIGNED_LONG_INT == 8
 #  define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b)
diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c 
b/grub-core/lib/libtasn1/lib/parser_aux.c
index c05bd2339..8bdc42ae3 100644
--- a/grub-core/lib/libtasn1/lib/parser_aux.c
+++ b/grub-core/lib/libtasn1/lib/parser_aux.c
@@ -26,7 +26,8 @@
 #include "gstr.h"
 #include "structure.h"
 #include "element.h"
-#include "c-ctype.h"
+

[PATCH v8 21/22] tpm2: Enable tpm2 module for grub-emu

2024-01-16 Thread Gary Lin via Grub-devel
As a preparation to test TPM 2.0 TSS stack with grub-emu, the new
option, --tpm-device, is introduced to specify the TPM device for
grub-emu so that grub-emu can share the emulated TPM device with
the host.

Since grub-emu can directly access the device node on host, it's easy to
implement the essential TCG2 command with the standard read/write
functions and enable the commands from tpm2 module for grub-emu, so that
we can further test TPM key unsealing with grub-emu.

Signed-off-by: Gary Lin 
---
 grub-core/Makefile.core.def |  2 ++
 grub-core/kern/emu/main.c   | 11 +++-
 grub-core/kern/emu/misc.c   | 51 
 grub-core/tpm2/tcg2-emu.c   | 52 +
 include/grub/emu/misc.h |  5 
 5 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/tpm2/tcg2-emu.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 560d65590..77fde4313 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2563,7 +2563,9 @@ module = {
   common = tpm2/tpm2key.c;
   common = tpm2/tpm2key_asn1_tab.c;
   efi = tpm2/tcg2.c;
+  emu = tpm2/tcg2-emu.c;
   enable = efi;
+  enable = emu;
 };
 
 module = {
diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c
index 855b11c3d..c10838613 100644
--- a/grub-core/kern/emu/main.c
+++ b/grub-core/kern/emu/main.c
@@ -55,7 +55,7 @@
 static jmp_buf main_env;
 
 /* Store the prefix specified by an argument.  */
-static char *root_dev = NULL, *dir = NULL;
+static char *root_dev = NULL, *dir = NULL, *tpm_dev = NULL;
 
 grub_addr_t grub_modbase = 0;
 
@@ -108,6 +108,7 @@ static struct argp_option options[] = {
   {"verbose", 'v', 0,  0, N_("print verbose messages."), 0},
   {"hold", 'H', N_("SECS"),  OPTION_ARG_OPTIONAL, N_("wait until a 
debugger will attach"), 0},
   {"kexec",   'X', 0,  0, N_("use kexec to boot Linux kernels via 
systemctl (pass twice to enable dangerous fallback to non-systemctl)."), 0},
+  {"tpm-device",  't', N_("DEV"), 0, N_("Set TPM device."), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
 
@@ -168,6 +169,10 @@ argp_parser (int key, char *arg, struct argp_state *state)
 case 'X':
   grub_util_set_kexecute ();
   break;
+case 't':
+  free (tpm_dev);
+  tpm_dev = xstrdup (arg);
+  break;
 
 case ARGP_KEY_ARG:
   {
@@ -276,6 +281,9 @@ main (int argc, char *argv[])
 
   dir = xstrdup (dir);
 
+  if (tpm_dev)
+grub_util_tpm_open (tpm_dev);
+
   /* Start GRUB!  */
   if (setjmp (main_env) == 0)
 grub_main ();
@@ -283,6 +291,7 @@ main (int argc, char *argv[])
   grub_fini_all ();
   grub_hostfs_fini ();
   grub_host_fini ();
+  grub_util_tpm_close ();
 
   grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
 
diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
index 521220b49..1db24fde7 100644
--- a/grub-core/kern/emu/misc.c
+++ b/grub-core/kern/emu/misc.c
@@ -28,6 +28,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include 
 #include 
@@ -41,6 +43,8 @@
 int verbosity;
 int kexecute;
 
+static int grub_util_tpm_fd = -1;
+
 void
 grub_util_warn (const char *fmt, ...)
 {
@@ -230,3 +234,50 @@ grub_util_get_kexecute (void)
 {
   return kexecute;
 }
+
+grub_err_t
+grub_util_tpm_open (const char *tpm_dev)
+{
+  if (grub_util_tpm_fd != -1)
+return GRUB_ERR_NONE;
+
+  grub_util_tpm_fd = open (tpm_dev, O_RDWR);
+  if (grub_util_tpm_fd == -1)
+grub_util_error (_("cannot open TPM device '%s': %s"), tpm_dev, strerror 
(errno));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_util_tpm_close (void)
+{
+  int err;
+
+  if (grub_util_tpm_fd == -1)
+return GRUB_ERR_NONE;
+
+  err = close (grub_util_tpm_fd);
+  if (err != GRUB_ERR_NONE)
+grub_util_error (_("cannot close TPM device: %s"), strerror (errno));
+
+  grub_util_tpm_fd = -1;
+  return GRUB_ERR_NONE;
+}
+
+grub_size_t
+grub_util_tpm_read (void *output, grub_size_t size)
+{
+  if (grub_util_tpm_fd == -1)
+return -1;
+
+  return read (grub_util_tpm_fd, output, size);
+}
+
+grub_size_t
+grub_util_tpm_write (const void *input, grub_size_t size)
+{
+  if (grub_util_tpm_fd == -1)
+return -1;
+
+  return write (grub_util_tpm_fd, input, size);
+}
diff --git a/grub-core/tpm2/tcg2-emu.c b/grub-core/tpm2/tcg2-emu.c
new file mode 100644
index 0..0d7b8b16e
--- /dev/null
+++ b/grub-core/tpm2/tcg2-emu.c
@@ -0,0 +1,52 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2024 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.
+ 

[PATCH v8 12/22] util/grub-protect: Add new tool

2024-01-16 Thread Gary Lin via Grub-devel
From: 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 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 \
--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-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  -P tpm2

Or, for the raw sealed key:

tpm2_key_protector_init --keyfile=(hd0,gpt1)/boot/grub2/sealed.key
cryptomount -u  -P tpm2

Signed-off-by: Hernan Gatta 
Signed-off-by: Gary Lin 
---
 .gitignore  |2 +
 Makefile.util.def   |   22 +
 configure.ac|9 +
 util/grub-protect.c | 1492 +++
 4 files changed, 1525 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 c43bec8a0..89ceeec0e 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)';
+
+  enable = efi;
+};
+
 program = {
   name = grub-mkrelpath;
   mansection = 1;
diff --git a/configure.ac b/configure.ac
index 84a202c6e..f463338de 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,14 @@ fi
 AC_SUBST([LIBZFS])
 AC_SUBST([LIBNVPAIR])
 
+LIBTASN1=
+if test x"$platform" = xefi; then
+  AC_CHECK_LIB([tasn1], [asn1_write_value], [],
+   [AC_MSG_ERROR([Your platform requires libtasn1])])
+  LIBTASN1="-ltasn1"
+fi
+AC_SUBST([LIBTASN1])
+
 LIBS=""
 
 AC_SUBST([FONT_SOURCE])
diff --git a/util/grub-protect.c b/util/grub-protect.c
new file mode 100644
index 0..c6d41ea40
--- /dev/null
+++ b/util/grub-protect.c
@@ -0,0 +1,1492 @@
+/*
+ *  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 .
+ */
+
+#include 
+
+#include 

[PATCH v8 14/22] tpm2: Add more marshal/unmarshal functions

2024-01-16 Thread Gary Lin via Grub-devel
Add a few more marshal/unmarshal functions to support authorized policy.

* Marshal:
  grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal()
  grub_tpm2_mu_TPMT_SENSITIVE_Marshal()
  grub_tpm2_mu_TPM2B_SENSITIVE_Marshal()
  grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal()
  grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal()
  grub_tpm2_mu_TPMU_HA_Marshal()
  grub_tpm2_mu_TPMT_HA_Marshal()
  grub_tpm2_mu_TPMU_SIGNATURE_Marshal()
  grub_tpm2_mu_TPMT_SIGNATURE_Marshal()
  grub_tpm2_mu_TPMT_TK_VERIFIED_Marshal()

* Unmarshal:
  grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal()
  grub_tpm2_mu_TPMT_TK_VERIFIED_Unmarshal()
  grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal()
  grub_tpm2_mu_TPMS_SIGNATURE_ECC_Unmarshal()
  grub_tpm2_mu_TPMU_HA_Unmarshal()
  grub_tpm2_mu_TPMT_HA_Unmarshal()
  grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal()
  grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal()

Signed-off-by: Gary Lin 
---
 grub-core/tpm2/mu.c| 262 +
 include/grub/tpm2/mu.h |  75 
 2 files changed, 337 insertions(+)

diff --git a/grub-core/tpm2/mu.c b/grub-core/tpm2/mu.c
index 1617f37cd..3a9a3c1be 100644
--- a/grub-core/tpm2/mu.c
+++ b/grub-core/tpm2/mu.c
@@ -383,6 +383,49 @@ grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal 
(grub_tpm2_buffer_t buffer,
   grub_tpm2_mu_TPM2B_Marshal (buffer, p->data.size, p->data.buffer);
 }
 
+void
+grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (grub_tpm2_buffer_t buffer,
+   const TPMI_ALG_PUBLIC type,
+   const TPMU_SENSITIVE_COMPOSITE 
*p)
+{
+  switch(type)
+{
+case TPM_ALG_RSA:
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->rsa.size, p->rsa.buffer);
+  break;
+case TPM_ALG_ECC:
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->ecc.size, p->ecc.buffer);
+  break;
+case TPM_ALG_KEYEDHASH:
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->bits.size, p->bits.buffer);
+  break;
+case TPM_ALG_SYMCIPHER:
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->sym.size, p->sym.buffer);
+  break;
+default:
+  buffer->error = 1;
+}
+}
+
+void
+grub_tpm2_mu_TPMT_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMT_SENSITIVE *p)
+{
+  grub_tpm2_buffer_pack_u16 (buffer, p->sensitiveType);
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->authValue.size, p->authValue.buffer);
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->seedValue.size, p->seedValue.buffer);
+  grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (buffer, p->sensitiveType,
+ >sensitive);
+}
+
+void
+grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (grub_tpm2_buffer_t buffer,
+  const TPM2B_SENSITIVE *p)
+{
+  grub_tpm2_buffer_pack_u16 (buffer, p->size);
+  grub_tpm2_mu_TPMT_SENSITIVE_Marshal (buffer, >sensitiveArea);
+}
+
 void
 grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer,
 const TPM2B_SENSITIVE_CREATE 
*sensitiveCreate)
@@ -405,6 +448,113 @@ grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal 
(grub_tpm2_buffer_t buffer,
 grub_tpm2_buffer_pack_u16 (buffer, 0);
 }
 
+void
+grub_tpm2_mu_TPMS_SIGNATURE_RSA_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMS_SIGNATURE_RSA *p)
+{
+  grub_tpm2_buffer_pack_u16 (buffer, p->hash);
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->sig.size, p->sig.buffer);
+}
+
+void
+grub_tpm2_mu_TPMS_SIGNATURE_ECC_Marshal (grub_tpm2_buffer_t buffer,
+ const TPMS_SIGNATURE_ECC *p)
+{
+  grub_tpm2_buffer_pack_u16 (buffer, p->hash);
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->signatureR.size, 
p->signatureR.buffer);
+  grub_tpm2_mu_TPM2B_Marshal (buffer, p->signatureS.size, 
p->signatureS.buffer);
+}
+
+void
+grub_tpm2_mu_TPMU_HA_Marshal (grub_tpm2_buffer_t buffer,
+  const TPMI_ALG_HASH hashAlg,
+  const TPMU_HA *p)
+{
+  switch (hashAlg)
+{
+case TPM_ALG_SHA1:
+  for (grub_uint16_t i = 0; i < TPM_SHA1_DIGEST_SIZE; i++)
+grub_tpm2_buffer_pack_u8 (buffer, p->sha1[i]);
+  break;
+case TPM_ALG_SHA256:
+  for (grub_uint16_t i = 0; i < TPM_SHA256_DIGEST_SIZE; i++)
+grub_tpm2_buffer_pack_u8 (buffer, p->sha256[i]);
+  break;
+case TPM_ALG_SHA384:
+  for (grub_uint16_t i = 0; i < TPM_SHA384_DIGEST_SIZE; i++)
+grub_tpm2_buffer_pack_u8 (buffer, p->sha384[i]);
+  break;
+case TPM_ALG_SHA512:
+  for (grub_uint16_t i = 0; i < TPM_SHA512_DIGEST_SIZE; i++)
+grub_tpm2_buffer_pack_u8 (buffer, p->sha512[i]);
+  break;
+default:
+  buffer->error = 1;
+  break;
+}
+}
+
+void
+grub_tpm2_mu_TPMT_HA_Marshal (grub_tpm2_buffer_t buffer,
+  const TPMT_HA *p)
+{
+  grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg);
+  grub_tpm2_mu_TPMU_HA_Marshal (buffer, p->hashAlg, >digest);
+}
+
+void

[PATCH v8 09/22] tpm2: Add TPM Software Stack (TSS)

2024-01-16 Thread Gary Lin via Grub-devel
From: Hernan Gatta 

A Trusted Platform Module (TPM) Software Stack (TSS) provides logic to
compose, submit, and parse TPM commands and responses.

A limited number of TPM commands may be accessed via the EFI TCG2
protocol. This protocol exposes functionality that is primarily geared
toward TPM usage within the context of Secure Boot. For all other TPM
commands, however, such as sealing and unsealing, this protocol does not
provide any help, with the exception of passthrough command submission.

The SubmitCommand method allows a caller to send raw commands to the
system's TPM and to receive the corresponding response. These
command/response pairs are formatted using the TPM wire protocol. To
construct commands in this way, and to parse the TPM's response, it is
necessary to, first, possess knowledge of the various TPM structures, and,
second, of the TPM wire protocol itself.

As such, this patch includes a set of header files that define the
necessary TPM structures and TSS functions, implementations of various
TPM2_* functions (inventoried below), and logic to write and read command
and response buffers, respectively, using the TPM wire protocol.

Functions: TPM2_Create, TPM2_CreatePrimary, TPM2_EvictControl,
TPM2_FlushContext, TPM2_Load, TPM2_PCR_Read, TPM2_PolicyGetDigest,
TPM2_PolicyPCR, TPM2_ReadPublic, TPM2_StartAuthSession, TPM2_Unseal.

Signed-off-by: Hernan Gatta 
Signed-off-by: Gary Lin 
---
 grub-core/tpm2/buffer.c| 145 +
 grub-core/tpm2/mu.c| 807 +
 grub-core/tpm2/tcg2.c  | 143 +
 grub-core/tpm2/tpm2.c  | 761 +++
 include/grub/tpm2/buffer.h |  65 ++
 include/grub/tpm2/internal/functions.h | 117 
 include/grub/tpm2/internal/structs.h   | 675 +
 include/grub/tpm2/internal/types.h | 370 
 include/grub/tpm2/mu.h | 292 +
 include/grub/tpm2/tcg2.h   |  34 ++
 include/grub/tpm2/tpm2.h   |  34 ++
 11 files changed, 3443 insertions(+)
 create mode 100644 grub-core/tpm2/buffer.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/tpm2/buffer.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

diff --git a/grub-core/tpm2/buffer.c b/grub-core/tpm2/buffer.c
new file mode 100644
index 0..cb9f29497
--- /dev/null
+++ b/grub-core/tpm2/buffer.c
@@ -0,0 +1,145 @@
+/*
+ *  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 
+
+void grub_tpm2_buffer_init (grub_tpm2_buffer_t buffer)
+{
+  grub_memset (buffer->data, 0xDD, sizeof (buffer->data));
+  buffer->size = 0;
+  buffer->offset = 0;
+  buffer->cap = sizeof (buffer->data);
+  buffer->error = 0;
+}
+
+void
+grub_tpm2_buffer_pack (grub_tpm2_buffer_t buffer, const void* data,
+  grub_size_t size)
+{
+  grub_uint32_t r = buffer->cap - buffer->size;
+
+  if (buffer->error)
+return;
+
+  if (size > r)
+{
+  buffer->error = 1;
+  return;
+}
+
+  grub_memcpy (>data[buffer->size], (void*) data, size);
+  buffer->size += size;
+}
+
+void
+grub_tpm2_buffer_pack_u8 (grub_tpm2_buffer_t buffer, grub_uint8_t value)
+{
+  grub_tpm2_buffer_pack (buffer, (const char*) , sizeof (value));
+}
+
+void
+grub_tpm2_buffer_pack_u16 (grub_tpm2_buffer_t buffer, grub_uint16_t value)
+{
+  grub_uint16_t tmp = grub_cpu_to_be16 (value);
+  grub_tpm2_buffer_pack (buffer, (const char*) , sizeof (tmp));
+}
+
+void
+grub_tpm2_buffer_pack_u32 (grub_tpm2_buffer_t buffer, grub_uint32_t value)
+{
+  grub_uint32_t tmp = grub_cpu_to_be32 (value);
+  grub_tpm2_buffer_pack (buffer, (const char*) , sizeof (tmp));
+}
+
+void
+grub_tpm2_buffer_unpack (grub_tpm2_buffer_t buffer, void* data,
+grub_size_t size)
+{
+  grub_uint32_t r = buffer->size - buffer->offset;
+
+  if (buffer->error)
+return;
+
+  if (size > r)
+{
+  buffer->error = 1;
+  return;
+}
+
+  

[PATCH v8 15/22] tpm2: Implement more TPM2 commands

2024-01-16 Thread Gary Lin via Grub-devel
This commit implements a few more TPM2 commands as the preparation for
the authorized policy support.

* TPM2_LoadExternal
  This command is added to load the external public key to verify the
  signed policy digest
* TPM2_HashSequenceStart, TPM2_SequenceUpdate, TPM2_SequenceComplete,
  and TPM2_Hash
  With those commands, we can use the TPM as a coprocessor to calculate
  the hash of a given binary blob.
* TPM2_VerifySignature
  This command verifies the given signature with the given public key
  and returns the validation ticket to authorize the policy.
* TPM2_PolicyAuthorize
  This command approves the given policy digest so that we can unseal
  the key with the newly authorized policy.

Signed-off-by: Gary Lin 
---
 grub-core/tpm2/tpm2.c  | 424 +
 include/grub/tpm2/internal/functions.h |  57 
 2 files changed, 481 insertions(+)

diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c
index d67699a24..159353b08 100644
--- a/grub-core/tpm2/tpm2.c
+++ b/grub-core/tpm2/tpm2.c
@@ -427,6 +427,73 @@ TPM2_Load (const TPMI_DH_OBJECT parent_handle,
   return TPM_RC_SUCCESS;
 }
 
+TPM_RC
+TPM2_LoadExternal (const TPMS_AUTH_COMMAND *authCommand,
+   const TPM2B_SENSITIVE *inPrivate,
+   const TPM2B_PUBLIC *inPublic,
+   const TPMI_RH_HIERARCHY hierarchy,
+   TPM_HANDLE *objectHandle,
+   TPM2B_NAME *name,
+   TPMS_AUTH_RESPONSE *authResponse)
+{
+  TPM_RC rc;
+  struct grub_tpm2_buffer in;
+  struct grub_tpm2_buffer out;
+  TPM_HANDLE objectHandleTmp;
+  TPM2B_NAME nameTmp;
+  TPMS_AUTH_RESPONSE authResponseTmp;
+  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+  TPM_RC responseCode;
+  grub_uint32_t param_size;
+
+  if (!inPublic)
+return TPM_RC_VALUE;
+
+  if (!objectHandle)
+objectHandle = 
+  if (!name)
+name = 
+  if (!authResponse)
+authResponse = 
+
+  grub_memset (objectHandle, 0, sizeof (*objectHandle));
+  grub_memset (name, 0, sizeof (*name));
+  grub_memset (authResponse, 0, sizeof (*authResponse));
+
+  /* Marshal */
+  grub_tpm2_buffer_init ();
+  if (authCommand)
+grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (, authCommand);
+  if (inPrivate)
+grub_tpm2_mu_TPM2B_SENSITIVE_Marshal (, inPrivate);
+  else
+grub_tpm2_buffer_pack_u16 (, 0);
+  grub_tpm2_mu_TPM2B_PUBLIC_Marshal (, inPublic);
+  grub_tpm2_buffer_pack_u32 (, hierarchy);
+  if (in.error)
+return TPM_RC_FAILURE;
+
+  /* Submit */
+  grub_tpm2_buffer_init ();
+  rc = grub_tpm2_submit_command (tag, TPM_CC_LoadExternal, , , 
);
+  if (rc != TPM_RC_SUCCESS)
+return rc;
+  if (responseCode != TPM_RC_SUCCESS)
+return responseCode;
+
+  /* Unmarshal*/
+  grub_tpm2_buffer_unpack_u32 (, objectHandle);
+  if (tag == TPM_ST_SESSIONS)
+grub_tpm2_buffer_unpack_u32 (, _size);
+  grub_tpm2_mu_TPM2B_Unmarshal (, (TPM2B*)name);
+  if (tag == TPM_ST_SESSIONS)
+grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (, authResponse);
+  if (out.error)
+return TPM_RC_FAILURE;
+
+  return TPM_RC_SUCCESS;
+}
+
 TPM_RC
 TPM2_Unseal (const TPMI_DH_OBJECT itemHandle,
 const TPMS_AUTH_COMMAND *authCommand,
@@ -759,3 +826,360 @@ TPM2_EvictControl (const TPMI_RH_PROVISION auth,
 
   return TPM_RC_SUCCESS;
 }
+
+TPM_RC
+TPM2_HashSequenceStart (const TPMS_AUTH_COMMAND *authCommand,
+const TPM2B_AUTH *auth,
+const TPMI_ALG_HASH hashAlg,
+TPMI_DH_OBJECT *sequenceHandle,
+TPMS_AUTH_RESPONSE *authResponse)
+{
+  struct grub_tpm2_buffer in;
+  struct grub_tpm2_buffer out;
+  TPMI_DH_OBJECT sequenceHandleTmp;
+  TPMS_AUTH_RESPONSE authResponseTmp;
+  TPMI_ST_COMMAND_TAG tag = authCommand ? TPM_ST_SESSIONS : TPM_ST_NO_SESSIONS;
+  TPM_RC responseCode;
+  TPM_RC rc;
+  grub_uint32_t parameterSize;
+
+  if (!auth)
+return TPM_RC_VALUE;
+
+  if (!sequenceHandle)
+sequenceHandle = 
+  if (!authResponse)
+authResponse = 
+
+  grub_memset (sequenceHandle, 0, sizeof (*sequenceHandle));
+  grub_memset (authResponse, 0, sizeof (*authResponse));
+
+  /* Marshal */
+  grub_tpm2_buffer_init ();
+  if (authCommand)
+grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (, authCommand);
+  grub_tpm2_mu_TPM2B_Marshal (, auth->size, auth->buffer);
+  grub_tpm2_buffer_pack_u16 (, hashAlg);
+  if (in.error)
+return TPM_RC_FAILURE;
+
+  /* Submit */
+  grub_tpm2_buffer_init ();
+  rc = grub_tpm2_submit_command (tag, TPM_CC_HashSequenceStart, , 
,
+ );
+  if (rc != TPM_RC_SUCCESS)
+return rc;
+  if (responseCode != TPM_RC_SUCCESS)
+return responseCode;
+
+  /* Unmarshal */
+  grub_tpm2_buffer_unpack_u32 (, sequenceHandle);
+  if (tag == TPM_ST_SESSIONS)
+{
+  grub_tpm2_buffer_unpack_u32 (, );
+  grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal(, authResponse);
+}
+  if (out.error)
+return TPM_RC_FAILURE;
+
+  return 

[PATCH v8 16/22] tpm2: Support authorized policy

2024-01-16 Thread Gary Lin via Grub-devel
This commit handles the TPM2_PolicyAuthorize command from the key file
in TPM 2.0 Key File format.

TPM2_PolicyAuthorize is the essential command to support authorized
policy which allows the users to sign TPM policies with their own keys.
Per TPM 2.0 Key File(*1), CommandPolicy for TPM2_PolicyAuthorize
comprises 'TPM2B_PUBLIC pubkey', 'TPM2B_DIGEST policy_ref', and
'TPMT_SIGNATURE signature'. To verify the signature, the current policy
digest is hashed with the hash algorithm written in 'signature', and then
'signature' is verified with the hashed policy digest and 'pubkey'. Once
TPM accepts 'signature', TPM2_PolicyAuthorize is invoked to authorize the
signed policy.

To create the key file with authorized policy, here are the pcr-oracle(*2)
commands:

  # Generate the RSA key and create the authorized policy file
  $ pcr-oracle \
--rsa-generate-key \
--private-key policy-key.pem \
--auth authorized.policy \
create-authorized-policy 0,2,4,7,9

  # Seal the secret with the authorized policy
  $ pcr-oracle \
--key-format tpm2.0 \
--auth authorized.policy \
--input disk-secret.txt \
--output sealed.key \
seal-secret

  # Sign the predicted PCR policy
  $ pcr-oracle \
--key-format tpm2.0 \
--private-key policy-key.pem \
--from eventlog \
--stop-event "grub-file=grub.cfg" \
--after \
--input sealed.key \
--output sealed.tpm \
sign 0,2,4,7.9

Then specify the key file and the key protector to grub.cfg in the EFI
system partition:

tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
cryptomount -u  -P tpm2

For any change in the boot components, just run the 'sign' command again
to update the signature in sealed.tpm, and TPM can unseal the key file
with the updated PCR policy.

(*1) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*2) https://github.com/okirch/pcr-oracle

Signed-off-by: Gary Lin 
---
 grub-core/tpm2/module.c | 84 +
 1 file changed, 84 insertions(+)

diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index df0727215..0cbfd06e8 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -453,6 +453,87 @@ grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION 
session,
   return GRUB_ERR_NONE;
 }
 
+static grub_err_t
+grub_tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION session,
+struct grub_tpm2_buffer *cmd_buf)
+{
+  TPM2B_PUBLIC pubkey;
+  TPM2B_DIGEST policy_ref;
+  TPMT_SIGNATURE signature;
+  TPM2B_DIGEST pcr_policy;
+  TPM2B_DIGEST pcr_policy_hash;
+  TPMI_ALG_HASH sig_hash;
+  TPMT_TK_VERIFIED verification_ticket;
+  TPM_HANDLE pubkey_handle = 0;
+  TPM2B_NAME pubname;
+  TPM_RC rc;
+  grub_err_t err;
+
+  grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (cmd_buf, );
+  grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (cmd_buf, _ref);
+  grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (cmd_buf, );
+  if (cmd_buf->error != 0)
+return grub_error (GRUB_ERR_BAD_ARGUMENT,
+  N_("Failed to unmarshal the buffer for 
TPM2_PolicyAuthorize"));
+
+  /* Retrieve Policy Digest */
+  rc = TPM2_PolicyGetDigest (session, NULL, _policy, NULL);
+  if (rc != TPM_RC_SUCCESS)
+return grub_error (GRUB_ERR_BAD_DEVICE,
+  N_("Failed to get policy digest (TPM2_PolicyGetDigest: 
0x%x)."),
+  rc);
+
+  /* Calculate the digest of the polcy for VerifySignature */
+  sig_hash = TPMT_SIGNATURE_get_hash_alg ();
+  if (sig_hash == TPM_ALG_NULL)
+return grub_error (GRUB_ERR_BAD_ARGUMENT,
+  N_("Failed to get the hash algorithm of the signature"));
+
+  rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)_policy, sig_hash,
+ TPM_RH_NULL, _policy_hash, NULL, NULL);
+  if (rc != TPM_RC_SUCCESS)
+return grub_error (GRUB_ERR_BAD_DEVICE,
+  N_("Failed to create PCR policy hash (TPM2_Hash: 0x%x)"),
+  rc);
+
+  /* Load the public key */
+  rc = TPM2_LoadExternal (NULL, NULL, , TPM_RH_OWNER,
+ _handle, , NULL);
+  if (rc != TPM_RC_SUCCESS)
+return grub_error (GRUB_ERR_BAD_DEVICE,
+  N_("Failed to load public key (TPM2_LoadExternal: 
0x%x)"),
+  rc);
+
+  /* Verify the signature against the public key and the policy digest */
+  rc = TPM2_VerifySignature (pubkey_handle, NULL, _policy_hash, ,
+_ticket, NULL);
+  if (rc != TPM_RC_SUCCESS)
+{
+  err = grub_error (GRUB_ERR_BAD_DEVICE,
+   N_("Failed to verify signature (TPM2_VerifySignature: 
0x%x)"),
+   rc);
+  goto error;
+}
+
+  /* Authorize the signed policy with the public key and the verification 
ticket */
+  rc = TPM2_PolicyAuthorize (session, NULL, _policy, _ref, ,
+_ticket, NULL);
+  if (rc != TPM_RC_SUCCESS)
+{
+  err = 

[PATCH v8 19/22] cryptodisk: wipe out the cached keys from protectors

2024-01-16 Thread Gary Lin via Grub-devel
An attacker may insert a malicious disk with the same crypto UUID and
trick grub2 to mount the fake root. Even though the key from the key
protector fails to unlock the fake root, it's not wiped out cleanly so
the attacker could dump the memory to retrieve the secret key. To defend
such attack, wipe out the cached key when we don't need it.

Signed-off-by: Gary Lin 
Cc: Fabian Vogt 
---
 grub-core/disk/cryptodisk.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index bbb9a56b5..5634eaeeb 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1349,7 +1349,11 @@ grub_cryptodisk_clear_key_cache (struct 
grub_cryptomount_args *cargs)
 return;
 
   for (i = 0; cargs->protectors[i]; i++)
-grub_free (cargs->key_cache[i].key);
+{
+  if (cargs->key_cache[i].key)
+   grub_memset (cargs->key_cache[i].key, 0, cargs->key_cache[i].key_len);
+  grub_free (cargs->key_cache[i].key);
+}
 
   grub_free (cargs->key_cache);
 }
-- 
2.35.3


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


[PATCH v8 17/22] protectors: Implement NV index

2024-01-16 Thread Gary Lin via Grub-devel
From: Patrick Colp 

Currently with the TPM2 protector, only SRK mode is supported and
NV index support is just a stub. Implement the NV index option.

Note: This only extends support on the unseal path. grub2_protect
has not been updated. tpm2-tools can be used to insert a key into
the NV index.

An example of inserting a key using tpm2-tools:

  # Get random key.
  tpm2_getrandom 32 > key.dat

  # Create primary object.
  tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx

  # Create policy object. `pcrs.dat` contains the PCR values to seal against.
  tpm2_startauthsession -S session.dat
  tpm2_policypcr -S session.dat -l sha256:7,11 -f pcrs.dat -L policy.dat
  tpm2_flushcontext session.dat

  # Seal key into TPM.
  cat key.dat | tpm2_create -C primary.ctx -u key.pub -r key.priv -L policy.dat 
-i-
  tpm2_load -C primary.ctx -u key.pub -r key.priv -n sealing.name -c sealing.ctx
  tpm2_evictcontrol -C o -c sealing.ctx 0x8100

Then to unseal the key in grub, add this to grub.cfg:

  tpm2_key_protector_init --mode=nv --nvindex=0x8100 --pcrs=7,11
  cryptomount -u  --protector tpm2

Signed-off-by: Patrick Colp 
Signed-off-by: Gary Lin 
---
 grub-core/tpm2/module.c | 25 -
 1 file changed, 20 insertions(+), 5 deletions(-)

diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
index 0cbfd06e8..00b401bd5 100644
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -834,12 +834,27 @@ static grub_err_t
 grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx,
grub_uint8_t **key, grub_size_t *key_size)
 {
-  (void)ctx;
-  (void)key;
-  (void)key_size;
+  TPM_HANDLE sealed_handle = ctx->nv;
+  tpm2key_policy_t policy_seq = NULL;
+  grub_err_t err;
+
+  /* Create a basic policy sequence based on the given PCR selection */
+  err = grub_tpm2_protector_simple_policy_seq (ctx, _seq);
+  if (err != GRUB_ERR_NONE)
+goto exit;
+
+  err = grub_tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size);
+
+  /* Pop error messages on success */
+  if (err == GRUB_ERR_NONE)
+while (grub_error_pop ());
+
+exit:
+  TPM2_FlushContext (sealed_handle);
 
-  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
-N_("NV Index mode is not implemented yet"));
+  grub_tpm2key_free_policy_seq (policy_seq);
+
+  return err;
 }
 
 static grub_err_t
-- 
2.35.3


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


[PATCH v8 00/22] Automatic Disk Unlock with TPM2

2024-01-16 Thread Gary Lin via Grub-devel
GIT repo for v8: https://github.com/lcp/grub2/tree/tpm2-unlock-v8

This patch series is based on "Automatic TPM Disk Unlock"(*1) posted by
Hernan Gatta to introduce the key protector framework and TPM2 stack
to GRUB2, and this could be a useful feature for the systems to
implement full disk encryption.

To support TPM 2.0 Key File format(*2), patch 1~6 are grabbed from
Daniel Axtens's "appended signature secure boot support" (*3) to import
libtasn1 into grub2. Besides, the libtasn1 version is upgraded to
4.19.0 instead of 4.16.0 in the original patch.

Patch 7 adds the document for libtasn1 and the steps to upgrade the
library.

Patch 8~12 are Hernan Gatta's patches with the follow-up fixes and
improvements:
- Converting 8 spaces into 1 tab
- Merging the minor build fix from Michael Chang
  - Replacing "lu" with "PRIuGRUB_SIZE" for grub_dprintf
  - Adding "enable = efi" to the tpm2 module in grub-core/Makefile.core.def
- Rebasing "cryptodisk: Support key protectors" to the git master
- Removing the measurement on the sealed key
  - Based on the patch from Olaf Kirch 
- Adjusting the input parameters of TPM2_EvictControl to match the order
  in "TCG TPM2 Part3 Commands"
- Declaring the input arguments of TPM2 functions as const
- Resending TPM2 commands on TPM_RC_RETRY
- Adding checks for the parameters of TPM2 commands
- Packing the missing authorization command for TPM2_PCR_Read
- Tweaking the TPM2 command functions to allow some parameters to be
  NULL so that we don't have to declare empty variables
- Only enabling grub-protect for "efi" since the TPM2 stack currently
  relies on the EFI TCG2 protocol to send TPM2 commands
- Using grub_cpu_to_be*() in the TPM2 stack instead of grub_swap_bytes*()
  which may cause problems in big-indian machines
- Changing the short name of "--protector" of "cryptomount" from "-k" to
  "-P" to avoid the conflict with "--key-file"
- Supporting TPM 2.0 Key File Format besides the raw sealed key
- Adding the external libtasn1 dependency to grub-protect to write the
  TPM 2.0 Key files

Patch 13~16 implement the authorized policy support.

Patch 17 implements the missing NV index mode. (Thanks to Patrick Colp)

Patch 18 improves the 'cryptomount' command to fall back to the
passphrase mode when the key protector fails to unlock the encrypted
partition. (Another patch from Patrick Colp)

Patch 19~20 fix the potential security issues spotted by Fabian Vogt.

Patch 21~22 add the TPM key unsealing testcase.

To utilize the TPM2 key protector to unlock the encrypted partition
(sdb1), here are the sample steps:

1. Add an extra random key for LUKS (luks-key)
   $ dd if=/dev/urandom of=luks-key bs=1 count=32
   $ sudo cryptsetup luksAddKey /dev/sdb1 luks-key --pbkdf=pbkdf2

2. Seal the key
   $ sudo grub-protect --action=add \
   --protector=tpm2 \
   --tpm2key \
   --tpm2-keyfile=luks-key \
   --tpm2-outfile=/boot/efi/boot/grub2/sealed.tpm

3. Unseal the key with the proper commands in grub.cfg:
   tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm
   cryptomount -u  -P tpm2

(*1) https://lists.gnu.org/archive/html/grub-devel/2022-02/msg6.html
(*2) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html
(*3) https://lists.gnu.org/archive/html/grub-devel/2021-06/msg00044.html

v8:
- Introducing TPM device support to grub-emu and adding the TPM key
  unsealing testcase

v7:
- Stopping reading SRK from the well-known persistent handle (TPM2_SRK_HANDLE,
  i.e. 0x8101) by default since the persistent handle may be created
  by other OS and causes unsealing failure due to SRK mismatching
  - The user now has to specify the persistent handle with "--srk"
explicitly.
- Utilizing grub_error() to print more error messages 
- Unifying the format of the error messages from TPM2 commands

v6:
- Supporting more SRK types than RSA2048 and ECC_NIST_P256
- Documenting SHA512 as the supported PCR bank type in the tpm2
  protector
- Removing the redundant error message for grub_tpm2_protector_srk_get()
  since it may overwrite the real error message.
- Updating the supported SRK types and PCR bank types in grub-protect 
- Removing the unused type: TPM2_ECC_CURVE

v5:
- https://lists.gnu.org/archive/html/grub-devel/2023-08/msg00113.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v5
- Rebasing to the latest git HEAD and improving the commit messages
- Implementing authorized poilcy support
- Implementing NV index mode
- Improving the 'cryptomount' command to fall back to the passphrase
  mode when the key protector fails to unlock the encrypted partition
- Fixing the potential security issues

v4:
- https://lists.gnu.org/archive/html/grub-devel/2023-04/msg00104.html
- GIT repo: https://github.com/lcp/grub2/tree/tpm2-unlock-v4
- Improving the error condition checks in cryptodisk.c
- Moving the code to unseal with the standalone policy sequence below
  the code for 

[PATCH v8 11/22] cryptodisk: Support key protectors

2024-01-16 Thread Gary Lin via Grub-devel
From: Hernan Gatta 

Add a new parameter to cryptomount to support the key protectors framework: -P.
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: Hernan Gatta 
Signed-off-by: Michael Chang 
Signed-off-by: Gary Lin 
Reviewed-by: Glenn Washburn 
---
 Makefile.util.def   |   1 +
 grub-core/disk/cryptodisk.c | 172 +---
 include/grub/cryptodisk.h   |  16 
 3 files changed, 158 insertions(+), 31 deletions(-)

diff --git a/Makefile.util.def b/Makefile.util.def
index 5bb3ae18e..c43bec8a0 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 2246af51b..dba5efa61 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 
@@ -44,7 +45,8 @@ enum
 OPTION_KEYFILE,
 OPTION_KEYFILE_OFFSET,
 OPTION_KEYFILE_SIZE,
-OPTION_HEADER
+OPTION_HEADER,
+OPTION_PROTECTOR
   };
 
 static const struct grub_arg_option options[] =
@@ -58,6 +60,8 @@ static const struct grub_arg_option options[] =
 {"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
 {"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, 
ARG_TYPE_INT},
 {"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
+{"protector", 'P', GRUB_ARG_OPTION_REPEATABLE,
+ N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
 {0, 0, 0, 0, 0, 0}
   };
 
@@ -1061,6 +1065,7 @@ grub_cryptodisk_scan_device_real (const char *name,
   grub_err_t ret = GRUB_ERR_NONE;
   grub_cryptodisk_t dev;
   grub_cryptodisk_dev_t cr;
+  int i;
   struct cryptodisk_read_hook_ctx read_hook_data = {0};
   int askpass = 0;
   char *part = NULL;
@@ -1113,41 +1118,112 @@ grub_cryptodisk_scan_device_real (const char *name,
   goto error_no_close;
 if (!dev)
   continue;
+break;
+  }
 
-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)
- goto error_no_close;
-
-   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 == NULL)
+{
+  grub_error (GRUB_ERR_BAD_MODULE,
+ "no cryptodisk module can handle this device");
+  goto error_no_close;
+}
 
-ret = cr->recover_key (source, dev, cargs);
-if (ret != GRUB_ERR_NONE)
-  goto error;
+  if (cargs->protectors)
+{
+  for (i = 0; cargs->protectors[i]; i++)
+   {
+ if (cargs->key_cache[i].invalid)
+   continue;
+
+ if (cargs->key_cache[i].key == NULL)
+   {
+ ret = grub_key_protector_recover_key (cargs->protectors[i],
+   >key_cache[i].key,
+   
>key_cache[i].key_len);
+ if (ret != GRUB_ERR_NONE)
+   {
+ 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 = grub_cryptodisk_insert (dev, name, source);
-if (ret != GRUB_ERR_NONE)
+ ret = cr->recover_key (source, dev, 

[PATCH v8 13/22] tpm2: Add TPM2 types, structures, and command constants

2024-01-16 Thread Gary Lin via Grub-devel
Add new TPM2 types and structures as the preparation to support
authorized policy.

* New types:
  TPM_ALG_ECDAA, TPM_ALG_ECDSA, TPM_ALG_ECSCHNORR, TPM_ALG_RSASSA,
  TPM_ALG_RSAPSS, TPM_ALG_SM2, and TPMI_ALG_SIG_SCHEME

* New structures:
  TPMS_EMPTY, TPMS_SIGNATURE_RSA, TPMS_SIGNATURE_ECC,
  TPMS_SIGNATURE_ECDSA, TPMS_SIGNATURE_ECDAA, TPMS_SIGNATURE_SM2,
  TPMS_SIGNATURE_ECSCHNORR, TPMU_SIGNATURE, and TPMT_TK_VERIFIED

* New command constants:
  TPM_CC_LoadExternal, TPM_CC_HashSequenceStart, TPM_CC_SequenceUpdate,
  TPM_CC_SequenceComplete, TPM_CC_Hash, TPM_CC_VerifySignature,
  TPM_CC_PolicyAuthorize

Signed-off-by: Gary Lin 
---
 include/grub/tpm2/internal/structs.h | 86 
 include/grub/tpm2/internal/types.h   | 42 +-
 2 files changed, 114 insertions(+), 14 deletions(-)

diff --git a/include/grub/tpm2/internal/structs.h 
b/include/grub/tpm2/internal/structs.h
index 72d71eb70..db9eb6cf6 100644
--- a/include/grub/tpm2/internal/structs.h
+++ b/include/grub/tpm2/internal/structs.h
@@ -672,4 +672,90 @@ struct TPMT_TK_CREATION
 };
 typedef struct TPMT_TK_CREATION TPMT_TK_CREATION;
 
+/* TPMS_EMPTY Structure */
+struct TPMS_EMPTY {
+  grub_uint8_t empty[1]; /* a structure with no member */
+};
+typedef struct TPMS_EMPTY TPMS_EMPTY;
+
+/* TPMS_SIGNATURE_RSA Structure */
+struct TPMS_SIGNATURE_RSA {
+  TPMI_ALG_HASH hash;
+  TPM2B_PUBLIC_KEY_RSA sig;
+};
+typedef struct TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSA;
+
+/* Definition of Types for RSA Signature */
+typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSASSA;
+typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSAPSS;
+
+/* TPMS_SIGNATURE_ECC Structure */
+struct TPMS_SIGNATURE_ECC {
+  TPMI_ALG_HASH hash;
+  TPM2B_ECC_PARAMETER signatureR;
+  TPM2B_ECC_PARAMETER signatureS;
+};
+typedef struct TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECC;
+
+/* Definition of Types for ECC TPMS_SIGNATURE_ECC */
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA;
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA;
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_SM2;
+typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECSCHNORR;
+
+/* TPMU_SIGNATURE Structure */
+union TPMU_SIGNATURE {
+  TPMS_SIGNATURE_RSASSA rsassa;
+  TPMS_SIGNATURE_RSAPSS rsapss;
+  TPMS_SIGNATURE_ECDSA ecdsa;
+  TPMS_SIGNATURE_ECDAA ecdaa;
+  TPMS_SIGNATURE_SM2 sm2;
+  TPMS_SIGNATURE_ECSCHNORR ecschnorr;
+  TPMT_HA hmac;
+  TPMS_SCHEME_HASH any;
+  TPMS_EMPTY null;
+};
+typedef union TPMU_SIGNATURE TPMU_SIGNATURE;
+
+/* TPMT_SIGNATURE Structure */
+struct TPMT_SIGNATURE {
+  TPMI_ALG_SIG_SCHEME sigAlg;
+  TPMU_SIGNATURE signature;
+};
+typedef struct TPMT_SIGNATURE TPMT_SIGNATURE;
+
+static inline TPMI_ALG_HASH
+TPMT_SIGNATURE_get_hash_alg (TPMT_SIGNATURE *sig)
+{
+  switch (sig->sigAlg)
+{
+case TPM_ALG_RSASSA:
+  return sig->signature.rsassa.hash;
+case TPM_ALG_RSAPSS:
+  return sig->signature.rsapss.hash;
+case TPM_ALG_ECDSA:
+  return sig->signature.ecdsa.hash;
+case TPM_ALG_ECDAA:
+  return sig->signature.ecdaa.hash;
+case TPM_ALG_SM2:
+  return sig->signature.sm2.hash;
+case TPM_ALG_ECSCHNORR:
+  return sig->signature.ecschnorr.hash;
+case TPM_ALG_HMAC:
+  return sig->signature.hmac.hashAlg;
+default:
+  break;
+}
+
+  return TPM_ALG_NULL;
+}
+
+/* TPMT_TK_VERIFIED Structure */
+struct TPMT_TK_VERIFIED {
+  TPM_ST tag;
+  TPMI_RH_HIERARCHY hierarchy;
+  TPM2B_DIGEST digest;
+};
+typedef struct TPMT_TK_VERIFIED TPMT_TK_VERIFIED;
+
 #endif /* ! GRUB_TPM2_INTERNAL_STRUCTS_HEADER */
diff --git a/include/grub/tpm2/internal/types.h 
b/include/grub/tpm2/internal/types.h
index 9118cad5d..4eef085f1 100644
--- a/include/grub/tpm2/internal/types.h
+++ b/include/grub/tpm2/internal/types.h
@@ -181,6 +181,9 @@ typedef grub_uint16_t TPM_ALG_ID;
 #define TPM_ALG_CFB((TPM_ALG_ID) 0x0043)
 #define TPM_ALG_ECB((TPM_ALG_ID) 0x0044)
 #define TPM_ALG_ECC((TPM_ALG_ID) 0x0023)
+#define TPM_ALG_ECDAA  ((TPM_ALG_ID) 0x001A)
+#define TPM_ALG_ECDSA  ((TPM_ALG_ID) 0x0018)
+#define TPM_ALG_ECSCHNORR  ((TPM_ALG_ID) 0x001C)
 #define TPM_ALG_HMAC   ((TPM_ALG_ID) 0x0005)
 #define TPM_ALG_KDF1_SP800_108 ((TPM_ALG_ID) 0x0022)
 #define TPM_ALG_KDF1_SP800_56A ((TPM_ALG_ID) 0x0020)
@@ -189,10 +192,13 @@ typedef grub_uint16_t TPM_ALG_ID;
 #define TPM_ALG_MGF1   ((TPM_ALG_ID) 0x0007)
 #define TPM_ALG_NULL   ((TPM_ALG_ID) 0x0010)
 #define TPM_ALG_RSA((TPM_ALG_ID) 0x0001)
+#define TPM_ALG_RSASSA ((TPM_ALG_ID) 0x0014)
+#define TPM_ALG_RSAPSS ((TPM_ALG_ID) 0x0016)
 #define TPM_ALG_SHA1   ((TPM_ALG_ID) 0x0004)
 #define TPM_ALG_SHA256 ((TPM_ALG_ID) 0x000B)
 #define TPM_ALG_SHA384 ((TPM_ALG_ID) 0x000C)
 #define TPM_ALG_SHA512 ((TPM_ALG_ID) 0x000D)
+#define TPM_ALG_SM2((TPM_ALG_ID) 0x001B)
 #define TPM_ALG_SM3_256((TPM_ALG_ID) 0x0012)
 #define TPM_ALG_SM4((TPM_ALG_ID) 0x0013)
 #define TPM_ALG_SYMCIPHER  

[PATCH v8 08/22] protectors: Add key protectors framework

2024-01-16 Thread Gary Lin via Grub-devel
From: 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 
Signed-off-by: Gary Lin 
---
 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 f18550c1c..af21fc72d 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 c9d81b56a..70d5e0e00 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -149,6 +149,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 0..5ee059565
--- /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 == NULL || protector->name == NULL || 
grub_strlen(protector->name) == 0)
+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 (_key_protectors),
+ GRUB_AS_LIST (protector));
+
+  return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_unregister (struct grub_key_protector *protector)
+{
+  if (protector == NULL)
+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 == NULL)
+return GRUB_ERR_OUT_OF_RANGE;
+
+  if (protector == NULL || grub_strlen (protector) == 0)
+return GRUB_ERR_BAD_ARGUMENT;
+
+  kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+protector);
+  if (kp == NULL)
+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 0..3d9f69bce
--- /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 

[PATCH v8 05/22] libtasn1: compile into asn1 module

2024-01-16 Thread Gary Lin via Grub-devel
From: Daniel Axtens 

Create a wrapper file that specifies the module license.
Set up the makefile so it is built.

Signed-off-by: Daniel Axtens 
Signed-off-by: Gary Lin 
---
 grub-core/Makefile.core.def| 15 +++
 grub-core/lib/libtasn1_wrap/wrap.c | 26 ++
 2 files changed, 41 insertions(+)
 create mode 100644 grub-core/lib/libtasn1_wrap/wrap.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1571421d7..b1294e0f7 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2595,3 +2595,18 @@ module = {
   efi = commands/bli.c;
   enable = efi;
 };
+
+module = {
+  name = asn1;
+  common = lib/libtasn1/lib/decoding.c;
+  common = lib/libtasn1/lib/coding.c;
+  common = lib/libtasn1/lib/element.c;
+  common = lib/libtasn1/lib/structure.c;
+  common = lib/libtasn1/lib/parser_aux.c;
+  common = lib/libtasn1/lib/gstr.c;
+  common = lib/libtasn1/lib/errors.c;
+  common = lib/libtasn1_wrap/wrap.c;
+  cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
+  // -Wno-type-limits comes from libtasn1's configure.ac
+  cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) 
-I$(srcdir)/lib/libtasn1/lib -Wno-type-limits';
+};
diff --git a/grub-core/lib/libtasn1_wrap/wrap.c 
b/grub-core/lib/libtasn1_wrap/wrap.c
new file mode 100644
index 0..622ba942e
--- /dev/null
+++ b/grub-core/lib/libtasn1_wrap/wrap.c
@@ -0,0 +1,26 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020 IBM 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 
+
+/*
+ * libtasn1 is provided under LGPL2.1+, which is compatible
+ * with GPL3+. As Grub as a whole is under GPL3+, this module
+ * is therefore under GPL3+ also.
+ */
+GRUB_MOD_LICENSE ("GPLv3+");
-- 
2.35.3


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


[PATCH v8 01/22] posix_wrap: tweaks in preparation for libtasn1

2024-01-16 Thread Gary Lin via Grub-devel
From: Daniel Axtens 

 - Define SIZEOF_UNSIGNED_LONG_INT, it's the same as
   SIZEOF_UNSIGNED_LONG.

 - Define WORD_BIT, the size in bits of an int. This is a defined
   in the Single Unix Specification and in gnulib's limits.h. gnulib
   assumes it's 32 bits on all our platforms, including 64 bit
   platforms, so we also use that value.

 - Provide strto[u]l[l] preprocessor macros that resolve to
   grub_strto[u]l[l]. To avoid gcrypt redefining strtoul, we
   also define HAVE_STRTOUL here.

Signed-off-by: Daniel Axtens 
Signed-off-by: Gary Lin 
---
 grub-core/lib/posix_wrap/limits.h| 1 +
 grub-core/lib/posix_wrap/stdlib.h| 8 
 grub-core/lib/posix_wrap/sys/types.h | 1 +
 3 files changed, 10 insertions(+)

diff --git a/grub-core/lib/posix_wrap/limits.h 
b/grub-core/lib/posix_wrap/limits.h
index 26918c8a0..4be7b4080 100644
--- a/grub-core/lib/posix_wrap/limits.h
+++ b/grub-core/lib/posix_wrap/limits.h
@@ -41,5 +41,6 @@
 #define LONG_MAX GRUB_LONG_MAX
 
 #define CHAR_BIT 8
+#define WORD_BIT 32
 
 #endif
diff --git a/grub-core/lib/posix_wrap/stdlib.h 
b/grub-core/lib/posix_wrap/stdlib.h
index f5279756a..14e4efdd0 100644
--- a/grub-core/lib/posix_wrap/stdlib.h
+++ b/grub-core/lib/posix_wrap/stdlib.h
@@ -64,4 +64,12 @@ abort (void)
   grub_abort ();
 }
 
+#define strtol grub_strtol
+
+/* for libgcrypt */
+#define HAVE_STRTOUL
+#define strtoul grub_strtoul
+
+#define strtoull grub_strtoull
+
 #endif
diff --git a/grub-core/lib/posix_wrap/sys/types.h 
b/grub-core/lib/posix_wrap/sys/types.h
index eeda543c4..2f3e86549 100644
--- a/grub-core/lib/posix_wrap/sys/types.h
+++ b/grub-core/lib/posix_wrap/sys/types.h
@@ -50,6 +50,7 @@ typedef grub_uint8_t byte;
 typedef grub_addr_t uintptr_t;
 
 #define SIZEOF_UNSIGNED_LONG GRUB_CPU_SIZEOF_LONG
+#define SIZEOF_UNSIGNED_LONG_INT GRUB_CPU_SIZEOF_LONG
 #define SIZEOF_UNSIGNED_INT 4
 #define SIZEOF_UNSIGNED_LONG_LONG 8
 #define SIZEOF_UNSIGNED_SHORT 2
-- 
2.35.3


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


Re: grub shell: unkown commands alwasy exit with zero code

2024-01-16 Thread Michael Chang via Grub-devel
On Fri, Jan 12, 2024 at 05:58:02PM +0100, Itxaka serrano wrote:
> Hey all,
> 
> I opened a bug because this behaviour doesnt seem correct to me:
> 
> https://savannah.gnu.org/bugs/?65154
> 
> 
> Example:
> 
> grub> hello
> error: ../../grub-core/script/function.c:119:can't find command `hello'.
> grub> echo $?
> 0
> 
> 
> Kind of weird because on the code it seems like its returning a
> GRUB_ERR_UNKNOWN_COMMAND which should not be zero. I had a quick look and
> maybe its becuase on line 1018 of grub-core/script/execute.c we print the
> error but always return 0
> https://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/script/execute.c#n1018
> 
> Is this expected behaviour or is it a mistake and we should not only print
> the error but return the actual error?

The behavior is expected: 

https://git.savannah.gnu.org/cgit/grub.git/commit/?id=bc028f2f86.

Given the limited context, it remains unclear if the rationale behind
this change can be easily retraced today.

My take is that this modification may have been implemented to support
the continued functionality of older `grub.cfg` files, even after
certain commands have been removed. This ensures compatibility with the
latest version of GRUB. Alternatively, it seems reasonable to halt
execution when encountering a missing command, considering the potential
consequence of such situations.

Thanks,
Michael

> 
> Cheers,
> Itxaka

> ___
> 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