[PATCH v4 08/12] tests/tpm2_key_protector_test: Simplify the NV index mode test

2025-03-26 Thread Gary Lin via Grub-devel
Since 'grub-protect' already supports NV index mode, tpm2_seal_nv() is
replaced with one 'grub-protect' command to simplify the test script.

'tpm2_evictcontrol' is also replaced with 'grub-protect --tpm2-evict'.

Signed-off-by: Gary Lin 
---
 tests/tpm2_key_protector_test.in | 108 +--
 1 file changed, 15 insertions(+), 93 deletions(-)

diff --git a/tests/tpm2_key_protector_test.in b/tests/tpm2_key_protector_test.in
index a92e5f498..07477ba2a 100644
--- a/tests/tpm2_key_protector_test.in
+++ b/tests/tpm2_key_protector_test.in
@@ -225,105 +225,22 @@ EOF
 fi
 }
 
-tpm2_seal_nv () {
-keyfile="$1"
-nv_index="$2"
-pcr_list="$3"
-
-primary_file=${tpm2testdir}/primary.ctx
-session_file=${tpm2testdir}/session.dat
-policy_file=${tpm2testdir}/policy.dat
-keypub_file=${tpm2testdir}/key.pub
-keypriv_file=${tpm2testdir}/key.priv
-name_file=${tpm2testdir}/sealing.name
-sealing_ctx_file=${tpm2testdir}/sealing.ctx
-
-# Since we don't run a resource manager on our swtpm instance, it has
-# to flush the transient handles after tpm2_createprimary, tpm2_create
-# and tpm2_load to avoid the potential out-of-memory (0x902) errors.
-# Ref: 
https://github.com/tpm2-software/tpm2-tools/issues/1338#issuecomment-469689398
-
-# Create the primary object
-tpm2_createprimary -Q -C o -g sha256 -G ecc -c "${primary_file}" || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to create the primary object: ${ret}" >&2
-   return 1
-fi
-tpm2_flushcontext -t || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to flush the transient handles: ${ret}" >&2
-   return 1
-fi
-
-# Create the policy object
-tpm2_startauthsession -S "${session_file}" || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to start auth session: ${ret}" >&2
-   return 1
-fi
-tpm2_policypcr -Q -S "${session_file}" -l "${pcr_list}" -L 
"${policy_file}" || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to create the policy object: ${ret}" >&2
-   return 1
-fi
-tpm2_flushcontext "${session_file}" || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to flush the transient handles: ${ret}" >&2
-   return 1
-fi
-
-# Seal the key into TPM
-tpm2_create -Q \
-   -C "${primary_file}" \
-   -u "${keypub_file}" \
-   -r "${keypriv_file}" \
-   -L "${policy_file}" \
-   -i "${keyfile}" || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to seal \"${keyfile}\": ${ret}" >&2
-   return 1
-fi
-tpm2_flushcontext -t || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to flush the transient handles: ${ret}" >&2
-   return 1
-fi
-
-tpm2_load -Q \
-   -C "${primary_file}" \
-   -u "${keypub_file}" \
-   -r "${keypriv_file}" \
-   -n "${name_file}" \
-   -c "${sealing_ctx_file}" || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to load the sealed key into TPM: ${ret}" >&2
-   return 1
-fi
-tpm2_flushcontext -t || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to flush the transient handles: ${ret}" >&2
-   return 1
-fi
-
-tpm2_evictcontrol -Q -C o -c "${sealing_ctx_file}" ${nv_index} || ret=$?
-if [ "${ret}" -ne 0 ]; then
-   echo "Failed to store the sealed key into ${nv_index}: ${ret}" >&2
-   return 1
-fi
-
-return 0
-}
-
 tpm2_seal_unseal_nv() {
 nv_index="0x8100"
-pcr_list="sha256:0,1"
 
 grub_cfg=${tpm2testdir}/testcase.cfg
 
 # Seal the key into a NV index guarded by PCR 0 and 1
-tpm2_seal_nv "${lukskeyfile}" ${nv_index} ${pcr_list} || ret=$?
+grub-protect ${extra_opt} \
+   --tpm2-device="${tpm2dev}" \
+   --action=add \
+   --protector=tpm2 \
+   --tpm2-bank=sha256 \
+   --tpm2-pcrs=0,1 \
+   --tpm2-keyfile="${lukskeyfile}" \
+   --tpm2-nvindex="${nv_index}" || ret=$?
 if [ "${ret}" -ne 0 ]; then
-   echo "Failed to seal the secret key into ${nv_index}" >&2
+   echo "Failed to seal the secret key into ${nv_index}: ${ret}" >&2
return 99
 fi
 
@@ -340,7 +257,12 @@ EOF
 ${grubshell} --timeout=${timeout} --emu-opts="-t ${tpm2dev}" < 
"${grub_cfg}" > "${testoutput}" || ret=$?
 
 # Remove the object from the NV index
-tpm2_evictcontrol -Q -C o -c "${nv_index}" || :
+grub-protect \
+   --tpm2-device="${tpm2dev}" \
+   --protector=tpm2 \
+   --action=remove \
+   --tpm2-nvindex=${nv_index} \
+   --tpm2-evict || :
 
 if [ "${ret}" -eq 0 ]; then
if ! grep -q "^${vtext}$" "${testoutput}"; then
-- 
2.43.0


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


Re: [PATCH v4 07/12] util/grub-protect: Support NV index mode

2025-03-26 Thread Daniel Kiper via Grub-devel
On Fri, Mar 21, 2025 at 03:59:03PM +0800, Gary Lin wrote:
> This commit implements the missing NV index mode support in
> 'grub-protect'. NV index mode stores the sealed key in the TPM
> non-volatile memory (NVRAM) instead of a file. There are two supported
> types of TPM handles.
>
> 1. Persistent handle (0x8100~0x81FF)
>Only the raw format is supported due to the limitation of persistent
>handles. This 'grub-protect' command seals the key into the
>persistent handle 0x8100.
>
>   # grub-protect \
>   --protector=tpm2 \
>   --action=add \
>   --tpm2-bank=sha256 \
>   --tpm2-pcrs=7,11 \
>   --tpm2-keyfile=luks-key \
>   --tpm2-nvindex=0x8100
>
> 2. NV index handle (0x100~0x1FF)
>Both TPM 2.0 Key File format and the raw format are supported by NV
>index handles. Here is the 'grub-protect' command to seal the key in
>TPM 2.0 Key File format into the NV index handle 0x100.
>
>   # grub-protect \
>   --protector=tpm2 \
>   --action=add \
>   --tpm2key \
>   --tpm2-bank=sha256 \
>   --tpm2-pcrs=7,11 \
>   --tpm2-keyfile=luks-key \
>   --tpm2-nvindex=0x100
>
> Besides the 'add' action, the corresponding 'remove' action is also
> introduced. To remove the data from a persistent or NV index handle,
> just use '--tpm2-nvindex=HANDLE' combining with '--tpm2-evict'. This
> sample command removes the data from the NV index handle 0x100.
>
>   # grub-protect \
>   --protector=tpm2 \
>   --action=remove \
>   --tpm2-evict \
>   --tpm2-nvindex=0x100
>
> Also set and check the boolean variables with true/false instead of 1/0.
>
> Signed-off-by: Gary Lin 
> Reviewed-by: Stefan Berger 

Reviewed-by: Daniel Kiper 

Daniel

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


Re: [PATCH v4 08/12] tests/tpm2_key_protector_test: Simplify the NV index mode test

2025-03-26 Thread Daniel Kiper via Grub-devel
On Fri, Mar 21, 2025 at 03:59:04PM +0800, Gary Lin wrote:
> Since 'grub-protect' already supports NV index mode, tpm2_seal_nv() is
> replaced with one 'grub-protect' command to simplify the test script.
>
> 'tpm2_evictcontrol' is also replaced with 'grub-protect --tpm2-evict'.
>
> Signed-off-by: Gary Lin 

Reviewed-by: Daniel Kiper 

Daniel

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


Re: [PATCH] tss2: restore buffer offset on tpm2_submit_command retry

2025-03-26 Thread Daniel Kiper
On Mon, Mar 10, 2025 at 03:48:16PM +0800, Gary Lin via Grub-devel wrote:
> On Thu, Mar 06, 2025 at 08:46:52PM +0100, Yann Diorcet wrote:
> > When tpm2_submit_command_real is called for a retry, the content of
> > out buffer can already be set with previous grub_tcg2_submit_command
> > call's reply. Restore previous offset allowing the next
> > tpm2_submit_command_real calls to succeed.
> >
> > This solves the issues occurring during TPM_CC_Load command on the 
> > integrated
> > TPM 2.0 in Intel Elkhart Lake chip.
> >
> Thanks for catching this issue!
>
> > Signed-off-by: Diorcet Yann 

Sadly this patch does not apply to upstream...

> > ---
> >  grub-core/lib/tss2/tpm2_cmd.c | 4 
> >  1 file changed, 4 insertions(+)
> >
> > diff --git a/grub-core/lib/tss2/tpm2_cmd.c b/grub-core/lib/tss2/tpm2_cmd.c
> > index 6d25db1ab..6be6c8fc5 100644
> > --- a/grub-core/lib/tss2/tpm2_cmd.c
> > +++ b/grub-core/lib/tss2/tpm2_cmd.c
> > @@ -85,6 +85,7 @@ tpm2_submit_command (const TPMI_ST_COMMAND_TAG_t tag,
> >  struct grub_tpm2_buffer *out)
> >  {
> >TPM_RC_t err;
> > +  grub_size_t offset = out->offset;
> >int retry_cnt = 0;
> >
> >/* Catch TPM_RC_RETRY and send the command again */
> Since we always need a clean output buffer, maybe we can call
> 'grub_tpm2_buffer_init(out)' right before 'tpm2_submit_command_real()'
> to make sure the output buffer is always initialized. Besides, with this
> change, we can remove all 'grub_tpm2_buffer_init (&out)' in the TPM2
> command functions.

It would be nice if Gary's comment is taken into account too.

Daniel

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


Re: [PATCH v2 3/3] blsuki: Add uki command to load Unified Kernel Image entries

2025-03-26 Thread Oliver Steffen via Grub-devel
On Tue, Mar 25, 2025 at 8:16 AM Alec Brown via Grub-devel
 wrote:
>
> A Unified Kernel Image is a single UEFI PE file that combines a UEFI boot 
> stub,
> a Linux kernel image, an initrd, and further resources. The uki command will
> locate where the uki file is and create a GRUB menu entry to load it.
>
> Signed-off-by: Alec Brown 

Nice to see someone picking that back up. I had proposed something
similar a while ago,
although over at the rhboot grub, because it already had blscfg
support back then.
https://github.com/rhboot/grub2/pull/119

Oliver

> ---
>  docs/grub.texi  |  26 +++
>  grub-core/commands/blsuki.c | 415 ++--
>  include/grub/menu.h |   2 +
>  3 files changed, 428 insertions(+), 15 deletions(-)
>
> diff --git a/docs/grub.texi b/docs/grub.texi
> index 19b0cc024..9317b4130 100644
> --- a/docs/grub.texi
> +++ b/docs/grub.texi
> @@ -6491,6 +6491,7 @@ you forget a command, you can run the command 
> @command{help}
>  * tpm2_key_protector_clear::Clear the TPM2 key protector
>  * true::Do nothing, successfully
>  * trust::   Add public key to list of trusted keys
> +* uki:: Load Unified Kernel Image menu entries
>  * unset::   Unset an environment variable
>  @comment * vbeinfo:: List available video modes
>  * verify_detached:: Verify detached digital signature
> @@ -8164,6 +8165,31 @@ Unset the environment variable @var{envvar}.
>  @end deffn
>
>
> +@node uki
> +@subsection uki
> +
> +@deffn Command uki [@option{--path} dir] [@option{--show-default}] 
> [@option{--show-non-default}] [@option{--entry} file]
> +Load Unified Kernel Image entries into the GRUB menu.
> +
> +The @option{--path} option overrides the default path to the directory 
> containing
> +the UKI entries. If this option isn't used, the default location is
> +/EFI/Linux in the EFI system partition.
> +
> +The @option{--show-default} option allows the default boot entry to be added 
> to the
> +GRUB menu from the UKI entries.
> +
> +The @option{--show-non-default} option allows non-default boot entries to be 
> added to
> +the GRUB menu from the UKI entries.
> +
> +The @option{--entry} option allows specific boot entries to be added to the 
> GRUB menu
> +from the UKI entries.
> +
> +The @option{--entry}, @option{--show-default}, and 
> @option{--show-non-default} options
> +are used to filter which UKI entries are added to the GRUB menu. If none are
> +used, all entries in the default location or the location specified by 
> @option{--path}
> +will be added to the GRUB menu.
> +@end deffn
> +
>  @ignore
>  @node vbeinfo
>  @subsection vbeinfo
> diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c
> index 12a9a1ed1..bf284e002 100644
> --- a/grub-core/commands/blsuki.c
> +++ b/grub-core/commands/blsuki.c
> @@ -39,9 +39,21 @@
>  #define GRUB_BOOT_DEVICE ""
>  #endif
>
> +#ifdef GRUB_MACHINE_EFI
> +#include 
> +#include 
> +#include 
> +#endif
> +
>  GRUB_MOD_LICENSE ("GPLv3+");
>
>  #define GRUB_BLS_CONFIG_PATH "/loader/entries/"
> +#define GRUB_UKI_CONFIG_PATH "/EFI/Linux"
> +
> +#define GRUB_BLS_CMD 1
> +#define GRUB_UKI_CMD 2
> +
> +static int cmd_type = 0;
>
>  static const struct grub_arg_option bls_opt[] =
>{
> @@ -52,6 +64,17 @@ static const struct grub_arg_option bls_opt[] =
>  {0, 0, 0, 0, 0, 0}
>};
>
> +#ifdef GRUB_MACHINE_EFI
> +static const struct grub_arg_option uki_opt[] =
> +  {
> +{"path", 'p', 0, N_("Specify path to find UKI entries."), N_("DIR"), 
> ARG_TYPE_PATHNAME},
> +{"show-default", 'd', 0, N_("Allow the default UKI entry to be added to 
> the GRUB menu."), 0, ARG_TYPE_NONE},
> +{"show-non-default", 'n', 0, N_("Allow the non-default UKI entries to be 
> added to the GRUB menu."), 0, ARG_TYPE_NONE},
> +{"entry", 'e', 0, N_("Allow specificUKII entries to be added to the GRUB 
> menu."), N_("FILE"), ARG_TYPE_FILE},
> +{0, 0, 0, 0, 0, 0}
> +  };
> +#endif
> +
>  struct keyval
>  {
>const char *key;
> @@ -288,6 +311,206 @@ bls_read_entry (grub_file_t f, grub_blsuki_entry_t 
> *entry)
>return err;
>  }
>
> +#ifdef GRUB_MACHINE_EFI
> +static grub_err_t
> +uki_read_entry (grub_file_t f, grub_blsuki_entry_t *entry)
> +{
> +  struct grub_msdos_image_header *dos = NULL;
> +  struct grub_pe_image_header *pe = NULL;
> +  grub_off_t section_offset = 0;
> +  struct grub_pe32_section_table *section = NULL;
> +  struct grub_pe32_coff_header *coff_header = NULL;
> +  char *val = NULL;
> +  char *key = NULL;
> +  const char *target[] = {".cmdline", ".osrel", ".linux", NULL};
> +  bool has_linux = false;
> +  grub_err_t err = GRUB_ERR_NONE;
> +
> +  dos = grub_zalloc (sizeof (*dos));
> +  if (dos == NULL)
> +return grub_errno;
> +  if (grub_file_read (f, dos, sizeof (*dos)) < (grub_ssize_t) sizeof (*dos))
> +{
> +  err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read UKI image 
> 

Re: [PATCH v6 1/2] lsefi: fixed memory leaks

2025-03-26 Thread Daniel Kiper
On Wed, Mar 19, 2025 at 01:47:56PM +0100, Renaud Métrich via Grub-devel wrote:
> Signed-off-by: Renaud Métrich 
> ---
>  grub-core/commands/efi/lsefi.c | 4 
>  1 file changed, 4 insertions(+)
>
> diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
> index 7b8316d41..bda25a3a9 100644
> --- a/grub-core/commands/efi/lsefi.c
> +++ b/grub-core/commands/efi/lsefi.c
> @@ -127,8 +127,12 @@ grub_cmd_lsefi (grub_command_t cmd __attribute__ 
> ((unused)),
>   grub_printf ("  %pG\n", protocols[j]);
>   }
>
> +  if (protocols)
> + grub_efi_free_pool (protocols);

Again, the grub_efi_free_pool() does not exist in upstream. I pointed
out this issue in v3 and it is still not fixed... :-(

Daniel

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


Re: [PATCH v4 12/12] INSTALL: Document the packages needed for TPM2 key protector tests

2025-03-26 Thread Daniel Kiper via Grub-devel
On Fri, Mar 21, 2025 at 03:59:08PM +0800, Gary Lin wrote:
> The TPM2 key protector tests require two external packages: swtpm-tools
> and tpm2-tools. Add those two packages to the INSTALL file to inform
> the user to install those packages before starting the TPM2 key protector
> tests.
>
> Signed-off-by: Gary Lin 

Reviewed-by: Daniel Kiper 

Daniel

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


[PATCH v2 09/21] appended signatures: parse PKCS#7 signedData and X.509 certificates

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

This code allows us to parse:

 - PKCS#7 signedData messages. Only a single signerInfo is supported,
   which is all that the Linux sign-file utility supports creating
   out-of-the-box. Only RSA, SHA-256 and SHA-512 are supported.
   Any certificate embedded in the PKCS#7 message will be ignored.

 - X.509 certificates: at least enough to verify the signatures on the
   PKCS#7 messages. We expect that the certificates embedded in grub will
   be leaf certificates, not CA certificates. The parser enforces this.

 - X.509 certificates support the Extended Key Usage extension and handle
   it by verifying that the certificate has a Code Signing usage.

Signed-off-by: Javier Martinez Canillas  # EKU support
Reported-by: Michal Suchanek  # key usage issue
Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/appendedsig/appendedsig.h | 110 +++
 grub-core/commands/appendedsig/asn1util.c|  98 ++
 grub-core/commands/appendedsig/pkcs7.c   | 460 +
 grub-core/commands/appendedsig/x509.c| 953 +++
 4 files changed, 1621 insertions(+)
 create mode 100644 grub-core/commands/appendedsig/appendedsig.h
 create mode 100644 grub-core/commands/appendedsig/asn1util.c
 create mode 100644 grub-core/commands/appendedsig/pkcs7.c
 create mode 100644 grub-core/commands/appendedsig/x509.c

diff --git a/grub-core/commands/appendedsig/appendedsig.h 
b/grub-core/commands/appendedsig/appendedsig.h
new file mode 100644
index 0..3f4d7002e
--- /dev/null
+++ b/grub-core/commands/appendedsig/appendedsig.h
@@ -0,0 +1,110 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020, 2022 Free Software Foundation, Inc.
+ *  Copyright (C) 2020, 2022 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 
+#include 
+
+extern asn1_node _gnutls_gnutls_asn;
+extern asn1_node _gnutls_pkix_asn;
+
+#define MAX_OID_LEN 32
+
+/*
+ * One or more x509 certificates.
+ * We do limited parsing: extracting only the serial, CN and RSA public key.
+ */
+struct x509_certificate
+{
+  struct x509_certificate *next;
+  grub_uint8_t *serial;
+  grub_size_t serial_len;
+  char *subject;
+  grub_size_t subject_len;
+  /* We only support RSA public keys. This encodes [modulus, publicExponent] */
+  gcry_mpi_t mpis[2];
+};
+
+/*
+ * A PKCS#7 signedData signerInfo.
+ */
+struct pkcs7_signerInfo
+{
+  const gcry_md_spec_t *hash;
+  gcry_mpi_t sig_mpi;
+};
+
+/*
+ * A PKCS#7 signedData message.
+ * We make no attempt to match intelligently, so we don't save any info about
+ * the signer.
+ */
+struct pkcs7_signedData
+{
+  int signerInfo_count;
+  struct pkcs7_signerInfo *signerInfos;
+};
+
+/* Do libtasn1 init */
+int
+asn1_init (void);
+
+/*
+ * Import a DER-encoded certificate at 'data', of size 'size'.
+ * Place the results into 'results', which must be already allocated.
+ */
+grub_err_t
+parse_x509_certificate (const void *data, grub_size_t size, struct 
x509_certificate *results);
+
+/*
+ * Release all the storage associated with the x509 certificate.
+ * If the caller dynamically allocated the certificate, it must free it.
+ * The caller is also responsible for maintenance of the linked list.
+ */
+void
+certificate_release (struct x509_certificate *cert);
+
+/*
+ * Parse a PKCS#7 message, which must be a signedData message.
+ * The message must be in 'sigbuf' and of size 'data_size'. The result is
+ * placed in 'msg', which must already be allocated.
+ */
+grub_err_t
+parse_pkcs7_signedData (const void *sigbuf, grub_size_t data_size, struct 
pkcs7_signedData *msg);
+
+/*
+ * Release all the storage associated with the PKCS#7 message.
+ * If the caller dynamically allocated the message, it must free it.
+ */
+void
+pkcs7_signedData_release (struct pkcs7_signedData *msg);
+
+/*
+ * Read a value from an ASN1 node, allocating memory to store it.
+ * It will work for anything where the size libtasn1 returns is right:
+ *  - Integers
+ *  - Octet strings
+ *  - DER encoding of other structures
+ * It will _not_ work for things where libtasn1 size requires adjustment:
+ *  - Strings that require an extra null byte at the end
+ *  - Bit strings because libtasn1 returns the length in bits, not bytes.
+ *
+ * If the function returns a non-NULL value, the caller must free it.
+ */
+void *
+gr

Re: [PATCH v2] fs/ntfs: Check at->attr_cur after calling next_attribute()

2025-03-26 Thread Ross Philipson via Grub-devel

On 3/20/25 3:54 PM, Andrew Hamilton wrote:

A regression was introduced recently as a part of the series of
filesystem related patches to address some CVEs found in GRUB.

This issue may cause either an infinite loop at startup when
accessing certain valid NTFS file systems, or may cause a crash
due to a NULL pointer deference on systems where "NULL" address
is invalid (such as may happen when calling grub-mount from
the operating system level).

Correct this issue by checking that at->attr_cur != NULL inside
find_attr.

Fixes: 
https://urldefense.com/v3/__https://savannah.gnu.org/bugs/?66855__;!!ACWV5N9M2RV99hQ!MlJos-JMiQzMR6XYrdHvoK1BCnCXRxxGUcBEZNXYJRmSe_ADsCWVO0Yzdk8RkShkoHuN6MBOT4mvwvWNMvBT$


Reviewed-by: Ross Philipson 



Co-authored-by: B Horn 
Co-authored-by: Andrew Hamilton 
Signed-off-by: Andrew Hamilton 
---
  grub-core/fs/ntfs.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
index 960833a34..a29e10401 100644
--- a/grub-core/fs/ntfs.c
+++ b/grub-core/fs/ntfs.c
@@ -387,7 +387,8 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
  }
at->attr_cur = at->attr_nxt;
mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
-  while (at->attr_cur < mft_end && *at->attr_cur != 0xFF)
+  while (at->attr_cur != NULL && at->attr_cur < mft_end
+ && *at->attr_cur != 0xFF)
  {
at->attr_nxt = next_attribute (at->attr_cur, at->end);
if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)



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


[PATCH v2 13/21] ieee1275: enter lockdown based on /ibm,secure-boot

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

If the 'ibm,secure-boot' property of the root node is 2 or greater,
enter lockdown.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 docs/grub.texi |  2 +-
 grub-core/Makefile.core.def|  1 +
 grub-core/kern/ieee1275/init.c | 35 ++
 include/grub/lockdown.h|  3 ++-
 4 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 25a51dee8..52e26c8fd 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -9019,7 +9019,7 @@ platforms.
 @section Lockdown when booting on a secure setup
 
 The GRUB can be locked down when booted on a secure boot environment, for 
example
-if the UEFI secure boot is enabled. On a locked down configuration, the GRUB 
will
+if the UEFI or Power secure boot is enabled. On a locked down configuration, 
the GRUB will
 be restricted and some operations/commands cannot be executed. This also 
includes
 limiting which filesystems are supported to those thought to be more robust and
 widely used within GRUB.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 9cf4a6009..1ed55b0e3 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -331,6 +331,7 @@ kernel = {
   powerpc_ieee1275 = kern/powerpc/cache.S;
   powerpc_ieee1275 = kern/powerpc/dl.c;
   powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
+  powerpc_ieee1275 = kern/lockdown.c;
 
   sparc64_ieee1275 = kern/sparc64/cache.S;
   sparc64_ieee1275 = kern/sparc64/dl.c;
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index dfbd0b899..ba3cb7cfa 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -49,6 +49,7 @@
 #if defined(__powerpc__) || defined(__i386__)
 #include 
 #endif
+#include 
 
 /* The maximum heap size we're going to claim at boot. Not used by sparc. */
 #ifdef __i386__
@@ -953,6 +954,38 @@ grub_parse_cmdline (void)
 }
 }
 
+static void
+grub_get_ieee1275_secure_boot (void)
+{
+  grub_ieee1275_phandle_t root;
+  int rc;
+  grub_uint32_t is_sb;
+
+  if (grub_ieee1275_finddevice ("/", &root))
+{
+  grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node");
+  return;
+}
+
+  rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb, 
sizeof (is_sb), 0);
+  if (rc < 0)
+{
+  grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /ibm,secure-boot 
property");
+  return;
+}
+  /*
+   * ibm,secure-boot:
+   * 0 - disabled
+   * 1 - audit
+   * 2 - enforce
+   * 3 - enforce + OS-specific behaviour
+   *
+   * We only support enforce.
+   */
+  if (is_sb >= 2)
+grub_lockdown ();
+}
+
 grub_addr_t grub_modbase;
 
 void
@@ -978,6 +1011,8 @@ grub_machine_init (void)
 #else
   grub_install_get_time_ms (grub_rtc_get_time_ms);
 #endif
+
+  grub_get_ieee1275_secure_boot ();
 }
 
 void
diff --git a/include/grub/lockdown.h b/include/grub/lockdown.h
index 40531fa82..ebfee4bf0 100644
--- a/include/grub/lockdown.h
+++ b/include/grub/lockdown.h
@@ -24,7 +24,8 @@
 #define GRUB_LOCKDOWN_DISABLED   0
 #define GRUB_LOCKDOWN_ENABLED1
 
-#ifdef GRUB_MACHINE_EFI
+#if defined(GRUB_MACHINE_EFI) || \
+(defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275))
 extern void
 EXPORT_FUNC (grub_lockdown) (void);
 extern int
-- 
2.43.5


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


[PATCH v2 11/21] appended signatures: verification tests

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

These tests are run through all_functional_test and test a range
of commands and behaviours.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/Makefile.core.def   |   6 +
 grub-core/tests/appended_signature_test.c | 258 ++
 grub-core/tests/appended_signatures.h | 975 ++
 grub-core/tests/lib/functional_test.c |   1 +
 4 files changed, 1240 insertions(+)
 create mode 100644 grub-core/tests/appended_signature_test.c
 create mode 100644 grub-core/tests/appended_signatures.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index d693986c6..9cf4a6009 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2194,6 +2194,12 @@ module = {
   common = tests/setjmp_test.c;
 };
 
+module = {
+  name = appended_signature_test;
+  common = tests/appended_signature_test.c;
+  common = tests/appended_signatures.h;
+};
+
 module = {
   name = signature_test;
   common = tests/signature_test.c;
diff --git a/grub-core/tests/appended_signature_test.c 
b/grub-core/tests/appended_signature_test.c
new file mode 100644
index 0..3d5b97391
--- /dev/null
+++ b/grub-core/tests/appended_signature_test.c
@@ -0,0 +1,258 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020, 2022 Free Software Foundation, Inc.
+ *  Copyright (C) 2020, 2022 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "appended_signatures.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define PROC_FILE(identifier, file_name)\
+  static char *get_##identifier (grub_size_t *sz)   \
+  { \
+char *ret;  \
+\
+*sz = identifier##_len; \
+ret = grub_malloc (*sz);\
+if (ret)\
+  grub_memcpy (ret, identifier, *sz);   \
+return ret; \
+  } \
+\
+  static struct grub_procfs_entry identifier##_entry = { .name = file_name, \
+ .get_contents = 
get_##identifier };
+
+#define DEFINE_TEST_CASE(case_name) PROC_FILE (case_name, #case_name)
+
+#define DO_TEST(case_name, is_valid)   \
+  {\
+grub_procfs_register (#case_name, &case_name##_entry); \
+do_verify ("(proc)/" #case_name, is_valid);\
+grub_procfs_unregister (&case_name##_entry);   \
+  }
+
+DEFINE_TEST_CASE (hi_signed);
+DEFINE_TEST_CASE (hi_signed_sha256);
+DEFINE_TEST_CASE (hj_signed);
+DEFINE_TEST_CASE (short_msg);
+DEFINE_TEST_CASE (unsigned_msg);
+DEFINE_TEST_CASE (hi_signed_2nd);
+DEFINE_TEST_CASE (hi_double);
+DEFINE_TEST_CASE (hi_double_extended);
+
+PROC_FILE (certificate_der, "certificate.der")
+PROC_FILE (certificate2_der, "certificate2.der")
+PROC_FILE (certificate_printable_der, "certificate_printable.der")
+PROC_FILE (certificate_eku_der, "certificate_eku.der")
+
+static void
+do_verify (const char *f, int is_valid)
+{
+  grub_command_t cmd;
+  char *args[] = { (char *) f, NULL };
+  grub_err_t err;
+
+  cmd = grub_command_find ("verify_appended");
+  if (!cmd)
+{
+  grub_test_assert (0, "can't find command `%s'", "verify_appended");
+  return;
+}
+  err = (cmd->func) (cmd, 1, args);
+  if (is_valid)
+{
+  grub_test_assert (err == GRUB_ERR_NONE, "verification of %s failed: %d: 
%s",
+f, grub_errno, grub_errmsg);
+}
+  else
+{
+  grub_test_assert (err == GRUB_ERR_BAD_SIGNATURE,
+"verification of %s unexpectedly succeeded", f);
+}
+  grub_errno = GRUB_ERR_NONE;

[PATCH v2 14/21] ieee1275: Platform Keystore (PKS) Support

2025-03-26 Thread Sudhakar Kuppusamy
enhancing the infrastructure to enable the Platform Keystore (PKS) feature,
which provides access to the SB VERSION, DB, and DBX secure boot variables
from PKS.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/Makefile.am  |   1 +
 grub-core/Makefile.core.def|   1 +
 grub-core/kern/powerpc/ieee1275/ieee1275.c | 140 +
 include/grub/powerpc/ieee1275/ieee1275.h   |  14 +++
 4 files changed, 156 insertions(+)
 create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index e50db8106..b516e139b 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -241,6 +241,7 @@ KERNEL_HEADER_FILES += 
$(top_builddir)/include/grub/machine/kernel.h
 endif
 
 if COND_powerpc_ieee1275
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1ed55b0e3..95bccce5d 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -328,6 +328,7 @@ kernel = {
   extra_dist = video/sis315_init.c;
   mips_loongson = commands/keylayouts.c;
 
+  powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c;
   powerpc_ieee1275 = kern/powerpc/cache.S;
   powerpc_ieee1275 = kern/powerpc/dl.c;
   powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
diff --git a/grub-core/kern/powerpc/ieee1275/ieee1275.c 
b/grub-core/kern/powerpc/ieee1275/ieee1275.c
new file mode 100644
index 0..f685afcff
--- /dev/null
+++ b/grub-core/kern/powerpc/ieee1275/ieee1275.c
@@ -0,0 +1,140 @@
+/* of.c - Access the Open Firmware client interface.  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2004,2005,2007,2008,2009  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 .
+ */
+#include 
+#include 
+#include 
+
+#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) - 1)
+
+int
+grub_ieee1275_test (const char *name, grub_ieee1275_cell_t *missing)
+{
+  struct test_args
+  {
+struct grub_ieee1275_common_hdr common;
+grub_ieee1275_cell_t name;
+grub_ieee1275_cell_t missing;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "test", 1, 1);
+  args.name = (grub_ieee1275_cell_t) name;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+return -1;
+
+  if (args.missing == IEEE1275_CELL_INVALID)
+return -1;
+
+  *missing = args.missing;
+
+  return 0;
+}
+
+int
+grub_ieee1275_pks_max_object_size (grub_size_t *result)
+{
+  struct mos_args
+  {
+struct grub_ieee1275_common_hdr common;
+grub_ieee1275_cell_t size;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "pks-max-object-size", 0, 1);
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+return -1;
+
+  if (args.size == IEEE1275_CELL_INVALID)
+return -1;
+
+  *result = args.size;
+
+  return 0;
+}
+
+int
+grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
+   grub_size_t label_len, grub_uint8_t *buffer,
+   grub_size_t buffer_len, grub_size_t *data_len,
+   grub_uint32_t *policies)
+{
+  struct pks_read_args
+  {
+struct grub_ieee1275_common_hdr common;
+grub_ieee1275_cell_t consumer;
+grub_ieee1275_cell_t label;
+grub_ieee1275_cell_t label_len;
+grub_ieee1275_cell_t buffer;
+grub_ieee1275_cell_t buffer_len;
+grub_ieee1275_cell_t data_len;
+grub_ieee1275_cell_t policies;
+grub_ieee1275_cell_t rc;
+  } args;
+
+  INIT_IEEE1275_COMMON (&args.common, "pks-read-object", 5, 3);
+  args.consumer = (grub_ieee1275_cell_t) consumer;
+  args.label = (grub_ieee1275_cell_t) label;
+  args.label_len = (grub_ieee1275_cell_t) label_len;
+  args.buffer = (grub_ieee1275_cell_t) buffer;
+  args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
+
+  if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+return -1;
+
+  if (args.data_len == IEEE1275_CELL_INVALID)
+return -1;
+
+  *data_len = args.data_len;
+  *policies = args.policies;
+
+  return (int) args.rc;
+}
+
+int
+grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
+   

[PATCH v2 17/21] appendedsig: While verifying the kernel, use trusted and distrusted lists

2025-03-26 Thread Sudhakar Kuppusamy
To verify the kernel's signature: verify the kernel binary against lists of 
binary hashes
that are either distrusted or trusted. If it is not list in either trusted or 
distrusted hashes list
then the trusted keys from the trusted key list are used to verify the 
signature.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/appendedsig/appendedsig.c | 199 +--
 1 file changed, 142 insertions(+), 57 deletions(-)

diff --git a/grub-core/commands/appendedsig/appendedsig.c 
b/grub-core/commands/appendedsig/appendedsig.c
index b24112050..3abb45ae0 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -454,6 +454,83 @@ extract_appended_signature (const grub_uint8_t *buf, 
grub_size_t bufsize,
   return parse_pkcs7_signedData (appsigdata, pkcs7_size, &sig->pkcs7);
 }
 
+static grub_err_t
+get_binary_hash (const grub_size_t binary_hash_size, const grub_uint8_t *data,
+ const grub_size_t data_size, grub_uint8_t *hash, grub_size_t 
*hash_size)
+{
+  grub_uuid_t guid = { 0 };
+
+  /* support SHA256, SHA384 and SHA512 for binary hash */
+  if (binary_hash_size == 32)
+grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE);
+  else if (binary_hash_size == 48)
+grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE);
+  else if (binary_hash_size == 64)
+grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE);
+  else
+{
+  grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") 
and skipping binary hash\n",
+binary_hash_size);
+  return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+  return get_hash (&guid, data, data_size, hash, hash_size);
+}
+
+/*
+ * Verify binary hash against the list of binary hashes that are distrusted
+ * and trusted.
+ * The following errors can occur:
+ *  - GRUB_ERR_BAD_SIGNATURE: indicates that the hash is distrusted.
+ *  - GRUB_ERR_NONE: the hash is trusted, since it was found in the trusted 
hashes list
+ *  - GRUB_ERR_EOF: the hash could not be found in the hashes list
+ */
+static grub_err_t
+verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size)
+{
+  grub_err_t rc = GRUB_ERR_NONE;
+  grub_size_t i = 0, hash_size = 0;
+  grub_uint8_t hash[GRUB_MAX_HASH_SIZE] = { 0 };
+
+  for (i = 0; i < dbx.signature_entries; i++)
+{
+  rc = get_binary_hash (dbx.signature_size[i], data, data_size, hash, 
&hash_size);
+  if (rc != GRUB_ERR_NONE)
+continue;
+
+  if (hash_size == dbx.signature_size[i] &&
+  grub_memcmp (dbx.signatures[i], hash, hash_size) == 0)
+{
+  grub_dprintf ("appendedsig", "the binary hash (%02x%02x%02x%02x) was 
listed as distrusted\n",
+hash[0], hash[1], hash[2], hash[3]);
+  return GRUB_ERR_BAD_SIGNATURE;
+}
+}
+
+  for (i = 0; i < db.signature_entries; i++)
+{
+  rc = get_binary_hash (db.signature_size[i], data, data_size, hash, 
&hash_size);
+  if (rc != GRUB_ERR_NONE)
+continue;
+
+  if (hash_size == db.signature_size[i] &&
+  grub_memcmp (db.signatures[i], hash, hash_size) == 0)
+{
+  grub_dprintf ("appendedsig", "verified with a trusted binary hash 
(%02x%02x%02x%02x)\n",
+hash[0], hash[1], hash[2], hash[3]);
+  return GRUB_ERR_NONE;
+}
+}
+
+  return GRUB_ERR_EOF;
+}
+
+
+/*
+ * Verify the kernel's integrity, the trusted key will be used from
+ * the trusted key list. If it fails, verify it against the list of binary 
hashes
+ * that are distrusted and trusted.
+ */
 static grub_err_t
 grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
 {
@@ -463,12 +540,12 @@ grub_verify_appended_signature (const grub_uint8_t *buf, 
grub_size_t bufsize)
   unsigned char *hash;
   gcry_mpi_t hashmpi;
   gcry_err_code_t rc;
-  struct x509_certificate *pk;
+  struct x509_certificate *cert;
   struct grub_appended_signature sig;
   struct pkcs7_signerInfo *si;
   int i;
 
-  if (!db.key_entries)
+  if (!db.key_entries && !db.signature_entries)
 return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify 
against"));
 
   err = extract_appended_signature (buf, bufsize, &sig);
@@ -476,69 +553,77 @@ grub_verify_appended_signature (const grub_uint8_t *buf, 
grub_size_t bufsize)
 return err;
 
   datasize = bufsize - sig.signature_len;
-
-  for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
+  err = verify_binary_hash (buf, datasize);
+  if (err != GRUB_ERR_EOF && err != GRUB_ERR_NONE)
 {
-  /*
-   * This could be optimised in a couple of ways:
-   * - we could only compute hashes once per hash type
-   * - we could track signer information and only verify where IDs match
-   * For now we do the naive O(trusted keys * pkcs7 signers) approach.
-   */
-  si = &sig.pkcs7.signerInfos[i];
-  co

[PATCH v2 16/21] appendedsig: The creation of trusted and distrusted lists

2025-03-26 Thread Sudhakar Kuppusamy
The trusted certificates and binary hashes, distrusted certificates and
binary/certificate hashes will be extracted from the platform keystore buffer
if Secure Boot is enabled with PKS.

In order to verify the integrity of the kernel, the extracted data
needs to be stored stored in the buffer db and dbx.

The trusted certificates will be extracted from the grub ELFNOTE if Secure Boot 
is
enabled with static key. In order to verify the integerity of the kernel,
the extracted data needs to be stored in the buffer db.

Note:-

If neither the trusted certificate nor binary hash exists in the distrusted 
list (dbx),
rejects it while extracting certificate/binary hash from the platform keystore 
buffer.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/appendedsig/appendedsig.c | 584 +--
 grub-core/kern/file.c|  34 ++
 include/grub/file.h  |   1 +
 3 files changed, 577 insertions(+), 42 deletions(-)

diff --git a/grub-core/commands/appendedsig/appendedsig.c 
b/grub-core/commands/appendedsig/appendedsig.c
index cbd227a3c..b24112050 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -34,7 +34,7 @@
 #include 
 #include 
 #include 
-
+#include 
 #include "appendedsig.h"
 
 GRUB_MOD_LICENSE ("GPLv3+");
@@ -64,8 +64,23 @@ struct grub_appended_signature
   struct pkcs7_signedData pkcs7;/* Parsed PKCS#7 data */
 };
 
-/* Trusted certificates for verifying appended signatures */
-struct x509_certificate *grub_trusted_key;
+/* This represents a trusted/distrusted list*/
+struct grub_database
+{
+  struct x509_certificate *keys; /* Certificates */
+  grub_size_t key_entries;   /* Number of certificates */
+  grub_uint8_t **signatures; /* Certificate/binary hashes */
+  grub_size_t *signature_size;   /* Size of certificate/binary hashes */
+  grub_size_t signature_entries; /* Number of certificate/binary hashes */
+};
+
+/* Trusted list */
+struct grub_database db = {.keys = NULL, .key_entries = 0, .signatures = NULL,
+   .signature_size = NULL, .signature_entries = 0};
+
+/* Distrusted list */
+struct grub_database dbx = {.signatures = NULL, .signature_size = NULL,
+.signature_entries = 0};
 
 /*
  * Force gcry_rsa to be a module dependency.
@@ -87,6 +102,13 @@ struct x509_certificate *grub_trusted_key;
  * also resolves our concerns about loading from the filesystem.
  */
 extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
+extern gcry_md_spec_t _gcry_digest_spec_sha224;
+extern gcry_md_spec_t _gcry_digest_spec_sha384;
+
+/* Free trusted list memory */
+static void free_trusted_list (void);
+/* Free distrusted list memory */
+static void free_distrusted_list (void);
 
 static enum
 {
@@ -95,6 +117,204 @@ static enum
   check_sigs_forced = 2
 } check_sigs = check_sigs_no;
 
+/*
+ * GUID can be used to determine the hashing function and
+ * generate the hash using determined hashing function.
+ */
+static grub_err_t
+get_hash (const grub_uuid_t *guid, const grub_uint8_t *data, const grub_size_t 
data_size,
+  grub_uint8_t *hash, grub_size_t *hash_size)
+{
+  gcry_md_spec_t *hash_func = NULL;
+
+  if (guid == NULL)
+return grub_error (GRUB_ERR_OUT_OF_RANGE, "GUID is null");
+
+  if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+   grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) 
== 0)
+hash_func = &_gcry_digest_spec_sha256;
+  else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 
||
+   grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) 
== 0)
+hash_func = &_gcry_digest_spec_sha384;
+  else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0 
||
+   grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) 
== 0)
+hash_func = &_gcry_digest_spec_sha512;
+  else
+return grub_error (GRUB_ERR_OUT_OF_RANGE, "Unsupported GUID for hash");
+
+  grub_memset (hash, 0, GRUB_MAX_HASH_SIZE);
+  grub_crypto_hash (hash_func, hash, data, data_size);
+  *hash_size =  hash_func->mdlen;
+
+  return GRUB_ERR_NONE;
+}
+
+/* Add the certificate/binary hash into the trusted/distrusted list */
+static grub_err_t
+add_hash (const grub_uint8_t **data, const grub_size_t data_size,
+  grub_uint8_t ***signature_list, grub_size_t **signature_size_list,
+  grub_size_t *signature_list_entries)
+{
+  grub_uint8_t **signatures = *signature_list;
+  grub_size_t *signature_size = *signature_size_list;
+  grub_size_t signature_entries = *signature_list_entries;
+
+  if (*data == NULL || data_size == 0)
+return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary hash 
data/size is null");
+
+  signatures = grub_realloc (signatures, sizeof (grub_uint8_t *) * 
(signature_entries + 1));
+  signature_size = grub_realloc (signatu

[PATCH v2 20/21] appendedsig: The grub command's trusted and distrusted support

2025-03-26 Thread Sudhakar Kuppusamy
To support the following trusted and distrusted commands

  1. trusted_list:
It will show the list of trusted certificates and binary hashes
  2. distrusted_list:
It will show the list of distrusted certificates and binary/certificate 
hashes
  3. trusted_certificate:
It will add the trusted certificate to the trusted list
  4. trusted_signature:
It will add the certificate/binary hash to the trusted list
  5. distrusted_certificate:
It will remove the trusted certificate from trsuted list
  6. distrusted_signature:
It will add the certificate/binary hash to the distrsuted list

Note:-
   The addition/deletion of trusted certificates and binary hashes
are not allowed in grub command prompt while secure boot is enabled.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/appendedsig/appendedsig.c | 518 +--
 1 file changed, 351 insertions(+), 167 deletions(-)

diff --git a/grub-core/commands/appendedsig/appendedsig.c 
b/grub-core/commands/appendedsig/appendedsig.c
index 5631f0ab4..6f665aab2 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -117,6 +117,36 @@ static enum
   check_sigs_forced = 2
 } check_sigs = check_sigs_no;
 
+enum
+{
+  OPTION_BINARY_HASH = 0,
+  OPTION_CERT_HASH = 1
+};
+
+static const struct grub_arg_option options[] =
+{
+  {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_NONE},
+  {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_NONE},
+  {0, 0, 0, 0, 0, 0}
+};
+
+static void
+print_hex (const grub_uint8_t *data, const grub_size_t length)
+{
+  grub_size_t i, count = 0;
+  for (i = 0; i < length-1; i++)
+{
+  grub_printf ("%02x:", data[i]);
+  count++;
+  if (count == 16)
+{
+  grub_printf ("\n\t  ");
+  count = 0;
+}
+}
+  grub_printf ("%02x\n", data[i]);
+}
+
 /*
  * GUID can be used to determine the hashing function and
  * generate the hash using determined hashing function.
@@ -344,72 +374,6 @@ grub_env_write_sec (struct grub_env_var *var __attribute__ 
((unused)), const cha
   return grub_strdup (grub_env_read_sec (NULL, NULL));
 }
 
-static grub_err_t
-file_read_all (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
-{
-  grub_off_t full_file_size;
-  grub_size_t file_size, total_read_size = 0;
-  grub_ssize_t read_size;
-
-  full_file_size = grub_file_size (file);
-  if (full_file_size == GRUB_FILE_SIZE_UNKNOWN)
-return grub_error (GRUB_ERR_BAD_ARGUMENT,
-   N_("Cannot read a file of unknown size into a buffer"));
-
-  if (full_file_size > GRUB_SIZE_MAX)
-return grub_error (GRUB_ERR_OUT_OF_RANGE,
-   N_("File is too large to read: %" PRIuGRUB_UINT64_T " 
bytes"),
-   full_file_size);
-
-  file_size = (grub_size_t) full_file_size;
-
-  *buf = grub_malloc (file_size);
-  if (!*buf)
-return grub_error (GRUB_ERR_OUT_OF_MEMORY,
-   N_("Could not allocate file data buffer size %" 
PRIuGRUB_SIZE),
-   file_size);
-
-  while (total_read_size < file_size)
-{
-  read_size = grub_file_read (file, *buf + total_read_size, file_size - 
total_read_size);
-
-  if (read_size < 0)
-{
-  grub_free (*buf);
-  return grub_errno;
-}
-  else if (read_size == 0)
-{
-  grub_free (*buf);
-  return grub_error (GRUB_ERR_IO,
- N_("Could not read full file size "
-"(%" PRIuGRUB_SIZE "), only %" PRIuGRUB_SIZE " 
bytes read"),
- file_size, total_read_size);
-}
-
-  total_read_size += read_size;
-}
-  *len = file_size;
-  return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-read_cert_from_file (grub_file_t f, struct x509_certificate *certificate)
-{
-  grub_err_t err;
-  grub_uint8_t *buf;
-  grub_size_t file_size;
-
-  err = file_read_all (f, &buf, &file_size);
-  if (err != GRUB_ERR_NONE)
-return err;
-
-  err = parse_x509_certificate (buf, file_size, certificate);
-  grub_free (buf);
-
-  return err;
-}
-
 static grub_err_t
 extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
 struct grub_appended_signature *sig)
@@ -630,145 +594,347 @@ grub_verify_appended_signature (const grub_uint8_t 
*buf, grub_size_t bufsize)
 static grub_err_t
 grub_cmd_verify_signature (grub_command_t cmd __attribute__ ((unused)), int 
argc, char **args)
 {
-  grub_file_t f;
   grub_err_t err = GRUB_ERR_NONE;
-  grub_uint8_t *data;
-  grub_size_t file_size;
+  grub_file_t signed_file = NULL;
+  grub_uint8_t *signed_data = NULL;
+  grub_ssize_t signed_data_size = 0;
 
-  if (argc < 1)
-return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+  if (argc != 1)
+{
+  grub_printf (N_("a signed file is expected\n"
+   

[PATCH v2 19/21] appendedsig: Reads the default DB keys from ELF Note

2025-03-26 Thread Sudhakar Kuppusamy
If Secure Boot is enabled with PKS and the use_static_keys flag is set,
then read the DB default keys from the ELF note and store them in the trusted 
list buffer.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/appendedsig/appendedsig.c | 56 ++--
 1 file changed, 40 insertions(+), 16 deletions(-)

diff --git a/grub-core/commands/appendedsig/appendedsig.c 
b/grub-core/commands/appendedsig/appendedsig.c
index 3abb45ae0..5631f0ab4 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -1041,7 +1041,7 @@ create_distrusted_list (void)
  * parse it, and add it to the trusted list.
  */
 static grub_err_t
-build_static_trusted_list (const struct grub_module_header *header)
+build_static_trusted_list (const struct grub_module_header *header, const 
grub_bool_t is_pks)
 {
   grub_err_t err = GRUB_ERR_NONE;
   struct grub_file pseudo_file;
@@ -1060,6 +1060,13 @@ build_static_trusted_list (const struct 
grub_module_header *header)
   if (err != GRUB_ERR_NONE)
 return err;
 
+  if (is_pks)
+{
+  err = is_distrusted_cert_hash (cert_data, cert_data_size);
+  if (err != GRUB_ERR_NONE)
+return err;
+}
+
   err = add_certificate (cert_data, cert_data_size, &db, 1);
   grub_free (cert_data);
 
@@ -1112,6 +1119,22 @@ free_distrusted_list (void)
   grub_memset (&dbx, 0, sizeof (dbx));
 }
 
+static grub_err_t
+load_static_keys (const struct grub_module_header *header, const grub_bool_t 
is_pks)
+{
+  int rc = GRUB_ERR_NONE;
+  FOR_MODULES (header)
+{
+  /* Not an ELF module, skip.  */
+  if (header->type != OBJ_TYPE_X509_PUBKEY)
+continue;
+  rc = build_static_trusted_list (header, is_pks);
+  if (rc != GRUB_ERR_NONE)
+return rc;
+}
+  return rc;
+}
+
 GRUB_MOD_INIT (appendedsig)
 {
   int rc;
@@ -1130,26 +1153,27 @@ GRUB_MOD_INIT (appendedsig)
 
   if (!grub_pks_use_keystore && check_sigs == check_sigs_forced)
 {
-  FOR_MODULES (header)
+  rc = load_static_keys (header, false);
+  if (rc != GRUB_ERR_NONE)
 {
-  /* Not an ELF module, skip.  */
-  if (header->type != OBJ_TYPE_X509_PUBKEY)
-continue;
-
-  rc = build_static_trusted_list (header);
-  if (rc != GRUB_ERR_NONE)
-{
-  free_trusted_list ();
-  grub_error (rc, "static trusted list creation failed");
-}
-  else
-grub_dprintf ("appendedsig", "the trusted list now has %" 
PRIuGRUB_SIZE " static keys\n",
-  db.key_entries);
+  free_trusted_list ();
+  grub_error (rc, "static trusted list creation failed");
 }
+  else
+grub_dprintf ("appendedsig", "the trusted list now has %" 
PRIuGRUB_SIZE " static keys\n",
+  db.key_entries);
 }
   else if (grub_pks_use_keystore && check_sigs == check_sigs_forced)
 {
-  rc = create_trusted_list ();
+  if (grub_pks_keystore.use_static_keys)
+{
+  grub_printf ("Warning: db variable is not available at PKS and using 
a static keys "
+   "as a default key in trusted list\n");
+  rc = load_static_keys (header, grub_pks_keystore.use_static_keys);
+}
+  else
+rc = create_trusted_list ();
+
   if (rc != GRUB_ERR_NONE)
 {
   free_trusted_list ();
-- 
2.43.5


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


[PATCH v2 02/21] docs/grub: Document signing grub under UEFI

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

Before adding information about how grub is signed with an appended
signature scheme, it's worth adding some information about how it
can currently be signed for UEFI.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
---
 docs/grub.texi | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index d9b26fa36..0e877e026 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -8632,6 +8632,7 @@ environment variables and commands are listed in the same 
order.
 * Measured Boot::Measuring boot components
 * Lockdown:: Lockdown when booting on a secure setup
 * TPM2 key protector::   Managing disk key with TPM2 key protector
+* Signing GRUB itself::  Ensuring the integrity of the GRUB core 
image
 @end menu
 
 @node Authentication and authorisation
@@ -8712,7 +8713,7 @@ commands.
 
 GRUB's @file{core.img} can optionally provide enforcement that all files
 subsequently read from disk are covered by a valid digital signature.
-This document does @strong{not} cover how to ensure that your
+This section does @strong{not} cover how to ensure that your
 platform's firmware (e.g., Coreboot) validates @file{core.img}.
 
 If environment variable @code{check_signatures}
@@ -9246,6 +9247,21 @@ which increases the risk of password leakage during the 
process. Moreover, the
 superuser list must be well maintained, and the password used cannot be
 synchronized with LUKS key rotation.
 
+@node Signing GRUB itself
+@section Signing GRUB itself
+To ensure a complete secure-boot chain, there must be a way for the code that
+loads GRUB to verify the integrity of the core image.
+This is ultimately platform-specific and individual platforms can define their
+own mechanisms. However, there are general-purpose mechanisms that can be used
+with GRUB.
+@section Signing GRUB for UEFI secure boot
+On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed
+with a tool such as @command{pesign} or @command{sbsign}. Refer to the
+suggestions in @pxref{UEFI secure boot and shim} to ensure that the final
+image works under UEFI secure boot and can maintain the secure-boot chain. It
+will also be necessary to enroll the public key used into a relevant firmware
+key database.
+
 @node Platform limitations
 @chapter Platform limitations
 
-- 
2.43.5


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


[PATCH v2 00/21] Appended Signature Secure Boot Support for PowerPC

2025-03-26 Thread Sudhakar Kuppusamy
This patch set contains v2 of the consolidated version of the patch
sets for secure boot using appended signatures on powerpc,
rebased on top of git HEAD.

The v1 series is at 
https://lists.gnu.org/archive/html/grub-devel/2024-12/msg00071.html

Linux on Power LPAR secure boot ensures the integrity of the Linux boot
stack. The hypervisor and partition firmware are part of the core root of
trust. The partition firmware verifies the signature on the GRUB image
before handing control to GRUB. Similarly, GRUB verifies the signature on
the kernel image before booting the OS. This ensures that every image
running at the boot time is verified and trusted. UEFI platforms relies
on PECOFF based signature scheme. Since Power is not a UEFI platform, an
alternative mechanism is needed. Power already uses appended signatures
on the Linux Kernel, and is now extended to sign the grub as well.

Linux on Power also allows multiple signers, and if any one of the
signature passes, then the image passes the validation. Appended signature
scheme uses CMS structure to contain signatures. On Power, the multiple
signature support relies on the multiple signers features already supported
by CMS standards. It does require that all the signers should sign at the
same time and are not allowed to add or remove the signatures randomly.

By default, Linux LPAR secure boot uses static key management[1]. This means
that each image embeds the keys it needs to verify the image it loads.
For example, the keys used to verify the GRUB image are built into the
firmware image. Similarly, the keys used for verifying the kernel image
are built into the GRUB image. These are pre-defined keys and they cannot
be modified at runtime. The drawback of this approach is that key rotations
results in both firmware and OS updates. This is where dynamic key
management is useful.

An admin can switch from static keys to dynamic keys by coordinating with
Hardware Management Console(HMC) admin and enabling the required flags
for the given LPAR.

The dynamic key management relies on the Platform KeyStore(PKS)[2] storage
allocation for each LPAR with individually managed access controls to
store sensitive information securely. Once switched to dynamic keys, HMC
advertises this flag to the PowerVM, which then initializes the PKS
with the default secvars. It also creates a variable SB_VERSION that
represents the secure boot key management mode. The default secvars are
used by Partition firmware, grub and the linux kernel to reads keys for
verification. These secvars can be managed by user interface exposed via
linux kernel. The linux kernel already supports this interface and
it is available in the upstream kernel.

This patchset adds the appended signature support both for signing and
verification and the key management to the grub component. The whole
patchset can be split into following four main parts:

The series has following four main parts:

1.) Sign grub.elf with an appended signature. (Patches 1 - 3)

These patches provide some infrastructure and documentation for
signing grub's core.elf with a Linux-kernel-module style appended
signature.

An appended signature is a 'dumb' signature over the contents of a
file. (It is distinct from schemes like Authenticode that are aware of
the structure of the file and only sign certain parts.) The signature
is wrapped in a PKCS#7 message, and is appended to the signed file
along with some metadata and a magic string. The signatures are
validated against a public key which is usually provided as an x509
certificate.

Because some platforms, such as powerpc-ieee1275, may load grub from a
raw disk partition rather than a filesystem, we extend grub-install to
add an ELF note that allows us to specify the size and location of the
signature.

2.) Enable appended signature verification using builtin keys (Patches 4 - 10).

Part of a secure boot chain is allowing grub to verify the boot
kernel. For UEFI platforms, this is usually delegated to the
shim. However, for platforms that do not implement UEFI, an
alternative scheme is required.

This part teaches grub how to verify Linux kernel-style appended
signatures. Kernels on powerpc are already signed with this scheme and
can be verified by IMA for kexec.

As PKCS#7 messages and x509 certificates are both based on ASN.1, we
import libtasn1 to parse them. Because ASN.1 isn't self-documenting,
we import from GNUTLS the information we need to navigate their
structure.

This section is composed of the following patches:

 - patch 4 is a small fix to allow persistent modules to work on the
   emu target.

 - patches 5 and 6 are small refactorings.

 - patch 7 allows x509 certificates to be built in to the grub core
   in much the same way as PGP keys.

 - patch 8 brings in the code from GNUTLS that allows us to parse
   PKCS#7 and x509 with libtasn1.

 - patch 9 is our PKCS#7 and x509 parser. They're minimal and fairly
   strict parsers that extract only the bits we need to verify 

[PATCH v2 01/21] powerpc-ieee1275: Add support for signing grub with an appended signature

2025-03-26 Thread Sudhakar Kuppusamy
From: Rashmica Gupta 

Add infrastructure to allow firmware to verify the integrity of grub
by use of a Linux-kernel-module-style appended signature. We initially
target powerpc-ieee1275, but the code should be extensible to other
platforms.

Usually these signatures are appended to a file without modifying the
ELF file itself. (This is what the 'sign-file' tool does, for example.)
The verifier loads the signed file from the file system and looks at the
end of the file for the appended signature. However, on powerpc-ieee1275
platforms, the bootloader is often stored directly in the PReP partition
as raw bytes without a file-system. This makes determining the location
of an appended signature more difficult.

To address this, we add a new ELF note.

The name field of shall be the string "Appended-Signature", zero-padded
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
for the string "ASig"). It must be the final section in the ELF binary.

The description shall contain the appended signature structure as defined
by the Linux kernel. The description will also be padded to be a multiple
of 4 bytes. The padding shall be added before the appended signature
structure (not at the end) so that the final bytes of a signed ELF file
are the appended signature magic.

A subsequent patch documents how to create a grub core.img validly signed
under this scheme.

Signed-off-by: Rashmica Gupta 
Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 include/grub/util/install.h |  7 +--
 include/grub/util/mkimage.h |  4 ++--
 util/grub-install-common.c  | 15 ---
 util/grub-mkimage.c | 11 +++
 util/grub-mkimagexx.c   | 38 -
 util/mkimage.c  |  6 +++---
 6 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 5c0a52ca2..3aabc4285 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -69,6 +69,8 @@
   N_("disable shim_lock verifier"), 0 },   \
   { "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
 N_("disabled command line interface access"), 0 }, \
+  { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,  \
+"SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended 
signature"), 1}, \
   { "verbose", 'v', 0, 0,  \
 N_("print verbose messages."), 1 }
 
@@ -132,7 +134,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_DTB,
   GRUB_INSTALL_OPTIONS_SBAT,
   GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
-  GRUB_INSTALL_OPTIONS_DISABLE_CLI
+  GRUB_INSTALL_OPTIONS_DISABLE_CLI,
+  GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
 };
 
 extern char *grub_install_source_directory;
@@ -192,7 +195,7 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
 size_t npubkeys,
 char *config_path,
 const struct grub_install_image_target_desc 
*image_target,
-int note,
+int note, size_t appsig_size,
 grub_compression_t comp, const char *dtb_file,
 const char *sbat_path, const int disable_shim_lock,
 const int disable_cli);
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 9d74f82c5..0d40383eb 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
   const struct grub_install_image_target_desc 
*image_target);
 void
 grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc 
*image_target,
-int note, char *sbat, char **core_img, size_t 
*core_size,
+int note, char *sbat, size_t appsig_size, char 
**core_img, size_t *core_size,
 Elf32_Addr target_addr,
 struct grub_mkimage_layout *layout);
 void
 grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc 
*image_target,
-int note, char *sbat, char **core_img, size_t 
*core_size,
+int note, char *sbat, size_t appsig_size, char 
**core_img, size_t *core_size,
 Elf64_Addr target_addr,
 struct grub_mkimage_layout *layout);
 
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 22bccb6a3..22f0e56cb 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -467,10 +467,12 @@ static char *sbat;
 static int disable_shim_lock;
 static grub_compression_t compression;
 static int disable_cli;
+static size_t appsig_size;
 
 int

[PATCH v2 04/21] dl: provide a fake grub_dl_set_persistent for the emu target

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

Trying to start grub-emu with a module that calls grub_dl_set_persistent
will crash because grub-emu fakes modules and passes NULL to the module
init function.

Provide an empty function for the emu case.

Fixes: ee7808e2197c (dl: Add support for persistent modules)
Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 include/grub/dl.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/include/grub/dl.h b/include/grub/dl.h
index 84509c5c1..43e411fef 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -242,11 +242,22 @@ grub_dl_get (const char *name)
   return 0;
 }
 
+#ifdef GRUB_MACHINE_EMU
+/*
+ * Under grub-emu, modules are faked and NULL is passed to GRUB_MOD_INIT.
+ * So we fake this out to avoid a NULL deref.
+ */
+static inline void
+grub_dl_set_persistent (grub_dl_t mod __attribute__((unused)))
+{
+}
+#else
 static inline void
 grub_dl_set_persistent (grub_dl_t mod)
 {
   mod->persistent = 1;
 }
+#endif
 
 static inline int
 grub_dl_is_persistent (grub_dl_t mod)
-- 
2.43.5


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


[PATCH v2 03/21] docs/grub: Document signing grub with an appended signature

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

Signing grub for firmware that verifies an appended signature is a
bit fiddly. I don't want people to have to figure it out from scratch
so document it here.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 docs/grub.texi | 32 
 1 file changed, 32 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index 0e877e026..19bbe9b2b 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -9262,6 +9262,38 @@ image works under UEFI secure boot and can maintain the 
secure-boot chain. It
 will also be necessary to enroll the public key used into a relevant firmware
 key database.
 
+@section Signing GRUB with an appended signature
+The @file{core.img} itself can be signed with a Linux kernel module-style
+appended signature.
+To support IEEE1275 platforms where the boot image is often loaded directly
+from a disk partition rather than from a file system, the @file{core.img}
+can specify the size and location of the appended signature with an ELF
+note added by @command{grub-install}.
+An image can be signed this way using the @command{sign-file} command from
+the Linux kernel:
+@example
+@group
+# grub.key is your private key and certificate.der is your public key
+# Determine the size of the appended signature. It depends on the signing
+# certificate and the hash algorithm
+touch empty
+sign-file SHA256 grub.key certificate.der empty empty.sig
+SIG_SIZE=`stat -c '%s' empty.sig`
+rm empty empty.sig
+# Build a grub image with $SIG_SIZE reserved for the signature
+grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
+# Replace the reserved size with a signature:
+# cut off the last $SIG_SIZE bytes with truncate's minus modifier
+truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
+# sign the trimmed file with an appended signature, restoring the correct size
+sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
+# Don't forget to install the signed image as required
+# (e.g. on powerpc-ieee1275, to the PReP partition)
+@end group
+@end example
+As with UEFI secure boot, it is necessary to build-in the required modules,
+or sign them separately.
+
 @node Platform limitations
 @chapter Platform limitations
 
-- 
2.43.5


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


[PATCH v2 10/21] appended signatures: support verifying appended signatures

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

Building on the parsers and the ability to embed x509 certificates, as
well as the existing gcrypt functionality, add a module for verifying
appended signatures.

This includes a verifier that requires that Linux kernels and grub modules
have appended signatures, and commands to manage the list of trusted
certificates for verification.

Verification must be enabled by setting check_appended_signatures. If
GRUB is locked down when the module is loaded, verification will be
enabled and locked automatically.

As with the PGP verifier, it is not a complete secure-boot solution:
other mechanisms, such as a password or lockdown, must be used to ensure
that a user cannot drop to the grub shell and disable verification.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/Makefile.core.def   |  14 +
 grub-core/commands/appendedsig/appendedsig.c  | 618 ++
 grub-core/commands/appendedsig/appendedsig.h  |   2 +-
 grub-core/commands/appendedsig/asn1util.c |   2 +-
 .../commands/appendedsig/gnutls_asn1_tab.c|   2 +-
 .../commands/appendedsig/pkix_asn1_tab.c  |   2 +-
 grub-core/commands/appendedsig/x509.c |   2 +-
 include/grub/file.h   |   2 +
 8 files changed, 639 insertions(+), 5 deletions(-)
 create mode 100644 grub-core/commands/appendedsig/appendedsig.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 60db2adc5..d693986c6 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -979,6 +979,20 @@ module = {
   cppflags = '-I$(srcdir)/lib/posix_wrap';
 };
 
+module = {
+  name = appendedsig;
+  common = commands/appendedsig/appendedsig.c;
+  common = commands/appendedsig/x509.c;
+  common = commands/appendedsig/pkcs7.c;
+  common = commands/appendedsig/asn1util.c;
+  common = commands/appendedsig/gnutls_asn1_tab.c;
+  common = commands/appendedsig/pkix_asn1_tab.c;
+
+  // posix wrapper required for gcry to get sys/types.h
+  cflags = '$(CFLAGS_POSIX)';
+  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/libtasn1-grub';
+};
+
 module = {
   name = hdparm;
   common = commands/hdparm.c;
diff --git a/grub-core/commands/appendedsig/appendedsig.c 
b/grub-core/commands/appendedsig/appendedsig.c
new file mode 100644
index 0..cbd227a3c
--- /dev/null
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -0,0 +1,618 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020, 2021, 2022 Free Software Foundation, Inc.
+ *  Copyright (C) 2020, 2021, 2022 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "appendedsig.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+const char magic[] = "~Module signature appended~\n";
+
+/*
+ * This structure is extracted from scripts/sign-file.c in the linux kernel
+ * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible.
+ */
+struct module_signature
+{
+  grub_uint8_t algo;   /* Public-key crypto algorithm [0] */
+  grub_uint8_t hash;   /* Digest algorithm [0] */
+  grub_uint8_t id_type;/* Key identifier type [PKEY_ID_PKCS7] */
+  grub_uint8_t signer_len; /* Length of signer's name [0] */
+  grub_uint8_t key_id_len; /* Length of key identifier [0] */
+  grub_uint8_t __pad[3];
+  grub_uint32_t sig_len;   /* Length of signature data */
+} GRUB_PACKED;
+
+/* This represents an entire, parsed, appended signature */
+struct grub_appended_signature
+{
+  grub_size_t signature_len;/* Length of PKCS#7 data + metadata + 
magic */
+  struct module_signature sig_metadata; /* Module signature metadata */
+  struct pkcs7_signedData pkcs7;/* Parsed PKCS#7 data */
+};
+
+/* Trusted certificates for verifying appended signatures */
+struct x509_certificate *grub_trusted_key;
+
+/*
+ * Force gcry_rsa to be a module dependency.
+ *
+ * If we use grub_crypto_pk_rsa, then then the gcry_rsa module won't be built
+ * in if you add 'appendedsig' to grub-install --modules. You would need to
+ * add 'gcry_rsa' too. That's confusing and seems suboptimal, especially when
+ * we only support RSA.
+ *
+ * Dynamic loading also caus

[PATCH v2 15/21] ieee1275: Read the DB and DBX secure boot variables

2025-03-26 Thread Sudhakar Kuppusamy
If secure boot is enabled with PKS, it will read secure boot variables
such as db and dbx from PKS and extract ESL's from it.
The ESL's would be saved in the platform keystore buffer, and
the appendedsig (module) would read it later to extract
the certificate's details from ESL.

In the following scenarios, static key mode will be activated:
 1. When Secure Boot is enabled with static keys
 2. When SB Version is unavailable but Secure Boot is enabled
 3. When PKS support is unavailable but Secure Boot is enabled

Note:-

SB Version - Secure Boot mode
1 - PKS
0 - static key (embeded key)

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/Makefile.am |   1 +
 grub-core/Makefile.core.def   |   1 +
 grub-core/kern/ieee1275/init.c|  15 +-
 .../kern/powerpc/ieee1275/platform_keystore.c | 332 ++
 .../grub/powerpc/ieee1275/platform_keystore.h | 225 
 include/grub/types.h  |   9 +
 6 files changed, 581 insertions(+), 2 deletions(-)
 create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c
 create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index b516e139b..cd6bb7c32 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -247,6 +247,7 @@ KERNEL_HEADER_FILES += 
$(top_srcdir)/include/grub/ieee1275/alloc.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
+KERNEL_HEADER_FILES += 
$(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h
 endif
 
 if COND_sparc64_ieee1275
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 95bccce5d..2730b35f4 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -333,6 +333,7 @@ kernel = {
   powerpc_ieee1275 = kern/powerpc/dl.c;
   powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
   powerpc_ieee1275 = kern/lockdown.c;
+  powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c;
 
   sparc64_ieee1275 = kern/sparc64/cache.S;
   sparc64_ieee1275 = kern/sparc64/dl.c;
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index ba3cb7cfa..d6ce9654d 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -50,6 +50,8 @@
 #include 
 #endif
 #include 
+#include 
+#include 
 
 /* The maximum heap size we're going to claim at boot. Not used by sparc. */
 #ifdef __i386__
@@ -959,7 +961,7 @@ grub_get_ieee1275_secure_boot (void)
 {
   grub_ieee1275_phandle_t root;
   int rc;
-  grub_uint32_t is_sb;
+  grub_uint32_t is_sb = 0;
 
   if (grub_ieee1275_finddevice ("/", &root))
 {
@@ -983,7 +985,16 @@ grub_get_ieee1275_secure_boot (void)
* We only support enforce.
*/
   if (is_sb >= 2)
-grub_lockdown ();
+{
+  grub_dprintf ("ieee1275", "Secure Boot Enabled\n");
+  rc = grub_pks_keystore_init ();
+  if (rc != GRUB_ERR_NONE)
+grub_error (rc, "Initialization of the Platform Keystore failed!\n");
+
+  grub_lockdown ();
+}
+  else
+  grub_dprintf ("ieee1275", "Secure Boot Disabled\n");
 }
 
 grub_addr_t grub_modbase;
diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c 
b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
new file mode 100644
index 0..cf1d0555e
--- /dev/null
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
@@ -0,0 +1,332 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2024  Free Software Foundation, Inc.
+ *  Copyright (C) 2024 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define PKS_CONSUMER_FW 1
+#define SB_VERSION_KEY_NAME ((grub_uint8_t *) "SB_VERSION")
+#define SB_VERSION_KEY_LEN 10
+#define DB 1
+#define DBX 2
+#define PKS_OBJECT_NOT_FOUND ((grub_err_t) - 7)
+
+/* Platform Keystore */
+static grub_size_t pks_max_object_size;
+grub_uint8_t grub_pks_use_keystore = 0;
+grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, 
.dbx_entries = 0 };
+
+/* Convert the esl data into the ESL */
+static grub_esl_t *
+convert_to_esl (const grub_uint8_t *esl_data, const grub_size_t esl_data_size)
+{
+ 

[PATCH v2 08/21] appended signatures: import GNUTLS's ASN.1 description files

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

In order to parse PKCS#7 messages and X.509 certificates with libtasn1,
we need some information about how they are encoded.

We get these from GNUTLS, which has the benefit that they support the
features we need and are well tested.

The GNUTLS files are from:

- 
https://github.com/gnutls/gnutls/blob/857543cc24114431dd5dde0e83c2c44b9b7e6050/lib/gnutls_asn1_tab.c
- 
https://github.com/gnutls/gnutls/blob/857543cc24114431dd5dde0e83c2c44b9b7e6050/lib/pkix_asn1_tab.c

The GNUTLS license is LGPLv2.1+, which is GPLv3 compatible, allowing
us to import it without issue.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 .../commands/appendedsig/gnutls_asn1_tab.c| 121 +
 .../commands/appendedsig/pkix_asn1_tab.c  | 484 ++
 2 files changed, 605 insertions(+)
 create mode 100644 grub-core/commands/appendedsig/gnutls_asn1_tab.c
 create mode 100644 grub-core/commands/appendedsig/pkix_asn1_tab.c

diff --git a/grub-core/commands/appendedsig/gnutls_asn1_tab.c 
b/grub-core/commands/appendedsig/gnutls_asn1_tab.c
new file mode 100644
index 0..ddd1314e6
--- /dev/null
+++ b/grub-core/commands/appendedsig/gnutls_asn1_tab.c
@@ -0,0 +1,121 @@
+#include 
+#include 
+
+const asn1_static_node gnutls_asn1_tab[] = {
+  { "GNUTLS", 536872976, NULL },
+  { NULL, 1073741836, NULL },
+  { "RSAPublicKey", 1610612741, NULL },
+  { "modulus", 1073741827, NULL },
+  { "publicExponent", 3, NULL },
+  { "RSAPrivateKey", 1610612741, NULL },
+  { "version", 1073741827, NULL },
+  { "modulus", 1073741827, NULL },
+  { "publicExponent", 1073741827, NULL },
+  { "privateExponent", 1073741827, NULL },
+  { "prime1", 1073741827, NULL },
+  { "prime2", 1073741827, NULL },
+  { "exponent1", 1073741827, NULL },
+  { "exponent2", 1073741827, NULL },
+  { "coefficient", 1073741827, NULL },
+  { "otherPrimeInfos", 16386, "OtherPrimeInfos"},
+  { "ProvableSeed", 1610612741, NULL },
+  { "algorithm", 1073741836, NULL },
+  { "seed", 7, NULL },
+  { "OtherPrimeInfos", 1612709899, NULL },
+  { "MAX", 1074266122, "1"},
+  { NULL, 2, "OtherPrimeInfo"},
+  { "OtherPrimeInfo", 1610612741, NULL },
+  { "prime", 1073741827, NULL },
+  { "exponent", 1073741827, NULL },
+  { "coefficient", 3, NULL },
+  { "AlgorithmIdentifier", 1610612741, NULL },
+  { "algorithm", 1073741836, NULL },
+  { "parameters", 541081613, NULL },
+  { "algorithm", 1, NULL },
+  { "DigestInfo", 1610612741, NULL },
+  { "digestAlgorithm", 1073741826, "DigestAlgorithmIdentifier"},
+  { "digest", 7, NULL },
+  { "DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
+  { "DSAPublicKey", 1073741827, NULL },
+  { "DSAParameters", 1610612741, NULL },
+  { "p", 1073741827, NULL },
+  { "q", 1073741827, NULL },
+  { "g", 3, NULL },
+  { "DSASignatureValue", 1610612741, NULL },
+  { "r", 1073741827, NULL },
+  { "s", 3, NULL },
+  { "DSAPrivateKey", 1610612741, NULL },
+  { "version", 1073741827, NULL },
+  { "p", 1073741827, NULL },
+  { "q", 1073741827, NULL },
+  { "g", 1073741827, NULL },
+  { "Y", 1073741827, NULL },
+  { "priv", 3, NULL },
+  { "DHParameter", 1610612741, NULL },
+  { "prime", 1073741827, NULL },
+  { "base", 1073741827, NULL },
+  { "privateValueLength", 16387, NULL },
+  { "ECParameters", 1610612754, NULL },
+  { "namedCurve", 12, NULL },
+  { "ECPrivateKey", 1610612741, NULL },
+  { "Version", 1073741827, NULL },
+  { "privateKey", 1073741831, NULL },
+  { "parameters", 1610637314, "ECParameters"},
+  { NULL, 2056, "0"},
+  { "publicKey", 536895494, NULL },
+  { NULL, 2056, "1"},
+  { "PrincipalName", 1610612741, NULL },
+  { "name-type", 1610620931, NULL },
+  { NULL, 2056, "0"},
+  { "name-string", 536879115, NULL },
+  { NULL, 1073743880, "1"},
+  { NULL, 27, NULL },
+  { "KRB5PrincipalName", 1610612741, NULL },
+  { "realm", 1610620955, NULL },
+  { NULL, 2056, "0"},
+  { "principalName", 536879106, "PrincipalName"},
+  { NULL, 2056, "1"},
+  { "RSAPSSParameters", 1610612741, NULL },
+  { "hashAlgorithm", 1610637314, "AlgorithmIdentifier"},
+  { NULL, 2056, "0"},
+  { "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"},
+  { NULL, 2056, "1"},
+  { "saltLength", 1610653699, NULL },
+  { NULL, 1073741833, "20"},
+  { NULL, 2056, "2"},
+  { "trailerField", 536911875, NULL },
+  { NULL, 1073741833, "1"},
+  { NULL, 2056, "3"},
+  { "GOSTParameters", 1610612741, NULL },
+  { "publicKeyParamSet", 1073741836, NULL },
+  { "digestParamSet", 16396, NULL },
+  { "GOSTParametersOld", 1610612741, NULL },
+  { "publicKeyParamSet", 1073741836, NULL },
+  { "digestParamSet", 1073741836, NULL },
+  { "encryptionParamSet", 16396, NULL },
+  { "GOSTPrivateKey", 1073741831, NULL },
+  { "GOSTPrivateKeyOld", 1073741827, NULL },
+  { "IssuerSignTool", 1610612741, NULL },
+  { "signTool", 1073741858, NULL },
+  { "cATool", 1073741858, NULL },
+  { "signToolCert", 1073741858, NULL },
+  { "cAToolCert", 34, NULL },
+  { "Gost28147-89-EncryptedKey", 1610

[PATCH v2 12/21] appended signatures: documentation

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

This explains how appended signatures can be used to form part of
a secure boot chain, and documents the commands and variables
introduced.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 docs/grub.texi | 185 -
 1 file changed, 167 insertions(+), 18 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 19bbe9b2b..25a51dee8 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3281,6 +3281,7 @@ These variables have special meaning to GRUB.
 
 @menu
 * biosnum::
+* check_appended_signatures::
 * check_signatures::
 * chosen::
 * cmdpath::
@@ -3343,12 +3344,16 @@ this.
 For an alternative approach which also changes BIOS drive mappings for the
 chain-loaded system, @pxref{drivemap}.
 
+@node check_appended_signatures
+@subsection check_appended_signatures
+This variable controls whether GRUB enforces appended signature validation on
+certain loaded files. @xref{Using appended signatures}.
 
 @node check_signatures
 @subsection check_signatures
 
-This variable controls whether GRUB enforces digital signature
-validation on loaded files. @xref{Using digital signatures}.
+This variable controls whether GRUB enforces GPG-style digital signature
+validation on loaded files. @xref{Using GPG-style digital signatures}.
 
 @node chosen
 @subsection chosen
@@ -6432,6 +6437,7 @@ you forget a command, you can run the command 
@command{help}
 * date::Display or set current date and time
 * devicetree::  Load a device tree blob
 * distrust::Remove a pubkey from trusted keys
+* distrust_certificate::Remove a certificate from the list of trusted 
certificates
 * drivemap::Map a drive to another
 * echo::Display a line of text
 * efitextmode:: Set/Get text output mode resolution
@@ -6450,6 +6456,7 @@ you forget a command, you can run the command 
@command{help}
 * hexdump:: Show raw contents of a file or memory
 * insmod::  Insert a module
 * keystatus::   Check key modifier status
+* list_certificates::   List trusted certificates
 * list_env::List variables in environment block
 * list_trusted::List trusted public keys
 * load_env::Load variables from environment block
@@ -6490,8 +6497,10 @@ you forget a command, you can run the command 
@command{help}
 * tpm2_key_protector_clear::Clear the TPM2 key protector
 * true::Do nothing, successfully
 * trust::   Add public key to list of trusted keys
+* trust_certificate::   Add an x509 certificate to the list of trusted 
certificates
 * unset::   Unset an environment variable
 @comment * vbeinfo:: List available video modes
+* verify_appended:: Verify appended digital signature
 * verify_detached:: Verify detached digital signature
 * videoinfo::   List available video modes
 * wrmsr::   Write values to model-specific registers
@@ -6833,7 +6842,24 @@ These keys are used to validate signatures when 
environment variable
 @code{check_signatures} is set to @code{enforce}
 (@pxref{check_signatures}), and by some invocations of
 @command{verify_detached} (@pxref{verify_detached}).  @xref{Using
-digital signatures}, for more information.
+GPG-style digital signatures}, for more information.
+@end deffn
+
+@node distrust_certificate
+@subsection distrust_certificate
+
+@deffn Command distrust_certificate cert_number
+Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of
+trusted x509 certificates for verifying appended signatures.
+
+@var{cert_number} is the certificate number as listed by
+@command{list_certificates} (@pxref{list_certificates}).
+
+These certificates are used to validate appended signatures when environment
+variable @code{check_appended_signatures} is set to @code{enforce}
+(@pxref{check_appended_signatures}), and by @command{verify_appended}
+(@pxref{verify_appended}). See @xref{Using appended signatures} for more
+information.
 @end deffn
 
 @node drivemap
@@ -7229,6 +7255,19 @@ without any options, the @command{keystatus} command 
returns true if and
 only if checking key modifier status is supported.
 @end deffn
 
+@node list_certificates
+@subsection list_certificates
+
+@deffn Command list_certificates
+List all x509 certificates trusted by GRUB for validating appended signatures.
+The output is a numbered list of certificates, showing the certificate's serial
+number and Common Name.
+
+The certificate number can be used as an argument to
+@command{distrust_certificate} (@pxref{distrust_certificate}).
+
+See @xref{Using appended signatures} for more information.
+@end deffn
 
 @node 

[PATCH v2 05/21] pgp: factor out rsa_pad

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

rsa_pad does the PKCS#1 v1.5 padding for the RSA signature scheme.
We want to use it in other RSA signature verification applications.

I considered and rejected putting it in lib/crypto.c. That file doesn't
currently require any MPI functions, but rsa_pad does. That's not so
much of a problem for the grub kernel and modules, but crypto.c also
gets built into all the grub utilities. So - despite the utils not
using any asymmetric ciphers -  we would need to built the entire MPI
infrastructure in to them.

A better and simpler solution is just to spin rsa_pad out into its own
PKCS#1 v1.5 module.

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/Makefile.core.def |  8 +
 grub-core/commands/pgp.c| 28 ++
 grub-core/lib/pkcs1_v15.c   | 59 +
 include/grub/pkcs1_v15.h| 27 +
 4 files changed, 96 insertions(+), 26 deletions(-)
 create mode 100644 grub-core/lib/pkcs1_v15.c
 create mode 100644 include/grub/pkcs1_v15.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index f70e02e69..60db2adc5 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2540,6 +2540,14 @@ module = {
   cppflags = '$(CPPFLAGS_GCRY)';
 };
 
+module = {
+  name = pkcs1_v15;
+  common = lib/pkcs1_v15.c;
+
+  cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
+  cppflags = '$(CPPFLAGS_GCRY)';
+};
+
 module = {
   name = all_video;
   common = lib/fake_module.c;
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index 5fadc33c4..5503d291a 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -411,32 +412,7 @@ static int
 rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
 {
-  grub_size_t tlen, emlen, fflen;
-  grub_uint8_t *em, *emptr;
-  unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]);
-  int ret;
-  tlen = hash->mdlen + hash->asnlen;
-  emlen = (nbits + 7) / 8;
-  if (emlen < tlen + 11)
-return 1;
-
-  em = grub_malloc (emlen);
-  if (!em)
-return 1;
-
-  em[0] = 0x00;
-  em[1] = 0x01;
-  fflen = emlen - tlen - 3;
-  for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
-*emptr = 0xff;
-  *emptr++ = 0x00;
-  grub_memcpy (emptr, hash->asnoid, hash->asnlen);
-  emptr += hash->asnlen;
-  grub_memcpy (emptr, hval, hash->mdlen);
-
-  ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
-  grub_free (em);
-  return ret;
+  return grub_crypto_rsa_pad(hmpi, hval, hash, sk->mpis[0]);
 }
 
 struct grub_pubkey_context
diff --git a/grub-core/lib/pkcs1_v15.c b/grub-core/lib/pkcs1_v15.c
new file mode 100644
index 0..535ba5c18
--- /dev/null
+++ b/grub-core/lib/pkcs1_v15.c
@@ -0,0 +1,59 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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 .
+ */
+
+#include 
+#include 
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/*
+ * Given a hash value 'hval', of hash specification 'hash', perform
+ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod'
+ * (see RFC 8017 s 9.2) and place the result in 'hmpi'.
+ */
+gcry_err_code_t
+grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval,
+ const gcry_md_spec_t * hash, gcry_mpi_t mod)
+{
+  grub_size_t tlen, emlen, fflen;
+  grub_uint8_t *em, *emptr;
+  unsigned nbits = gcry_mpi_get_nbits (mod);
+  int ret;
+  tlen = hash->mdlen + hash->asnlen;
+  emlen = (nbits + 7) / 8;
+  if (emlen < tlen + 11)
+return GPG_ERR_TOO_SHORT;
+
+  em = grub_malloc (emlen);
+  if (!em)
+return 1;
+
+  em[0] = 0x00;
+  em[1] = 0x01;
+  fflen = emlen - tlen - 3;
+  for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
+*emptr = 0xff;
+  *emptr++ = 0x00;
+  grub_memcpy (emptr, hash->asnoid, hash->asnlen);
+  emptr += hash->asnlen;
+  grub_memcpy (emptr, hval, hash->mdlen);
+
+  ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
+  grub_free (em);
+  return ret;
+}
diff --git a/include/grub/pkcs1_v15.h b/include/grub/pkcs1_v15.h
new file mode 100644
index 0..7644ac9e0
--- /dev/null
+++ b/include/grub/pkcs1_v15.h
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  G

[PATCH v2 21/21] appendedsig: documentation

2025-03-26 Thread Sudhakar Kuppusamy
This explains how static and dynamic key appended signatures can be used to 
form part of
a secure boot chain, and documents the commands and variables introduced.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Avnish Chouhan 
---
 docs/grub.texi | 108 +++--
 1 file changed, 77 insertions(+), 31 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 52e26c8fd..e0d6fe95e 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6437,7 +6437,9 @@ you forget a command, you can run the command 
@command{help}
 * date::Display or set current date and time
 * devicetree::  Load a device tree blob
 * distrust::Remove a pubkey from trusted keys
-* distrust_certificate::Remove a certificate from the list of trusted 
certificates
+* distrusted_certificate::  Remove a certificate from the trusted list
+* distrusted_list:: List distrusted certificates and 
binary/certificate hashes
+* distrusted_signature::Add a binary hash to the distrusted list
 * drivemap::Map a drive to another
 * echo::Display a line of text
 * efitextmode:: Set/Get text output mode resolution
@@ -6456,7 +6458,6 @@ you forget a command, you can run the command 
@command{help}
 * hexdump:: Show raw contents of a file or memory
 * insmod::  Insert a module
 * keystatus::   Check key modifier status
-* list_certificates::   List trusted certificates
 * list_env::List variables in environment block
 * list_trusted::List trusted public keys
 * load_env::Load variables from environment block
@@ -6497,7 +6498,9 @@ you forget a command, you can run the command 
@command{help}
 * tpm2_key_protector_clear::Clear the TPM2 key protector
 * true::Do nothing, successfully
 * trust::   Add public key to list of trusted keys
-* trust_certificate::   Add an x509 certificate to the list of trusted 
certificates
+* trusted_certificate:: Add an x509 certificate to the trusted list
+* trusted_list::List trusted certificates and binary hashes
+* trusted_signature::   Add a binary hash to the trusted list.
 * unset::   Unset an environment variable
 @comment * vbeinfo:: List available video modes
 * verify_appended:: Verify appended digital signature
@@ -6845,15 +6848,15 @@ These keys are used to validate signatures when 
environment variable
 GPG-style digital signatures}, for more information.
 @end deffn
 
-@node distrust_certificate
-@subsection distrust_certificate
+@node distrusted_certificate
+@subsection distrusted_certificate
 
-@deffn Command distrust_certificate cert_number
+@deffn Command distrusted_certificate cert_number
 Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of
 trusted x509 certificates for verifying appended signatures.
 
 @var{cert_number} is the certificate number as listed by
-@command{list_certificates} (@pxref{list_certificates}).
+@command{trusted_list} (@pxref{trusted_list}).
 
 These certificates are used to validate appended signatures when environment
 variable @code{check_appended_signatures} is set to @code{enforce}
@@ -6862,6 +6865,28 @@ variable @code{check_appended_signatures} is set to 
@code{enforce}
 information.
 @end deffn
 
+@node distrusted_list
+@subsection distrusted_list
+
+@deffn Command distrusted_list
+List all the distrusted x509 certificates and binary/certificate hashes.
+The output is a numbered list of certificates and binary/certificate hashes,
+showing the certificate's serial number and Common Name.
+@end deffn
+
+@node distrusted_signature
+@subsection distrusted_signature
+
+@deffn Command distrusted_signature
+Read a binary hash from the file @var{binary hash file}
+and add it to GRUB's internal distrusted list. These hash are used to
+restrict validation of linux image integrity using trusted list if appended
+signatures validation failed when the environment variable
+@code{check_appended_signatures} is set to @code{enforce}.
+
+See @xref{Using appended signatures} for more information.
+@end deffn
+
 @node drivemap
 @subsection drivemap
 
@@ -7255,20 +7280,6 @@ without any options, the @command{keystatus} command 
returns true if and
 only if checking key modifier status is supported.
 @end deffn
 
-@node list_certificates
-@subsection list_certificates
-
-@deffn Command list_certificates
-List all x509 certificates trusted by GRUB for validating appended signatures.
-The output is a numbered list of certificates, showing the certificate's serial
-number and Common Name.
-
-The certificate number can be used as an argument to
-@command{distrust_certificate} (@pxref{distrust_certificate}).
-
-See @xref{Using appended sign

[PATCH v2 07/21] grub-install: support embedding x509 certificates

2025-03-26 Thread Sudhakar Kuppusamy
From: Alastair D'Silva 

To support verification of appended signatures, we need a way to
embed the necessary public keys. Existing appended signature schemes
in the Linux kernel use X.509 certificates, so allow certificates to
be embedded in the grub core image in the same way as PGP keys.

Signed-off-by: Alastair D'Silva 
Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/pgp.c|  2 +-
 include/grub/kernel.h   |  2 ++
 include/grub/util/install.h |  3 +++
 util/grub-install-common.c  | 19 ++-
 util/grub-mkimage.c | 14 --
 util/mkimage.c  | 33 +++--
 6 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index 961abf775..fa3ef5c75 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -944,7 +944,7 @@ GRUB_MOD_INIT(pgp)
 grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
 
 /* Not an ELF module, skip.  */
-if (header->type != OBJ_TYPE_PUBKEY)
+if (header->type != OBJ_TYPE_GPG_PUBKEY)
   continue;
 
 pseudo_file.fs = &pseudo_fs;
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index 6121c1e66..5c5ac129d 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -29,6 +29,8 @@ enum
   OBJ_TYPE_CONFIG,
   OBJ_TYPE_PREFIX,
   OBJ_TYPE_PUBKEY,
+  OBJ_TYPE_GPG_PUBKEY,
+  OBJ_TYPE_X509_PUBKEY,
   OBJ_TYPE_DTB,
   OBJ_TYPE_DISABLE_SHIM_LOCK,
   OBJ_TYPE_DISABLE_CLI
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 3aabc4285..52a667c37 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -69,6 +69,8 @@
   N_("disable shim_lock verifier"), 0 },   \
   { "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
 N_("disabled command line interface access"), 0 }, \
+  { "x509key",   'x', N_("FILE"), 0,   \
+  N_("embed FILE as an x509 certificate for signature checking"), 0}, \
   { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,  \
 "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended 
signature"), 1}, \
   { "verbose", 'v', 0, 0,  \
@@ -193,6 +195,7 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
 const char *outname, char *mods[],
 char *memdisk_path, char **pubkey_paths,
 size_t npubkeys,
+char **x509key_paths, size_t nx509keys,
 char *config_path,
 const struct grub_install_image_target_desc 
*image_target,
 int note, size_t appsig_size,
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index 22f0e56cb..29c45e26e 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -463,6 +463,8 @@ handle_install_list (struct install_list *il, const char 
*val,
 
 static char **pubkeys;
 static size_t npubkeys;
+static char **x509keys;
+static size_t nx509keys;
 static char *sbat;
 static int disable_shim_lock;
 static grub_compression_t compression;
@@ -510,6 +512,10 @@ grub_install_parse (int key, char *arg)
 case GRUB_INSTALL_OPTIONS_DISABLE_CLI:
   disable_cli = 1;
   return 1;
+case 'x':
+  x509keys = xrealloc (x509keys, sizeof (x509keys[0]) * (nx509keys + 1));
+  x509keys[nx509keys++] = xstrdup (arg);
+  return 1;
 
 case GRUB_INSTALL_OPTIONS_VERBOSITY:
   verbosity++;
@@ -640,6 +646,9 @@ grub_install_make_image_wrap_file (const char *dir, const 
char *prefix,
   for (pk = pubkeys; pk < pubkeys + npubkeys; pk++)
 slen += sizeof (" --pubkey ''") + grub_strlen (*pk);
 
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
+slen += sizeof (" --x509key ''") + grub_strlen (*pk);
+
   for (md = modules.entries; *md; md++)
 slen += sizeof (" ''") + grub_strlen (*md);
 
@@ -680,6 +689,14 @@ grub_install_make_image_wrap_file (const char *dir, const 
char *prefix,
   *p++ = '\'';
 }
 
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
+{
+  p = grub_stpcpy (p, "--x509key '");
+  p = grub_stpcpy (p, *pk);
+  *p++ = '\'';
+  *p++ = ' ';
+}
+
   for (md = modules.entries; *md; md++)
 {
   *p++ = ' ';
@@ -706,7 +723,7 @@ grub_install_make_image_wrap_file (const char *dir, const 
char *prefix,
 
   grub_install_generate_image (dir, prefix, fp, outname,
   modules.entries, memdisk_path,
-  pubkeys, npubkeys, config_path, tgt,
+  pubkeys, npubkeys,  x509keys, nx509keys, 
config_path, tgt,
   note, appsig_size, compression, dtb, sbat,
 

[PATCH v2 18/21] powerpc_ieee1275: set use_static_keys flag

2025-03-26 Thread Sudhakar Kuppusamy
Introduce the use_static_keys flag to indicate that static keys are to be used
rather than keys from the PKS storage's DB variable. This variable is set when
Secure Boot is enabled with PKS but the DB variable is not present in the PKS 
storage.
The appendedsig module would use this variable to extract the default DB keys 
from
the ELF note and store the keys found there in the trustedlist.

Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Avnish Chouhan 
---
 .../kern/powerpc/ieee1275/platform_keystore.c| 16 +++-
 grub-core/term/tparm.c   |  1 -
 .../grub/powerpc/ieee1275/platform_keystore.h| 11 ++-
 include/grub/types.h |  2 ++
 4 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c 
b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
index cf1d0555e..a83fcf7cd 100644
--- a/grub-core/kern/powerpc/ieee1275/platform_keystore.c
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
@@ -34,7 +34,11 @@
 /* Platform Keystore */
 static grub_size_t pks_max_object_size;
 grub_uint8_t grub_pks_use_keystore = 0;
-grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, 
.dbx_entries = 0 };
+grub_pks_t grub_pks_keystore = { .db = NULL,
+ .dbx = NULL,
+ .db_entries = 0,
+ .dbx_entries = 0,
+ .use_static_keys = false };
 
 /* Convert the esl data into the ESL */
 static grub_esl_t *
@@ -312,6 +316,16 @@ grub_pks_keystore_init (void)
   grub_memset (&grub_pks_keystore, 0, sizeof (grub_pks_t));
   /* DB */
   rc = read_secure_boot_variables (0, DB, &grub_pks_keystore.db, 
&grub_pks_keystore.db_entries);
+  if (rc == PKS_OBJECT_NOT_FOUND)
+{
+  rc = GRUB_ERR_NONE;
+  /*
+   * DB variable won't be available by default in PKS.
+   * So, it will load the Default Keys from ELF Note
+   */
+  grub_pks_keystore.use_static_keys = true;
+}
+
   if (rc == GRUB_ERR_NONE)
 {
   /* DBX */
diff --git a/grub-core/term/tparm.c b/grub-core/term/tparm.c
index fb5b15a88..f2db325f6 100644
--- a/grub-core/term/tparm.c
+++ b/grub-core/term/tparm.c
@@ -46,7 +46,6 @@
 /*
  * Common/troublesome character definitions
  */
-typedef char grub_bool_t;
 #ifndef FALSE
 # define FALSE (0)
 #endif
diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h 
b/include/grub/powerpc/ieee1275/platform_keystore.h
index 0641adb0f..870fb8cc5 100644
--- a/include/grub/powerpc/ieee1275/platform_keystore.h
+++ b/include/grub/powerpc/ieee1275/platform_keystore.h
@@ -199,10 +199,11 @@ struct grub_pks_sd
 /* The structure of a PKS.*/
 struct grub_pks
 {
-  grub_pks_sd_t *db;/* signature database */
-  grub_pks_sd_t *dbx;   /* forbidden signature database */
-  grub_size_t db_entries;   /* size of signature database */
-  grub_size_t dbx_entries;  /* size of forbidden signature database */
+  grub_pks_sd_t *db;  /* signature database */
+  grub_pks_sd_t *dbx; /* forbidden signature database */
+  grub_size_t db_entries; /* size of signature database */
+  grub_size_t dbx_entries;/* size of forbidden signature database */
+  grub_bool_t use_static_keys;/* flag to indicate use of static keys */
 } GRUB_PACKED;
 
 #ifdef __powerpc__
@@ -217,7 +218,7 @@ extern grub_pks_t EXPORT_VAR(grub_pks_keystore);
 #else
 
 #define grub_pks_use_keystore  0
-grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0};
+grub_pks_t grub_pks_keystore = {NULL, NULL, 0, 0, false};
 void grub_pks_free_keystore (void);
 
 #endif
diff --git a/include/grub/types.h b/include/grub/types.h
index ce914decb..865d56a7e 100644
--- a/include/grub/types.h
+++ b/include/grub/types.h
@@ -397,4 +397,6 @@ struct grub_uuid
   grub_uint8_t b[GRUB_UUID_SIZE];
 };
 
+typedef char grub_bool_t;
+
 #endif /* ! GRUB_TYPES_HEADER */
-- 
2.43.5


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


[PATCH v2 06/21] crypto: move storage for grub_crypto_pk_* to crypto.c

2025-03-26 Thread Sudhakar Kuppusamy
From: Daniel Axtens 

The way gcry_rsa and friends (the asymmetric ciphers) are loaded for the
pgp module is a bit quirky.

include/grub/crypto.h contains:
  extern struct gcry_pk_spec *grub_crypto_pk_rsa;

commands/pgp.c contains the actual storage:
  struct gcry_pk_spec *grub_crypto_pk_rsa;

And the module itself saves to the storage in pgp.c:
  GRUB_MOD_INIT(gcry_rsa)
  {
grub_crypto_pk_rsa = &_gcry_pubkey_spec_rsa;
  }

This is annoying: gcry_rsa now has a dependency on pgp!

We want to be able to bring in gcry_rsa without bringing in PGP,
so move the storage to crypto.c.

Previously, gcry_rsa depended on pgp and mpi. Now it depends on
crypto and mpi. As pgp depends on crypto, this doesn't add any new
module dependencies using the PGP verfier.

[FWIW, the story is different for the symmetric ciphers. cryptodisk
and friends (zfs encryption etc) use grub_crypto_lookup_cipher_by_name()
to get a cipher handle. That depends on grub_ciphers being populated
by people calling grub_cipher_register. import_gcry.py ensures that the
symmetric ciphers call it.]

Signed-off-by: Daniel Axtens 
Signed-off-by: Sudhakar Kuppusamy 
Reviewed-by: Stefan Berger 
Reviewed-by: Vladimir Serbinenko 
Reviewed-by: Avnish Chouhan 
---
 grub-core/commands/pgp.c | 4 
 grub-core/lib/crypto.c   | 4 
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index 5503d291a..961abf775 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -147,10 +147,6 @@ const char *hashes[] = {
   [0x0b] = "sha224"
 };
 
-struct gcry_pk_spec *grub_crypto_pk_dsa;
-struct gcry_pk_spec *grub_crypto_pk_ecdsa;
-struct gcry_pk_spec *grub_crypto_pk_rsa;
-
 static int
 dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
 const gcry_md_spec_t *hash, struct grub_public_subkey *sk);
diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c
index 396f76410..d53ddbe2c 100644
--- a/grub-core/lib/crypto.c
+++ b/grub-core/lib/crypto.c
@@ -121,6 +121,10 @@ grub_md_unregister (gcry_md_spec_t *cipher)
   }
 }
 
+struct gcry_pk_spec *grub_crypto_pk_dsa;
+struct gcry_pk_spec *grub_crypto_pk_ecdsa;
+struct gcry_pk_spec *grub_crypto_pk_rsa;
+
 void
 grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
  grub_size_t inlen)
-- 
2.43.5


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


Re: [PATCH v2 3/3] blsuki: Add uki command to load Unified Kernel Image entries

2025-03-26 Thread Vladimir 'phcoder' Serbinenko
>
>
>
> +#ifdef GRUB_MACHINE_EFI
> +#include 
> +#include 
> +#include 
> +#endif
> +
>
Can UKI work without EFI? I think of scenario of putting e.g. EFI disk into
coreboot or BIOS machine.

>  GRUB_MOD_LICENSE ("GPLv3+");
>
>  #define GRUB_BLS_CONFIG_PATH "/loader/entries/"
> +#define GRUB_UKI_CONFIG_PATH "/EFI/Linux"
> +
> +#define GRUB_BLS_CMD 1
> +#define GRUB_UKI_CMD 2
> +
> +static int cmd_type = 0;
>
Can we make this into an enum?

>
>
>
> +  if (pe->optional_header.magic != GRUB_PE32_NATIVE_MAGIC)
> +{
> +  err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "non-native image
> not supported");
>
Maybe it's a bad kernel and not not implemented yet? Later indicates that
sick a config is valid, just not supported yet. Is it so?

> +
> +static char *
> +uki_read_osrel (char *content, grub_off_t *pos, char **key_ret, char
> **val_ret)
> +{
> +  char *line;
> +  char *value;
> +  grub_size_t linelen;
> +
> + skip:
> +  line = content + *pos;
> +  if (*line == '\0')
> +return NULL;
> +
> +  linelen = 0;
> +  while (line[linelen] != '\0' && !grub_strchr ("\n\r", line[linelen]))
>
While I recognize the elegance of strchr, we don't use this trick in the
code and it makes it more difficult to read. Can you use 2 comparisons
instead?

> +linelen++;
> +
> +  /* Move pos to the next line */
> +  *pos += linelen;
> +  if (content[*pos] != '\0')
> +(*pos)++;
> +
> +  /* Skip empty line */
> +  if (linelen == 0)
> +goto skip;
> +
> +  line[linelen] = '\0';
> +
> +  /* Remove leading white space */
> +  while (grub_strchr (" \t", *line))
>
Ditto

> +{
> +  line++;
> +  linelen--;
> +}
> +
> +  /* Remove trailing whitespace */
> +  while (linelen > 0 && grub_strchr ("=", line[linelen - 1]))
> +linelen--;
>
Comment doesn't match what really happens here. Also strchr with single
character string makes no sense.

> +  line[linelen] = '\0';
> +
> +  if (*line == '#')
> +goto skip;
> +
> +  /* Split key/value */
> +  value = line;
> +  while (*value != '\0' && !grub_strchr ("=", *value))
> +value++;
>
Ditto

> +  if (*value == '\0')
> +goto skip;
> +  *value = '\0';
> +  value++;
> +  while (*value != '\0' && grub_strchr ("=", *value))
> +value++;
>
Ditto

>
> +  if (grub_mul (argc + 1, sizeof (char *), &size))
> +{
> +  grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected creating
> argv list"));
>
Not worth translating. Generally the code which is only to guard against
malicious input is not worth translating

+  goto finish;
> +}
> +  argv = grub_malloc (size);
> +  if (argv == NULL)
> +{
> +  grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate argv list");
>
Grub_malloc already sets err no.

> +  goto finish;
> +}
> +  argv[0] = title;
> +  argv[argc] = NULL;
> +
> +  src = grub_xasprintf ("insmod chain\n"
>
Why do you need insmod? Didn't automatic insmod work?

+   "chainloader (%s)%s/%s%s%s\n",
> +   entry->devid, entry->dirname,
> +   entry->filename, options ? " " : "", options ?
> options : "");
>
Can we have a Linux variant for non-EFI?

>
>
>/*
> * If we aren't able to find BLS entries in the directory given by
> info->dirname,
> * we can fallback to the default location "/boot/loader/entries/" and
> see if we
> -   * can find the files there.
> +   * can find the files there. If we can't find UKI entries, fallback to
> +   * "/boot/efi/EFI/Linux".
> */
>
What's the purpose of fallback? It's not what user/script has requested. It
needs to be at very least disableable

>
>
> +   }
> +  else if (cmd_type == GRUB_UKI_CMD)
> +   {
> +#ifdef GRUB_MACHINE_EFI
> + grub_efi_loaded_image_t *image;
> + image = grub_efi_get_loaded_image (grub_efi_image_handle);
> + devid = grub_efidisk_get_device_name (image->device_handle);
> +#endif
>
This uses grub image location. What about a scenario when booted from
external drive and I want to boot into install on primary disk?

>
> +static grub_err_t
> +grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc __attribute__
> ((unused)),
> +char **args __attribute__ ((unused)))
> +{
> +  cmd_type = GRUB_BLS_CMD;
> +  return blsuki_cmd (ctxt);
>
Do we really need a static variable? Maybe a parameter is more appropriate?
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: [PATCH v4 05/12] tpm2_key_protector: Unseal key from a buffer

2025-03-26 Thread Gary Lin via Grub-devel
On Tue, Mar 25, 2025 at 05:01:02PM +0100, Daniel Kiper wrote:
> On Fri, Mar 21, 2025 at 03:59:01PM +0800, Gary Lin wrote:
> > Extract the logic to handle the file buffer from the SRK recover
> > function to prepare to load the sealed key from the NV index handle,
> > so the NV index mode can share the same code path in the later patch.
> > The SRK recover function now only reads the file and sends the file
> > buffer to the new function.
> >
> > Besides this, to avoid introducing more options for the NV index mode,
> > the file format is detected automatically before unmarshalling the data,
> > so there is no need to use the command option to specify the file format
> > anymore. In other words, '--tpm2key' and '--keyfile' are the same now.
> 
> You are referring to long options in the commit message but documentation
> updates doing some stuff around short ones. I can understand they are
> equivalent but I think you should be consistent and use short form
> everywhere or both in the commit message.
> 
Agree. Mixing the long and short options is confusing. I'll update the
commit message to use the short option.

> Additionally, it seems to me the docs mention short or long options but
> do not show there are some equivalents. Am I right? If yes I think this
> should be fixed in separate patch.
> 
When writing the document, I mainly use the short options. So yes, it
needs to address the equivalent long options. I'll update the document.

Gary Lin

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