Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package grub2 for openSUSE:Factory checked 
in at 2022-01-14 23:12:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/grub2 (Old)
 and      /work/SRC/openSUSE:Factory/.grub2.new.1892 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "grub2"

Fri Jan 14 23:12:59 2022 rev:257 rq:946360 version:2.06

Changes:
--------
--- /work/SRC/openSUSE:Factory/grub2/grub2.changes      2021-12-28 
12:26:09.052462769 +0100
+++ /work/SRC/openSUSE:Factory/.grub2.new.1892/grub2.changes    2022-01-14 
23:13:57.738659704 +0100
@@ -1,0 +2,45 @@
+Fri Jan 14 08:39:36 UTC 2022 - Michael Chang <mch...@suse.com>
+
+- Power guest secure boot with static keys: GRUB2 signing portion
+  (jsc#SLE-18271) (bsc#1192764)
+  * 0001-grub-install-Add-SUSE-signed-image-support-for-power.patch
+
+-------------------------------------------------------------------
+Tue Jan 11 03:49:15 UTC 2022 - Michael Chang <mch...@suse.com>
+
+- Power guest secure boot with static keys: GRUB2 signing portion
+  (jsc#SLE-18271) (bsc#1192764)
+  * grub2.spec
+- Power guest secure boot with static keys: GRUB2 portion (jsc#SLE-18144)
+  (bsc#1192686)
+  * 0001-ieee1275-Drop-HEAP_MAX_ADDR-and-HEAP_MIN_SIZE-consta.patch
+  * 0002-ieee1275-claim-more-memory.patch
+  * 0003-ieee1275-request-memory-with-ibm-client-architecture.patch
+  * 0004-Add-suport-for-signing-grub-with-an-appended-signatu.patch
+  * 0005-docs-grub-Document-signing-grub-under-UEFI.patch
+  * 0006-docs-grub-Document-signing-grub-with-an-appended-sig.patch
+  * 0007-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch
+  * 0008-pgp-factor-out-rsa_pad.patch
+  * 0009-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch
+  * 0010-posix_wrap-tweaks-in-preparation-for-libtasn1.patch
+  * 0011-libtasn1-import-libtasn1-4.18.0.patch
+  * 0012-libtasn1-disable-code-not-needed-in-grub.patch
+  * 0013-libtasn1-changes-for-grub-compatibility.patch
+  * 0014-libtasn1-compile-into-asn1-module.patch
+  * 0015-test_asn1-test-module-for-libtasn1.patch
+  * 0016-grub-install-support-embedding-x509-certificates.patch
+  * 0017-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch
+  * 0018-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch
+  * 0019-appended-signatures-support-verifying-appended-signa.patch
+  * 0020-appended-signatures-verification-tests.patch
+  * 0021-appended-signatures-documentation.patch
+  * 0022-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch
+  * 0023-x509-allow-Digitial-Signature-plus-other-Key-Usages.patch
+
+-------------------------------------------------------------------
+Mon Jan 10 09:38:46 UTC 2022 - Michael Chang <mch...@suse.com>
+
+- Fix no menuentry is found if hibernation on btrfs RAID1 (bsc#1193090)
+  * grub2-systemd-sleep-plugin
+
+-------------------------------------------------------------------

New:
----
  0001-grub-install-Add-SUSE-signed-image-support-for-power.patch
  0001-ieee1275-Drop-HEAP_MAX_ADDR-and-HEAP_MIN_SIZE-consta.patch
  0002-ieee1275-claim-more-memory.patch
  0003-ieee1275-request-memory-with-ibm-client-architecture.patch
  0004-Add-suport-for-signing-grub-with-an-appended-signatu.patch
  0005-docs-grub-Document-signing-grub-under-UEFI.patch
  0006-docs-grub-Document-signing-grub-with-an-appended-sig.patch
  0007-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch
  0008-pgp-factor-out-rsa_pad.patch
  0009-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch
  0010-posix_wrap-tweaks-in-preparation-for-libtasn1.patch
  0011-libtasn1-import-libtasn1-4.18.0.patch
  0012-libtasn1-disable-code-not-needed-in-grub.patch
  0013-libtasn1-changes-for-grub-compatibility.patch
  0014-libtasn1-compile-into-asn1-module.patch
  0015-test_asn1-test-module-for-libtasn1.patch
  0016-grub-install-support-embedding-x509-certificates.patch
  0017-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch
  0018-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch
  0019-appended-signatures-support-verifying-appended-signa.patch
  0020-appended-signatures-verification-tests.patch
  0021-appended-signatures-documentation.patch
  0022-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch
  0023-x509-allow-Digitial-Signature-plus-other-Key-Usages.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ grub2.spec ++++++
--- /var/tmp/diff_new_pack.d9XIXO/_old  2022-01-14 23:13:59.402660777 +0100
+++ /var/tmp/diff_new_pack.d9XIXO/_new  2022-01-14 23:13:59.406660779 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package grub2
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -52,7 +52,7 @@
 BuildRequires:  python
 %endif
 BuildRequires:  xz-devel
-%ifarch x86_64 aarch64
+%ifarch x86_64 aarch64 ppc ppc64 ppc64le
 %if 0%{?suse_version} >= 1230 || 0%{?suse_version} == 1110
 BuildRequires:  openssl >= 0.9.8
 BuildRequires:  pesign-obs-integration
@@ -76,6 +76,7 @@
 %ifarch ppc ppc64 ppc64le
 %define grubcpu powerpc
 %define platform ieee1275
+%define brp_pesign_reservation 65536
 # emu does not build here yet... :-(
 %define emu 0
 %endif
@@ -328,6 +329,30 @@
 Patch810:       0010-efilinux-Fix-integer-overflows-in-grub_cmd_initrd.patch
 Patch811:       0011-Also-define-GRUB_EFI_MAX_ALLOCATION_ADDRESS-for-RISC.patch
 Patch812:       0001-grub-mkconfig-restore-umask-for-grub.cfg.patch
+Patch813:       0001-ieee1275-Drop-HEAP_MAX_ADDR-and-HEAP_MIN_SIZE-consta.patch
+Patch814:       0002-ieee1275-claim-more-memory.patch
+Patch815:       0003-ieee1275-request-memory-with-ibm-client-architecture.patch
+Patch816:       0004-Add-suport-for-signing-grub-with-an-appended-signatu.patch
+Patch817:       0005-docs-grub-Document-signing-grub-under-UEFI.patch
+Patch818:       0006-docs-grub-Document-signing-grub-with-an-appended-sig.patch
+Patch819:       0007-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch
+Patch820:       0008-pgp-factor-out-rsa_pad.patch
+Patch821:       0009-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch
+Patch822:       0010-posix_wrap-tweaks-in-preparation-for-libtasn1.patch
+Patch823:       0011-libtasn1-import-libtasn1-4.18.0.patch
+Patch824:       0012-libtasn1-disable-code-not-needed-in-grub.patch
+Patch825:       0013-libtasn1-changes-for-grub-compatibility.patch
+Patch826:       0014-libtasn1-compile-into-asn1-module.patch
+Patch827:       0015-test_asn1-test-module-for-libtasn1.patch
+Patch828:       0016-grub-install-support-embedding-x509-certificates.patch
+Patch829:       0017-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch
+Patch830:       0018-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch
+Patch831:       0019-appended-signatures-support-verifying-appended-signa.patch
+Patch832:       0020-appended-signatures-verification-tests.patch
+Patch833:       0021-appended-signatures-documentation.patch
+Patch834:       0022-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch
+Patch835:       0023-x509-allow-Digitial-Signature-plus-other-Key-Usages.patch
+Patch836:       0001-grub-install-Add-SUSE-signed-image-support-for-power.patch
 
 Requires:       gettext-runtime
 %if 0%{?suse_version} >= 1140
@@ -354,8 +379,6 @@
 Requires:       powerpc-utils
 %endif
 
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-
 %if 0%{?only_x86_64:1}
 ExclusiveArch:  x86_64
 %else
@@ -591,28 +614,21 @@
 cd ..
 %endif
 
-%ifarch %{efi}
-cd build-efi
-../configure                                                   \
-        TARGET_LDFLAGS=-static                          \
-       --prefix=%{_prefix}                             \
-       --libdir=%{_datadir}                            \
-       --sysconfdir=%{_sysconfdir}                     \
-        --target=%{_target_platform}                    \
-        --with-platform=efi                             \
-        --program-transform-name=s,grub,%{name},
-make %{?_smp_mflags}
-
-#TODO: add efifwsetup module
-
 FS_MODULES="btrfs ext2 xfs jfs reiserfs"
-CD_MODULES=" all_video boot cat chain configfile echo true \
-               efifwsetup efinet font gfxmenu gfxterm gzio halt iso9660 \
+CD_MODULES="all_video boot cat configfile echo true \
+               font gfxmenu gfxterm gzio halt iso9660 \
                jpeg minicmd normal part_apple part_msdos part_gpt \
                password password_pbkdf2 png reboot search search_fs_uuid \
                search_fs_file search_label sleep test video fat loadenv"
-PXE_MODULES="efinet tftp http"
+PXE_MODULES="tftp http"
 CRYPTO_MODULES="luks gcry_rijndael gcry_sha1 gcry_sha256"
+%ifarch %{efi}
+CD_MODULES="${CD_MODULES} chain efifwsetup efinet"
+PXE_MODULES="${PXE_MODULES} efinet"
+%else
+CD_MODULES="${CD_MODULES} net"
+PXE_MODULES="${PXE_MODULES} net"
+%endif
 
 %ifarch x86_64
 CD_MODULES="${CD_MODULES} linuxefi"
@@ -620,6 +636,23 @@
 CD_MODULES="${CD_MODULES} linux"
 %endif
 
+GRUB_MODULES="${CD_MODULES} ${FS_MODULES} ${PXE_MODULES} ${CRYPTO_MODULES} 
mdraid09 mdraid1x lvm serial"
+%ifarch ppc ppc64 ppc64le
+GRUB_MODULES="${GRUB_MODULES} appendedsig memdisk tar regexp"
+%endif
+
+%ifarch %{efi}
+cd build-efi
+../configure                                                   \
+        TARGET_LDFLAGS=-static                          \
+       --prefix=%{_prefix}                             \
+       --libdir=%{_datadir}                            \
+       --sysconfdir=%{_sysconfdir}                     \
+        --target=%{_target_platform}                    \
+        --with-platform=efi                             \
+        --program-transform-name=s,grub,%{name},
+make %{?_smp_mflags}
+
 # SBAT metadata
 %if 0%{?is_opensuse} == 1
 distro_id="opensuse"
@@ -634,7 +667,6 @@
 echo "grub,${upstream_sbat},Free Software 
Foundation,grub,%{version},https://www.gnu.org/software/grub/"; >> sbat.csv
 echo 
"grub.${distro_id},${distro_sbat},${distro_name},%{name},%{version},mail:security-t...@suse.de"
 >> sbat.csv
 
-GRUB_MODULES="${CD_MODULES} ${FS_MODULES} ${PXE_MODULES} ${CRYPTO_MODULES} 
mdraid09 mdraid1x lvm serial"
 ./grub-mkimage -O %{grubefiarch} -o grub.efi --prefix= --sbat sbat.csv \
                -d grub-core ${GRUB_MODULES}
 %ifarch x86_64
@@ -695,6 +727,67 @@
        %{arch_specific}                \
         --program-transform-name=s,grub,%{name},
 make %{?_smp_mflags}
+
+if [ "%{platform}" = "ieee1275" ]; then
+        cert="%{_sourcedir}/_projectcert.crt"
+        openssl x509 -in "$cert" -outform DER -out grub.der
+        cat > %{platform}-config <<'EOF'
+set root=memdisk
+set prefix=($root)/
+echo "earlycfg: root=$root prefix=$prefix"
+EOF
+        cat > ./grub.cfg <<'EOF'
+
+regexp --set 1:bdev --set 2:bpart --set 3:bpath '\(([^,]+)(,?.*)?\)(.*)' 
"$cmdpath"
+
+echo "bdev=$bdev"
+echo "bpart=$bpart"
+echo "bpath=$bpath"
+
+if [ "$bdev" -a "$bpart" -a "$bpath" ]; then
+  hints="--hint $bdev$bpart"
+  cfg_dir="$bpath"
+elif [ "$bdev" -a "$bpart" ]; then
+  hints="--hint $bdev$bpart"
+  cfg_dir="/boot/grub2 /grub2"
+elif [ "$bdev" ]; then
+  hints="--hint ${bdev},"
+  cfg_dir="/boot/grub2 /grub2"
+else
+  hints=""
+  cfg_dir="/boot/grub2 /grub2"
+fi
+
+set prefix=""
+set root=""
+set cfg="grub.cfg"
+for d in ${cfg_dir}; do
+  set btrfs_relative_path=1
+  echo "start searching for $d/${cfg} with $hints"
+  if search --file --set=root "${d}/${cfg}" $hints; then
+    echo "${d}/${cfg} is on $root"
+    set btrfs_relative_path=0
+    if [ -f /@"${d}"/powerpc-ieee1275/command.lst ]; then
+      set btrfs_relative_path=1
+      echo "mounting subvolume @${d}/powerpc-ieee1275 on ${d}/powerpc-ieee1275"
+      btrfs-mount-subvol ($root) "${d}"/powerpc-ieee1275 
@"${d}"/powerpc-ieee1275
+    fi
+    set btrfs_relative_path=1
+    set prefix="($root)${d}"
+    break
+  fi
+done
+echo "prefix=$prefix root=$root"
+if [ -n "$prefix" ]; then
+  source "${prefix}/${cfg}"
+fi
+EOF
+        %{__tar} cvf memdisk.tar ./grub.cfg
+        ./grub-mkimage -O %{grubarch} -o grub.elf -d grub-core -x grub.der -m 
memdisk.tar \
+            -c %{platform}-config --appended-signature-size 
%brp_pesign_reservation ${GRUB_MODULES}
+        ls -l "grub.elf"
+        truncate -s -%brp_pesign_reservation "grub.elf"
+fi
 %endif
 cd ..
 %endif
@@ -757,6 +850,12 @@
 %if ! 0%{?only_efi:1}
 cd build
 %make_install
+if [ "%{platform}" = "ieee1275" ]; then
+        export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubarch}/grub.elf"
+        export BRP_PESIGN_GRUB_RESERVATION=%brp_pesign_reservation
+        install -m 444 grub.der %{buildroot}%{_datadir}/%{name}/%{grubarch}/
+        install -m 644 grub.elf %{buildroot}%{_datadir}/%{name}/%{grubarch}/
+fi
 cd ..
 %endif
 
@@ -1132,6 +1231,8 @@
 %ifarch ppc ppc64 ppc64le
 # This is intentionally "grub.chrp" and not "%%{name}.chrp"
 %{_datadir}/%{name}/%{grubarch}/grub.chrp
+%{_datadir}/%{name}/%{grubarch}/grub.elf
+%{_datadir}/%{name}/%{grubarch}/grub.der
 %{_datadir}/%{name}/%{grubarch}/bootinfo.txt
 %endif
 %ifnarch ppc ppc64 ppc64le s390x %{arm}

++++++ 0001-grub-install-Add-SUSE-signed-image-support-for-power.patch ++++++
>From 83a6f72e1896bd012b7fbca21317e96c2c22b327 Mon Sep 17 00:00:00 2001
From: Michal Suchanek <msucha...@suse.de>
Date: Wed, 12 Jan 2022 19:25:54 +0100
Subject: [PATCH] grub-install: Add SUSE signed image support for powerpc.

Signed-off-by: Michal Suchanek <msucha...@suse.de>
---
 grub-core/osdep/linux/platform.c | 13 +++++++++++++
 include/grub/util/install.h      |  3 +++
 util/grub-install.c              | 29 ++++++++++++++++++++++++++---
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/grub-core/osdep/linux/platform.c b/grub-core/osdep/linux/platform.c
index e28a79dab..2a12ed867 100644
--- a/grub-core/osdep/linux/platform.c
+++ b/grub-core/osdep/linux/platform.c
@@ -154,3 +154,16 @@ grub_install_get_default_x86_platform (void)
   grub_util_info ("... not found");
   return "i386-pc";
 }
+
+int
+grub_install_get_powerpc_secure_boot (void)
+{
+  int32_t ret = -1;
+  FILE *fp = grub_util_fopen ("/proc/device-tree/ibm,secure-boot", "rb");
+  if (fp) {
+    if (fread (&ret , 1, sizeof(ret), fp) > 0)
+      ret = grub_be_to_cpu32(ret);
+    fclose(fp);
+  }
+  return ret;
+}
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index c241a2a40..154487b72 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -233,6 +233,9 @@ grub_install_get_default_arm_platform (void);
 const char *
 grub_install_get_default_x86_platform (void);
 
+int
+grub_install_get_powerpc_secure_boot (void);
+
 int
 grub_install_register_efi (grub_device_t efidir_grub_dev,
                           const char *efifile_path,
diff --git a/util/grub-install.c b/util/grub-install.c
index a2286b3dd..8fb5ea616 100644
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -321,10 +321,10 @@ static struct argp_option options[] = {
   {"suse-enable-tpm", OPTION_SUSE_ENABLE_TPM, 0, 0, N_("install TPM modules"), 
0},
   {"suse-force-signed", OPTION_SUSE_FORCE_SIGNED, 0, 0,
    N_("force installation of signed grub" "%s."
-      "This option is only available on ARM64 EFI targets."), 0},
+      "This option is only available on ARM64 EFI and powerpc targets."), 0},
   {"suse-inhibit-signed", OPTION_SUSE_INHIBIT_SIGNED, 0, 0,
    N_("inhibit installation of signed grub. "
-      "This option is only available on ARM64 EFI targets."), 0},
+      "This option is only available on ARM64 EFI and powerpc targets."), 0},
   {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
   {"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2},
   {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2},
@@ -1724,6 +1724,7 @@ main (int argc, char *argv[])
   char mkimage_target[200];
   const char *core_name = NULL;
   char *signed_imgfile = NULL;
+  int ppc_sb_state = -1;
 
   switch (platform)
     {
@@ -1770,11 +1771,33 @@ main (int argc, char *argv[])
                grub_install_get_platform_platform (platform));
       break;
 
+
+    case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
+      ppc_sb_state = grub_install_get_powerpc_secure_boot();
+
+      if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == 
SIGNED_GRUB_AUTO) && (ppc_sb_state > 0)))
+       {
+         signed_imgfile = grub_util_path_concat (2, 
grub_install_source_directory, "grub.elf");
+         if (!grub_util_is_regular (signed_imgfile))
+           {
+             if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || (ppc_sb_state > 1))
+               grub_util_error ("signed image `%s' does not exist\n", 
signed_imgfile);
+             else
+               {
+                 free (signed_imgfile);
+                 signed_imgfile = NULL;
+               }
+           }
+       }
+
+      if (signed_imgfile)
+       fprintf (stderr, _("Use signed file in %s for installation.\n"), 
signed_imgfile);
+
+      /* fallthrough.  */
     case GRUB_INSTALL_PLATFORM_I386_COREBOOT:
     case GRUB_INSTALL_PLATFORM_ARM_COREBOOT:
     case GRUB_INSTALL_PLATFORM_I386_MULTIBOOT:
     case GRUB_INSTALL_PLATFORM_I386_IEEE1275:
-    case GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275:
     case GRUB_INSTALL_PLATFORM_I386_XEN:
     case GRUB_INSTALL_PLATFORM_X86_64_XEN:
     case GRUB_INSTALL_PLATFORM_I386_XEN_PVH:
-- 
2.31.1


++++++ 0001-ieee1275-Drop-HEAP_MAX_ADDR-and-HEAP_MIN_SIZE-consta.patch ++++++
>From 41589d37934c7e4c464a584939de0137af7a181b Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 20 Jul 2021 17:14:46 -0400
Subject: [PATCH 01/23] ieee1275: Drop HEAP_MAX_ADDR and HEAP_MIN_SIZE
 constants

The HEAP_MAX_ADDR is confusing. Currently it is set to 32MB, except on
ieee1275 on x86, where it is 64MB.

There is a comment which purports to explain it:

  /* If possible, we will avoid claiming heap above this address, because it
     seems to cause relocation problems with OSes that link at 4 MiB */

This doesn't make a lot of sense when the constants are well above 4MB
already. It was not always this way. Prior to commit 7b5d0fe4440c
(Increase heap limit) in 2010, HEAP_MAX_SIZE and HEAP_MAX_ADDR were
indeed 4MB. However, when the constants were increased the comment was
left unchanged.

It's been over a decade. It doesn't seem like we have problems with
claims over 4MB on powerpc or x86 ieee1275. The SPARC does things
completely differently and never used the constant.

Drop the constant and the check.

The only use of HEAP_MIN_SIZE was to potentially override the
HEAP_MAX_ADDR check. It is now unused. Remove it too.

Signed-off-by: Daniel Axtens <d...@axtens.net>
Signed-off-by: Stefan Berger <stef...@linux.ibm.com>
Tested-by: Stefan Berger <stef...@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
---
 grub-core/kern/ieee1275/init.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 1187492ae..c15d40e55 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -45,9 +45,6 @@
 #include <grub/machine/kernel.h>
 #endif
 
-/* The minimal heap size we can live with. */
-#define HEAP_MIN_SIZE          (unsigned long) (2 * 1024 * 1024)
-
 /* The maximum heap size we're going to claim */
 #ifdef __i386__
 #define HEAP_MAX_SIZE          (unsigned long) (64 * 1024 * 1024)
@@ -55,14 +52,6 @@
 #define HEAP_MAX_SIZE          (unsigned long) (32 * 1024 * 1024)
 #endif
 
-/* If possible, we will avoid claiming heap above this address, because it
-   seems to cause relocation problems with OSes that link at 4 MiB */
-#ifdef __i386__
-#define HEAP_MAX_ADDR          (unsigned long) (64 * 1024 * 1024)
-#else
-#define HEAP_MAX_ADDR          (unsigned long) (32 * 1024 * 1024)
-#endif
-
 extern char _start[];
 extern char _end[];
 
@@ -184,12 +173,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, 
grub_memory_type_t type,
   if (*total + len > HEAP_MAX_SIZE)
     len = HEAP_MAX_SIZE - *total;
 
-  /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
-  if ((addr < HEAP_MAX_ADDR) &&                                /* if it's too 
late, don't bother */
-      (addr + len > HEAP_MAX_ADDR) &&                          /* if it wasn't 
available anyway, don't bother */
-      (*total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE))       /* only limit 
ourselves when we can afford to */
-     len = HEAP_MAX_ADDR - addr;
-
   /* In theory, firmware should already prevent this from happening by not
      listing our own image in /memory/available.  The check below is intended
      as a safeguard in case that doesn't happen.  However, it doesn't protect
-- 
2.31.1


++++++ 0002-ieee1275-claim-more-memory.patch ++++++
>From 7f2590e8715b634ffea9cb7b538ac076d86fab40 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Wed, 15 Apr 2020 23:28:29 +1000
Subject: [PATCH 02/23] ieee1275: claim more memory

On powerpc-ieee1275, we are running out of memory trying to verify
anything. This is because:

 - we have to load an entire file into memory to verify it. This is
   extremely difficult to change with appended signatures.
 - We only have 32MB of heap.
 - Distro kernels are now often around 30MB.

So we want to claim more memory from OpenFirmware for our heap.

There are some complications:

 - The grub mm code isn't the only thing that will make claims on
   memory from OpenFirmware:

    * PFW/SLOF will have claimed some for their own use.

    * The ieee1275 loader will try to find other bits of memory that we
      haven't claimed to place the kernel and initrd when we go to boot.

    * Once we load Linux, it will also try to claim memory. It claims
      memory without any reference to /memory/available, it just starts
      at min(top of RMO, 768MB) and works down. So we need to avoid this
      area. See arch/powerpc/kernel/prom_init.c as of v5.11.

 - The smallest amount of memory a ppc64 KVM guest can have is 256MB.
   It doesn't work with distro kernels but can work with custom kernels.
   We should maintain support for that. (ppc32 can boot with even less,
   and we shouldn't break that either.)

 - Even if a VM has more memory, the memory OpenFirmware makes available
   as Real Memory Area can be restricted. A freshly created LPAR on a
   PowerVM machine is likely to have only 256MB available to OpenFirmware
   even if it has many gigabytes of memory allocated.

EFI systems will attempt to allocate 1/4th of the available memory,
clamped to between 1M and 1600M. That seems like a good sort of
approach, we just need to figure out if 1/4 is the right fraction
for us.

We don't know in advance how big the kernel and initrd are going to be,
which makes figuring out how much memory we can take a bit tricky.

To figure out how much memory we should leave unused, I looked at:

 - an Ubuntu 20.04.1 ppc64le pseries KVM guest:
    vmlinux: ~30MB
    initrd:  ~50MB

 - a RHEL8.2 ppc64le pseries KVM guest:
    vmlinux: ~30MB
    initrd:  ~30MB

Ubuntu VMs struggle to boot with just 256MB under SLOF.
RHEL likewise has a higher minimum supported memory figure.
So lets first consider a distro kernel and 512MB of addressible memory.
(This is the default case for anything booting under PFW.) Say we lose
131MB to PFW (based on some tests). This leaves us 381MB. 1/4 of 381MB
is ~95MB. That should be enough to verify a 30MB vmlinux and should
leave plenty of space to load Linux and the initrd.

If we consider 256MB of RMA under PFW, we have just 125MB remaining. 1/4
of that is a smidge under 32MB, which gives us very poor odds of verifying
a distro-sized kernel. However, if we need 80MB just to put the kernel
and initrd in memory, we can't claim any more than 45MB anyway. So 1/4
will do. We'll come back to this later.

grub is always built as a 32-bit binary, even if it's loading a ppc64
kernel. So we can't address memory beyond 4GB. This gives a natural cap
of 1GB for powerpc-ieee1275.

Also apply this 1/4 approach to i386-ieee1275, but keep the 32MB cap.

make check still works for both i386 and powerpc and I've booted
powerpc grub with this change under SLOF and PFW.

Signed-off-by: Daniel Axtens <d...@axtens.net>
---
 docs/grub-dev.texi             |  6 ++-
 grub-core/kern/ieee1275/init.c | 70 ++++++++++++++++++++++++++++------
 2 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
index 6c629a23e..c11f1ac46 100644
--- a/docs/grub-dev.texi
+++ b/docs/grub-dev.texi
@@ -1047,7 +1047,9 @@ space is limited to 4GiB. GRUB allocates pages from EFI 
for its heap, at most
 1.6 GiB.
 
 On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275.
-It allocates at most 32MiB for its heap.
+
+On i386-ieee1275, GRUB allocates at most 32MiB for its heap. On
+powerpc-ieee1275, GRUB allocates up to 1GiB.
 
 On sparc64-ieee1275 stack is 256KiB and heap is 2MiB.
 
@@ -1075,7 +1077,7 @@ In short:
 @item i386-qemu               @tab 60 KiB  @tab < 4 GiB
 @item *-efi                   @tab ?       @tab < 1.6 GiB
 @item i386-ieee1275           @tab ?       @tab < 32 MiB
-@item powerpc-ieee1275        @tab ?       @tab < 32 MiB
+@item powerpc-ieee1275        @tab ?       @tab < 1 GiB
 @item sparc64-ieee1275        @tab 256KiB  @tab 2 MiB
 @item arm-uboot               @tab 256KiB  @tab 2 MiB
 @item mips(el)-qemu_mips      @tab 2MiB    @tab 253 MiB
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index c15d40e55..d661a8da5 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -45,11 +45,12 @@
 #include <grub/machine/kernel.h>
 #endif
 
-/* The maximum heap size we're going to claim */
+/* The maximum heap size we're going to claim. Not used by sparc.
+   We allocate 1/4 of the available memory under 4G, up to this limit. */
 #ifdef __i386__
 #define HEAP_MAX_SIZE          (unsigned long) (64 * 1024 * 1024)
-#else
-#define HEAP_MAX_SIZE          (unsigned long) (32 * 1024 * 1024)
+#else // __powerpc__
+#define HEAP_MAX_SIZE          (unsigned long) (1 * 1024 * 1024 * 1024)
 #endif
 
 extern char _start[];
@@ -146,16 +147,45 @@ grub_claim_heap (void)
                                 + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
 }
 #else
-/* Helper for grub_claim_heap.  */
+/* Helper for grub_claim_heap on powerpc. */
+static int
+heap_size (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
+          void *data)
+{
+  grub_uint32_t total = *(grub_uint32_t *)data;
+
+  if (type != GRUB_MEMORY_AVAILABLE)
+    return 0;
+
+  /* Do not consider memory beyond 4GB */
+  if (addr > 0xffffffffUL)
+    return 0;
+
+  if (addr + len > 0xffffffffUL)
+    len = 0xffffffffUL - addr;
+
+  total += len;
+  *(grub_uint32_t *)data = total;
+
+  return 0;
+}
+
 static int
 heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
           void *data)
 {
-  unsigned long *total = data;
+  grub_uint32_t total = *(grub_uint32_t *)data;
 
   if (type != GRUB_MEMORY_AVAILABLE)
     return 0;
 
+  /* Do not consider memory beyond 4GB */
+  if (addr > 0xffffffffUL)
+    return 0;
+
+  if (addr + len > 0xffffffffUL)
+    len = 0xffffffffUL - addr;
+
   if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))
     {
       if (addr + len <= 0x180000)
@@ -169,10 +199,6 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, 
grub_memory_type_t type,
     }
   len -= 1; /* Required for some firmware.  */
 
-  /* Never exceed HEAP_MAX_SIZE  */
-  if (*total + len > HEAP_MAX_SIZE)
-    len = HEAP_MAX_SIZE - *total;
-
   /* In theory, firmware should already prevent this from happening by not
      listing our own image in /memory/available.  The check below is intended
      as a safeguard in case that doesn't happen.  However, it doesn't protect
@@ -184,6 +210,18 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, 
grub_memory_type_t type,
       len = 0;
     }
 
+  /* If this block contains 0x30000000 (768MB), do not claim below that.
+     Linux likes to claim memory at min(RMO top, 768MB) and works down
+     without reference to /memory/available. */
+  if ((addr < 0x30000000) && ((addr + len) > 0x30000000))
+    {
+      len = len - (0x30000000 - addr);
+      addr = 0x30000000;
+    }
+
+  if (len > total)
+    len = total;
+
   if (len)
     {
       grub_err_t err;
@@ -192,10 +230,12 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, 
grub_memory_type_t type,
       if (err)
        return err;
       grub_mm_init_region ((void *) (grub_addr_t) addr, len);
+      total -= len;
     }
 
-  *total += len;
-  if (*total >= HEAP_MAX_SIZE)
+  *(grub_uint32_t *)data = total;
+
+  if (total == 0)
     return 1;
 
   return 0;
@@ -204,7 +244,13 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, 
grub_memory_type_t type,
 static void 
 grub_claim_heap (void)
 {
-  unsigned long total = 0;
+  grub_uint32_t total = 0;
+
+  grub_machine_mmap_iterate (heap_size, &total);
+
+  total = total / 4;
+  if (total > HEAP_MAX_SIZE)
+    total = HEAP_MAX_SIZE;
 
   if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM))
     heap_init (GRUB_IEEE1275_STATIC_HEAP_START, GRUB_IEEE1275_STATIC_HEAP_LEN,
-- 
2.31.1


++++++ 0003-ieee1275-request-memory-with-ibm-client-architecture.patch ++++++
>From bbfcae1cd408c4922ddcefc0528bfe19da845c90 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Fri, 16 Apr 2021 11:48:46 +1000
Subject: [PATCH 03/23] ieee1275: request memory with
 ibm,client-architecture-support

On PowerVM, the first time we boot a Linux partition, we may only get
256MB of real memory area, even if the partition has more memory.

This isn't really enough. Fortunately, the Power Architecture Platform
Reference (PAPR) defines a method we can call to ask for more memory.
This is part of the broad and powerful ibm,client-architecture-support
(CAS) method.

CAS can do an enormous amount of things on a PAPR platform: as well as
asking for memory, you can set the supported processor level, the interrupt
controller, hash vs radix mmu, and so on. We want to touch as little of
this as possible because we don't want to step on the toes of the future OS.

If:

 - we are running under what we think is PowerVM (compatible property of /
   begins with "IBM"), and

 - the full amount of RMA is less than 512MB (as determined by the reg
   property of /memory)

then call CAS as follows: (refer to the Linux on Power Architecture
Reference, LoPAR, which is public, at B.5.2.3):

 - Use the "any" PVR value and supply 2 option vectors.

 - Set option vector 1 (PowerPC Server Processor Architecture Level)
   to "ignore".

 - Set option vector 2 with default or Linux-like options, including a
   min-rma-size of 512MB.

This will cause a CAS reboot and the partition will restart with 512MB
of RMA. Grub will notice the 512MB and not call CAS again.

(A partition can be configured with only 256MB of memory, which would
mean this request couldn't be satisfied, but PFW refuses to load with
only 256MB of memory, so it's a bit moot. SLOF will run fine with 256MB,
but we will never call CAS under qemu/SLOF because /compatible won't
begin with "IBM".)

One of the first things Linux does while still running under OpenFirmware
is to call CAS with a much fuller set of options (including asking for
512MB of memory). This includes a much more restrictive set of PVR values
and processor support levels, and this will induce another reboot. On this
reboot grub will again notice the higher RMA, and not call CAS. We will get
to Linux, Linux will call CAS but because the values are now set for Linux
this will not induce another CAS reboot and we will finally boot.

On all subsequent boots, everything will be configured with 512MB of RMA
and all the settings Linux likes, so there will be no further CAS reboots.

(phyp is super sticky with the RMA size - it persists even on cold boots.
So if you've ever booted Linux in a partition, you'll probably never have
grub call CAS. It'll only ever fire the first time a partition loads grub,
or if you deliberately lower the amount of memory your partition has below
512MB.)

Signed-off-by: Daniel Axtens <d...@axtens.net>
---
 grub-core/kern/ieee1275/cmain.c  |   3 +
 grub-core/kern/ieee1275/init.c   | 140 +++++++++++++++++++++++++++++++
 include/grub/ieee1275/ieee1275.h |   8 +-
 3 files changed, 150 insertions(+), 1 deletion(-)

diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c
index e9a184657..ee63c7b71 100644
--- a/grub-core/kern/ieee1275/cmain.c
+++ b/grub-core/kern/ieee1275/cmain.c
@@ -127,6 +127,9 @@ grub_ieee1275_find_options (void)
              break;
            }
        }
+
+      if (grub_strncmp (tmp, "IBM,", 4) == 0)
+       grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY);
     }
 
   if (is_smartfirmware)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index d661a8da5..446201165 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -241,11 +241,151 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, 
grub_memory_type_t type,
   return 0;
 }
 
+/* How much memory does OF believe it has? (regardless of whether
+   it's accessible or not) */
+static grub_err_t
+grub_ieee1275_total_mem (grub_uint64_t *total)
+{
+  grub_ieee1275_phandle_t root;
+  grub_ieee1275_phandle_t memory;
+  grub_uint32_t reg[4];
+  grub_ssize_t reg_size;
+  grub_uint32_t address_cells = 1;
+  grub_uint32_t size_cells = 1;
+  grub_uint64_t size;
+
+  /* If we fail to get to the end, report 0. */
+  *total = 0;
+
+  /* Determine the format of each entry in `reg'.  */
+  grub_ieee1275_finddevice ("/", &root);
+  grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
+                                     sizeof address_cells, 0);
+  grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
+                                     sizeof size_cells, 0);
+
+  if (size_cells > address_cells)
+    address_cells = size_cells;
+
+  /* Load `/memory/reg'.  */
+  if (grub_ieee1275_finddevice ("/memory", &memory))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                      "couldn't find /memory node");
+  if (grub_ieee1275_get_integer_property (memory, "reg", reg,
+                                         sizeof reg, &reg_size))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                      "couldn't examine /memory/reg property");
+  if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg))
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+                       "/memory response buffer exceeded");
+
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS))
+    {
+      address_cells = 1;
+      size_cells = 1;
+    }
+
+  /* Decode only the size */
+  size = reg[address_cells];
+  if (size_cells == 2)
+    size = (size << 32) | reg[address_cells + 1];
+
+  *total = size;
+
+  return grub_errno;
+}
+
+/* Based on linux - arch/powerpc/kernel/prom_init.c */
+struct option_vector2 {
+       grub_uint8_t byte1;
+       grub_uint16_t reserved;
+       grub_uint32_t real_base;
+       grub_uint32_t real_size;
+       grub_uint32_t virt_base;
+       grub_uint32_t virt_size;
+       grub_uint32_t load_base;
+       grub_uint32_t min_rma;
+       grub_uint32_t min_load;
+       grub_uint8_t min_rma_percent;
+       grub_uint8_t max_pft_size;
+} __attribute__((packed));
+
+struct pvr_entry {
+         grub_uint32_t mask;
+         grub_uint32_t entry;
+};
+
+struct cas_vector {
+    struct {
+      struct pvr_entry terminal;
+    } pvr_list;
+    grub_uint8_t num_vecs;
+    grub_uint8_t vec1_size;
+    grub_uint8_t vec1;
+    grub_uint8_t vec2_size;
+    struct option_vector2 vec2;
+} __attribute__((packed));
+
+/* Call ibm,client-architecture-support to try to get more RMA.
+   We ask for 512MB which should be enough to verify a distro kernel.
+   We ignore most errors: if we don't succeed we'll proceed with whatever
+   memory we have. */
+static void
+grub_ieee1275_ibm_cas (void)
+{
+  int rc;
+  grub_ieee1275_ihandle_t root;
+  struct cas_args {
+    struct grub_ieee1275_common_hdr common;
+    grub_ieee1275_cell_t method;
+    grub_ieee1275_ihandle_t ihandle;
+    grub_ieee1275_cell_t cas_addr;
+    grub_ieee1275_cell_t result;
+  } args;
+  struct cas_vector vector = {
+    .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */
+    .num_vecs = 2 - 1,
+    .vec1_size = 0,
+    .vec1 = 0x80, /* ignore */
+    .vec2_size = 1 + sizeof(struct option_vector2) - 2,
+    .vec2 = {
+      0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48
+    },
+  };
+
+  INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
+  args.method = (grub_ieee1275_cell_t)"ibm,client-architecture-support";
+  rc = grub_ieee1275_open("/", &root);
+  if (rc) {
+         grub_error (GRUB_ERR_IO, "could not open root when trying to call 
CAS");
+         return;
+  }
+  args.ihandle = root;
+  args.cas_addr = (grub_ieee1275_cell_t)&vector;
+
+  grub_printf("Calling ibm,client-architecture-support...");
+  IEEE1275_CALL_ENTRY_FN (&args);
+  grub_printf("done\n");
+
+  grub_ieee1275_close(root);
+}
+
 static void 
 grub_claim_heap (void)
 {
   grub_uint32_t total = 0;
 
+  if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY))
+    {
+      grub_uint64_t rma_size;
+      grub_err_t err;
+
+      err = grub_ieee1275_total_mem (&rma_size);
+      /* if we have an error, don't call CAS, just hope for the best */
+      if (!err && rma_size < (512 * 1024 * 1024))
+       grub_ieee1275_ibm_cas();
+    }
+
   grub_machine_mmap_iterate (heap_size, &total);
 
   total = total / 4;
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index debb7086a..591f4f12c 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -155,7 +155,13 @@ enum grub_ieee1275_flag
 
   GRUB_IEEE1275_FLAG_RAW_DEVNAMES,
 
-  GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT
+  GRUB_IEEE1275_FLAG_DISABLE_VIDEO_SUPPORT,
+
+  /* On PFW, the first time we boot a Linux partition, we may only get 256MB
+     of real memory area, even if the partition has more memory. Set this flag
+     if we think we're running under PFW. Then, if this flag is set, and the
+     RMA is only 256MB in size, try asking for more with CAS. */
+  GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY,
 };
 
 extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag);
-- 
2.31.1


++++++ 0004-Add-suport-for-signing-grub-with-an-appended-signatu.patch ++++++
>From cf6b16f113b1b5e6efce79b569be1de3e504de8f Mon Sep 17 00:00:00 2001
From: Rashmica Gupta <rashmic...@gmail.com>
Date: Thu, 11 Jun 2020 11:26:23 +1000
Subject: [PATCH 04/23] Add suport for signing grub with an appended signature

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: Daniel Axtens <d...@axtens.net>
Signed-off-by: Rashmica Gupta <rashmic...@gmail.com>

---

You can experiment with this code with a patched version of SLOF
that verifies these signatures. You can find one at:
   https://github.com/daxtens/SLOF

I will be proposing this for inclusion in a future Power Architecture
Platform Reference (PAPR).
---
 include/grub/util/install.h |  8 ++++++--
 include/grub/util/mkimage.h |  4 ++--
 util/grub-install-common.c  | 15 +++++++++++---
 util/grub-mkimage.c         | 11 +++++++++++
 util/grub-mkimagexx.c       | 39 ++++++++++++++++++++++++++++++++++++-
 util/mkimage.c              | 13 +++++++------
 6 files changed, 76 insertions(+), 14 deletions(-)

diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 9e83e1339..0b2e8a06d 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -67,6 +67,9 @@
       N_("SBAT metadata"), 0 },                                                
\
   { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
       N_("disable shim_lock verifier"), 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 }
 
@@ -129,7 +132,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
   GRUB_INSTALL_OPTIONS_DTB,
   GRUB_INSTALL_OPTIONS_SBAT,
-  GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
+  GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
+  GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
 };
 
 extern char *grub_install_source_directory;
@@ -189,7 +193,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);
 
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 3819a6744..6f1da89b9 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 **core_img, size_t *core_size,
+                            int note, 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 **core_img, size_t *core_size,
+                            int note, 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 c6c561292..954df20eb 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -461,10 +461,12 @@ static size_t npubkeys;
 static char *sbat;
 static int disable_shim_lock;
 static grub_compression_t compression;
+static size_t appsig_size;
 
 int
 grub_install_parse (int key, char *arg)
 {
+  const char *end;
   switch (key)
     {
     case 'C':
@@ -562,6 +564,12 @@ grub_install_parse (int key, char *arg)
       grub_util_error (_("Unrecognized compression `%s'"), arg);
     case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
       return 1;
+    case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE:
+      grub_errno = 0;
+      appsig_size = grub_strtol(arg, &end, 10);
+      if (grub_errno)
+        return 0;
+      return 1;
     default:
       return 0;
     }
@@ -661,10 +669,11 @@ grub_install_make_image_wrap_file (const char *dir, const 
char *prefix,
                  " --output '%s' "
                  " --dtb '%s' "
                  "--sbat '%s' "
-                 "--format '%s' --compression '%s' %s %s %s\n",
+                 "--format '%s' --compression '%s' "
+                 "--appended-signature-size %zu %s %s %s\n",
                  dir, prefix,
                  outname, dtb ? : "", sbat ? : "", mkimage_target,
-                 compnames[compression], note ? "--note" : "",
+                 compnames[compression], appsig_size, note ? "--note" : "",
                  disable_shim_lock ? "--disable-shim-lock" : "", s);
   free (s);
 
@@ -675,7 +684,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,
-                              note, compression, dtb, sbat,
+                              note, appsig_size, compression, dtb, sbat,
                               disable_shim_lock);
   while (dc--)
     grub_install_pop_module ();
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index c0d559937..d01eaeb84 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -84,6 +84,7 @@ static struct argp_option options[] = {
   {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
   {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, 
N_("disable shim_lock verifier"), 0},
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
+  {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment 
reserving SIZE bytes for an appended signature"), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
 
@@ -128,6 +129,7 @@ struct arguments
   char *sbat;
   int note;
   int disable_shim_lock;
+  size_t appsig_size;
   const struct grub_install_image_target_desc *image_target;
   grub_compression_t comp;
 };
@@ -138,6 +140,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
   /* Get the input argument from argp_parse, which we
      know is a pointer to our arguments structure. */
   struct arguments *arguments = state->input;
+  const char* end;
 
   switch (key)
     {
@@ -170,6 +173,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->note = 1;
       break;
 
+    case 'S':
+      grub_errno = 0;
+      arguments->appsig_size = grub_strtol(arg, &end, 10);
+      if (grub_errno)
+        return 0;
+      break;
+
     case 'm':
       if (arguments->memdisk)
        free (arguments->memdisk);
@@ -324,6 +334,7 @@ main (int argc, char *argv[])
                               arguments.memdisk, arguments.pubkeys,
                               arguments.npubkeys, arguments.config,
                               arguments.image_target, arguments.note,
+                              arguments.appsig_size,
                               arguments.comp, arguments.dtb,
                               arguments.sbat, arguments.disable_shim_lock);
 
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index d78fa3e53..393119486 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -84,6 +84,15 @@ struct grub_ieee1275_note
   struct grub_ieee1275_note_desc descriptor;
 };
 
+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
+
+struct grub_appended_signature_note
+{
+  Elf32_Nhdr header;
+  char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)];
+};
+
 #define GRUB_XEN_NOTE_NAME "Xen"
 
 struct fixup_block_list
@@ -207,7 +216,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr 
sym_addr)
 
 void
 SUFFIX (grub_mkimage_generate_elf) (const struct 
grub_install_image_target_desc *image_target,
-                                   int note, char **core_img, size_t 
*core_size,
+                                   int note, size_t appsig_size, char 
**core_img, size_t *core_size,
                                    Elf_Addr target_addr,
                                    struct grub_mkimage_layout *layout)
 {
@@ -221,6 +230,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct 
grub_install_image_target_desc
   int shnum = 4;
   int string_size = sizeof (".text") + sizeof ("mods") + 1;
 
+  if (appsig_size)
+    {
+      phnum++;
+      footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + 
appsig_size, 4);
+    }
+
   if (image_target->id != IMAGE_LOONGSON_ELF)
     phnum += 2;
 
@@ -484,6 +499,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct 
grub_install_image_target_desc
       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
     }
 
+  if (appsig_size) {
+    int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + 
appsig_size, 4);
+    struct grub_appended_signature_note *note_ptr = (struct 
grub_appended_signature_note *)
+      (elf_img + program_size + header_size + (note ? sizeof (struct 
grub_ieee1275_note) : 0));
+
+    note_ptr->header.n_namesz = grub_host_to_target32 (sizeof 
(GRUB_APPENDED_SIGNATURE_NOTE_NAME));
+    /* needs to sit at the end, so we round this up and sign some zero padding 
*/
+    note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 
4));
+    note_ptr->header.n_type = grub_host_to_target32 
(GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
+    strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
+
+    phdr++;
+    phdr->p_type = grub_host_to_target32 (PT_NOTE);
+    phdr->p_flags = grub_host_to_target32 (PF_R);
+    phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+    phdr->p_vaddr = 0;
+    phdr->p_paddr = 0;
+    phdr->p_filesz = grub_host_to_target32 (note_size);
+    phdr->p_memsz = 0;
+    phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note 
? sizeof (struct grub_ieee1275_note) : 0));
+  }
+
   {
     char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
                       + shnum * sizeof (*shdr));
diff --git a/util/mkimage.c b/util/mkimage.c
index a26cf76f7..d2cb33883 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -869,8 +869,9 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
                             char *memdisk_path, char **pubkey_paths,
                             size_t npubkeys, char *config_path,
                             const struct grub_install_image_target_desc 
*image_target,
-                            int note, grub_compression_t comp, const char 
*dtb_path,
-                            const char *sbat_path, int disable_shim_lock)
+                            int note, size_t appsig_size, grub_compression_t 
comp,
+                            const char *dtb_path, const char *sbat_path, 
+                            int disable_shim_lock)
 {
   char *kernel_img, *core_img;
   size_t total_module_size, core_size;
@@ -1773,11 +1774,11 @@ grub_install_generate_image (const char *dir, const 
char *prefix,
        else
          target_addr = image_target->link_addr;
        if (image_target->voidp_sizeof == 4)
-         grub_mkimage_generate_elf32 (image_target, note, &core_img, 
&core_size,
-                                      target_addr, &layout);
+         grub_mkimage_generate_elf32 (image_target, note, appsig_size, 
&core_img,
+                                      &core_size, target_addr, &layout);
        else
-         grub_mkimage_generate_elf64 (image_target, note, &core_img, 
&core_size,
-                                      target_addr, &layout);
+         grub_mkimage_generate_elf64 (image_target, note, appsig_size, 
&core_img,
+                                      &core_size, target_addr, &layout);
       }
       break;
     }
-- 
2.31.1


++++++ 0005-docs-grub-Document-signing-grub-under-UEFI.patch ++++++
>From f7b9580133cf346d77f345d175fa5cb8a591be16 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Sat, 15 Aug 2020 02:00:57 +1000
Subject: [PATCH 05/23] docs/grub: Document signing grub under UEFI

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 <d...@axtens.net>
---
 docs/grub.texi | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index e48018c5f..b1d808d93 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5814,6 +5814,7 @@ environment variables and commands are listed in the same 
order.
 * Secure Boot Advanced Targeting::   Embedded information for generation 
number based revocation
 * Measured Boot::                    Measuring boot components
 * Lockdown::                         Lockdown when booting on a secure setup
+* Signing GRUB itself::              Ensuring the integrity of the GRUB core 
image
 @end menu
 
 @node Authentication and authorisation
@@ -5892,7 +5893,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}
@@ -6054,6 +6055,25 @@ be restricted and some operations/commands cannot be 
executed.
 The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down.
 Otherwise it does not exit.
 
+@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 enrol the public key used into a relevant firmware
+key database.
+
 @node Platform limitations
 @chapter Platform limitations
 
-- 
2.31.1


++++++ 0006-docs-grub-Document-signing-grub-with-an-appended-sig.patch ++++++
>From ac539a315495792cd75fe8ab1c474f26e0a78852 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Sat, 15 Aug 2020 02:19:36 +1000
Subject: [PATCH 06/23] docs/grub: Document signing grub with an appended
 signature

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 <d...@axtens.net>
---
 docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index b1d808d93..dc1c58304 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6074,6 +6074,48 @@ image works under UEFI secure boot and can maintain the 
secure-boot chain. It
 will also be necessary to enrol 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.31.1


++++++ 0007-dl-provide-a-fake-grub_dl_set_persistent-for-the-emu.patch ++++++
>From 4773f90bdefb72dde55fb5961f7f37b467307016 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Thu, 30 Jul 2020 00:13:21 +1000
Subject: [PATCH 07/23] dl: provide a fake grub_dl_set_persistent for the emu
 target

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 <d...@axtens.net>
---
 include/grub/dl.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/grub/dl.h b/include/grub/dl.h
index b3753c9ca..5decbe2f2 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -243,11 +243,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.31.1


++++++ 0008-pgp-factor-out-rsa_pad.patch ++++++
>From 923c8f6807cbd93b72d4dcb16c213d0d2a6b5b9a Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Thu, 1 Oct 2020 20:23:48 +1000
Subject: [PATCH 08/23] pgp: factor out rsa_pad

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 <d...@axtens.net>
---
 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 46a488131..5525aa194 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2504,6 +2504,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 5daa1e9d0..2408db499 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -24,6 +24,7 @@
 #include <grub/file.h>
 #include <grub/command.h>
 #include <grub/crypto.h>
+#include <grub/pkcs1_v15.h>
 #include <grub/i18n.h>
 #include <grub/gcrypt/gcrypt.h>
 #include <grub/pubkey.h>
@@ -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 000000000..dbacd563d
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/gcrypt/gcrypt.h>
+
+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 000000000..5c338c84a
--- /dev/null
+++ b/include/grub/pkcs1_v15.h
@@ -0,0 +1,27 @@
+/*
+ *  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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * 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)
+ */
+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);
+
-- 
2.31.1


++++++ 0009-crypto-move-storage-for-grub_crypto_pk_-to-crypto.c.patch ++++++
>From def9a985bdb1a12db49be42b748b646abc156411 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Fri, 2 Oct 2020 10:49:26 +1000
Subject: [PATCH 09/23] crypto: move storage for grub_crypto_pk_* to crypto.c

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 <d...@axtens.net>
---
 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 2408db499..355a43844 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 ca334d5a4..c578128a5 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.31.1


++++++ 0010-posix_wrap-tweaks-in-preparation-for-libtasn1.patch ++++++
>From fa3436ad10a63d5ad3d27cc330fb2594e699cc34 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Sat, 2 May 2020 00:27:57 +1000
Subject: [PATCH 10/23] posix_wrap: tweaks in preparation for libtasn1

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

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

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

Signed-off-by: Daniel Axtens <d...@axtens.net>
---
 grub-core/lib/posix_wrap/limits.h    | 1 +
 grub-core/lib/posix_wrap/stdlib.h    | 8 ++++++++
 grub-core/lib/posix_wrap/sys/types.h | 1 +
 3 files changed, 10 insertions(+)

diff --git a/grub-core/lib/posix_wrap/limits.h 
b/grub-core/lib/posix_wrap/limits.h
index 7217138ff..591dbf328 100644
--- a/grub-core/lib/posix_wrap/limits.h
+++ b/grub-core/lib/posix_wrap/limits.h
@@ -37,5 +37,6 @@
 #define LONG_MAX GRUB_LONG_MAX
 
 #define CHAR_BIT 8
+#define WORD_BIT 32
 
 #endif
diff --git a/grub-core/lib/posix_wrap/stdlib.h 
b/grub-core/lib/posix_wrap/stdlib.h
index 7a8d385e9..4634db09f 100644
--- a/grub-core/lib/posix_wrap/stdlib.h
+++ b/grub-core/lib/posix_wrap/stdlib.h
@@ -58,4 +58,12 @@ abs (int c)
   return (c >= 0) ? c : -c;
 }
 
+#define strtol grub_strtol
+
+/* for libgcrypt */
+#define HAVE_STRTOUL
+#define strtoul grub_strtoul
+
+#define strtoull grub_strtoull
+
 #endif
diff --git a/grub-core/lib/posix_wrap/sys/types.h 
b/grub-core/lib/posix_wrap/sys/types.h
index 854eb0122..f63412c8d 100644
--- a/grub-core/lib/posix_wrap/sys/types.h
+++ b/grub-core/lib/posix_wrap/sys/types.h
@@ -51,6 +51,7 @@ typedef grub_uint8_t byte;
 typedef grub_addr_t uintptr_t;
 
 #define SIZEOF_UNSIGNED_LONG GRUB_CPU_SIZEOF_LONG
+#define SIZEOF_UNSIGNED_LONG_INT GRUB_CPU_SIZEOF_LONG
 #define SIZEOF_UNSIGNED_INT 4
 #define SIZEOF_UNSIGNED_LONG_LONG 8
 #define SIZEOF_UNSIGNED_SHORT 2
-- 
2.31.1


++++++ 0011-libtasn1-import-libtasn1-4.18.0.patch ++++++
++++ 9045 lines (skipped)

++++++ 0012-libtasn1-disable-code-not-needed-in-grub.patch ++++++
>From 40099cf0d4d68e79db9e71d78070f37c73f998a0 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Fri, 1 May 2020 17:12:23 +1000
Subject: [PATCH 12/23] libtasn1: disable code not needed in grub

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

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

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

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

diff --git a/grub-core/lib/libtasn1/lib/coding.c 
b/grub-core/lib/libtasn1/lib/coding.c
index 671104f63..b3d826710 100644
--- a/grub-core/lib/libtasn1/lib/coding.c
+++ b/grub-core/lib/libtasn1/lib/coding.c
@@ -30,11 +30,11 @@
 #include "parser_aux.h"
 #include <gstr.h>
 #include "element.h"
-#include "minmax.h"
 #include <structure.h>
 
 #define MAX_TAG_LEN 16
 
+#if 0
 /******************************************************/
 /* Function : _asn1_error_description_value_not_found */
 /* Description: creates the ErrorDescription string   */
@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
   Estrcat (ErrorDescription, "' not found");
 
 }
+#endif
 
 /**
  * asn1_length_der:
@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned 
char *str,
   return ASN1_SUCCESS;
 }
 
+#if 0
 /******************************************************/
 /* Function : _asn1_time_der                          */
 /* Description: creates the DER coding for a TIME     */
@@ -278,7 +280,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned 
char *der,
 
   return ASN1_SUCCESS;
 }
-
+#endif
 
 /*
 void
@@ -519,6 +521,7 @@ asn1_bit_der (const unsigned char *str, int bit_len,
 }
 
 
+#if 0
 /******************************************************/
 /* Function : _asn1_complete_explicit_tag             */
 /* Description: add the length coding to the EXPLICIT */
@@ -595,6 +598,7 @@ _asn1_complete_explicit_tag (asn1_node node, unsigned char 
*der,
 
   return ASN1_SUCCESS;
 }
+#endif
 
 const tag_and_class_st _asn1_tags[] = {
   [ASN1_ETYPE_GENERALSTRING] =
@@ -647,6 +651,8 @@ const tag_and_class_st _asn1_tags[] = {
 
 unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
 
+
+#if 0
 /******************************************************/
 /* Function : _asn1_insert_tag_der                    */
 /* Description: creates the DER coding of tags of one */
@@ -1423,3 +1429,5 @@ error:
   asn1_delete_structure (&node);
   return err;
 }
+
+#endif
\ No newline at end of file
diff --git a/grub-core/lib/libtasn1/lib/decoding.c 
b/grub-core/lib/libtasn1/lib/decoding.c
index b1a35356f..b8130b956 100644
--- a/grub-core/lib/libtasn1/lib/decoding.c
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -1620,6 +1620,7 @@ asn1_der_decoding (asn1_node * element, const void *ider, 
int ider_len,
   return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription);
 }
 
+#if 0
 /**
  * asn1_der_decoding_element:
  * @structure: pointer to an ASN1 structure
@@ -1650,6 +1651,7 @@ asn1_der_decoding_element (asn1_node * structure, const 
char *elementName,
 {
   return asn1_der_decoding (structure, ider, len, errorDescription);
 }
+#endif
 
 /**
  * asn1_der_decoding_startEnd:
diff --git a/grub-core/lib/libtasn1/lib/element.c 
b/grub-core/lib/libtasn1/lib/element.c
index 86e64f2cf..8cd6b662c 100644
--- a/grub-core/lib/libtasn1/lib/element.c
+++ b/grub-core/lib/libtasn1/lib/element.c
@@ -191,7 +191,7 @@ _asn1_append_sequence_set (asn1_node node, struct 
node_tail_cache_st *pcache)
   return ASN1_SUCCESS;
 }
 
-
+#if 0
 /**
  * asn1_write_value:
  * @node_root: pointer to a structure
@@ -646,7 +646,7 @@ asn1_write_value (asn1_node node_root, const char *name,
 
   return ASN1_SUCCESS;
 }
-
+#endif
 
 #define PUT_VALUE( ptr, ptr_size, data, data_size) \
        *len = data_size; \
diff --git a/grub-core/lib/libtasn1/lib/errors.c 
b/grub-core/lib/libtasn1/lib/errors.c
index 4dadbd96d..41921d813 100644
--- a/grub-core/lib/libtasn1/lib/errors.c
+++ b/grub-core/lib/libtasn1/lib/errors.c
@@ -57,6 +57,8 @@ static const libtasn1_error_entry error_algorithms[] = {
   {0, 0}
 };
 
+
+#if 0
 /**
  * asn1_perror:
  * @error: is an error returned by a libtasn1 function.
@@ -73,6 +75,7 @@ asn1_perror (int error)
   const char *str = asn1_strerror (error);
   fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)");
 }
+#endif
 
 /**
  * asn1_strerror:
diff --git a/grub-core/lib/libtasn1/lib/structure.c 
b/grub-core/lib/libtasn1/lib/structure.c
index c0802202e..45435732c 100644
--- a/grub-core/lib/libtasn1/lib/structure.c
+++ b/grub-core/lib/libtasn1/lib/structure.c
@@ -76,7 +76,7 @@ _asn1_find_left (asn1_node_const node)
   return node->left;
 }
 
-
+#if 0
 int
 _asn1_create_static_structure (asn1_node_const pointer,
                               char *output_file_name, char *vector_name)
@@ -155,7 +155,7 @@ _asn1_create_static_structure (asn1_node_const pointer,
 
   return ASN1_SUCCESS;
 }
-
+#endif
 
 /**
  * asn1_array2tree:
@@ -721,7 +721,7 @@ asn1_create_element (asn1_node_const definitions, const 
char *source_name,
   return res;
 }
 
-
+#if 0
 /**
  * asn1_print_structure:
  * @out: pointer to the output file (e.g. stdout).
@@ -1062,7 +1062,7 @@ asn1_print_structure (FILE * out, asn1_node_const 
structure, const char *name,
        }
     }
 }
-
+#endif
 
 
 /**
@@ -1158,6 +1158,7 @@ asn1_find_structure_from_oid (asn1_node_const definitions,
   return NULL;                 /* ASN1_ELEMENT_NOT_FOUND; */
 }
 
+#if 0
 /**
  * asn1_copy_node:
  * @dst: Destination asn1 node.
@@ -1207,6 +1208,7 @@ asn1_copy_node (asn1_node dst, const char *dst_name,
 
   return result;
 }
+#endif
 
 /**
  * asn1_dup_node:
diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h
index fc695a28a..0c3a44881 100644
--- a/include/grub/libtasn1.h
+++ b/include/grub/libtasn1.h
@@ -314,6 +314,8 @@ extern "C"
 /*  Functions definitions          */
 /***********************************/
 
+/* These functions are not used in grub and should not be referenced. */
+# if 0
   extern ASN1_API int
     asn1_parser2tree (const char *file,
                      asn1_node * definitions, char *error_desc);
@@ -322,14 +324,17 @@ extern "C"
     asn1_parser2array (const char *inputFileName,
                       const char *outputFileName,
                       const char *vectorName, char *error_desc);
+# endif
 
   extern ASN1_API int
     asn1_array2tree (const asn1_static_node * array,
                     asn1_node * definitions, char *errorDescription);
 
+# if 0
   extern ASN1_API void
     asn1_print_structure (FILE * out, asn1_node_const structure,
                          const char *name, int mode);
+# endif
 
   extern ASN1_API int
     asn1_create_element (asn1_node_const definitions,
@@ -343,9 +348,11 @@ extern "C"
   extern ASN1_API int
     asn1_delete_element (asn1_node structure, const char *element_name);
 
+# if 0
   extern ASN1_API int
     asn1_write_value (asn1_node node_root, const char *name,
                      const void *ivalue, int len);
+# endif
 
   extern ASN1_API int
     asn1_read_value (asn1_node_const root, const char *name,
@@ -362,9 +369,11 @@ extern "C"
     asn1_number_of_elements (asn1_node_const element, const char *name,
                             int *num);
 
+# if 0
   extern ASN1_API int
     asn1_der_coding (asn1_node_const element, const char *name,
                     void *ider, int *len, char *ErrorDescription);
+# endif
 
   extern ASN1_API int
     asn1_der_decoding2 (asn1_node * element, const void *ider,
@@ -375,6 +384,7 @@ extern "C"
     asn1_der_decoding (asn1_node * element, const void *ider,
                       int ider_len, char *errorDescription);
 
+# if 0
 /* Do not use. Use asn1_der_decoding() instead. */
   extern ASN1_API int
     asn1_der_decoding_element (asn1_node * structure,
@@ -382,6 +392,7 @@ extern "C"
                               const void *ider, int len,
                               char *errorDescription)
     _ASN1_GCC_ATTR_DEPRECATED;
+# endif
 
   extern ASN1_API int
     asn1_der_decoding_startEnd (asn1_node element,
@@ -407,12 +418,16 @@ extern "C"
                                                            const char
                                                            *oidValue);
 
+# if 0
     __LIBTASN1_PURE__
     extern ASN1_API const char *asn1_check_version (const char *req_version);
+# endif
 
   __LIBTASN1_PURE__ extern ASN1_API const char *asn1_strerror (int error);
 
+# if 0
   extern ASN1_API void asn1_perror (int error);
+# endif
 
 # define ASN1_MAX_TAG_SIZE 4
 # define ASN1_MAX_LENGTH_SIZE 9
-- 
2.31.1


++++++ 0013-libtasn1-changes-for-grub-compatibility.patch ++++++
>From f05ba09c9adea447d3ca837c73498b9619306180 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Fri, 1 May 2020 20:44:29 +1000
Subject: [PATCH 13/23] libtasn1: changes for grub compatibility

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

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

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

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

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

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

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

Signed-off-by: Daniel Axtens <d...@axtens.net>

---

v2: Clean up strcat handling, thanks Stefan Berger.
---
 grub-core/lib/libtasn1/lib/decoding.c   | 11 +++++-----
 grub-core/lib/libtasn1/lib/element.c    |  3 ++-
 grub-core/lib/libtasn1/lib/gstr.c       |  4 ++--
 grub-core/lib/libtasn1/lib/int.h        |  4 ++--
 grub-core/lib/libtasn1/lib/parser_aux.c |  7 +++---
 include/grub/libtasn1.h                 | 29 +++++++------------------
 6 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/grub-core/lib/libtasn1/lib/decoding.c 
b/grub-core/lib/libtasn1/lib/decoding.c
index b8130b956..beeb6a176 100644
--- a/grub-core/lib/libtasn1/lib/decoding.c
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -32,7 +32,8 @@
 #include <element.h>
 #include <limits.h>
 #include <intprops.h>
-#include "c-ctype.h"
+
+#define c_isdigit grub_isdigit
 
 #ifdef DEBUG
 # define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
@@ -2016,8 +2017,8 @@ asn1_expand_octet_string (asn1_node_const definitions, 
asn1_node * element,
          (p2->type & CONST_ASSIGN))
        {
          strcpy (name, definitions->name);
-         strcat (name, ".");
-         strcat (name, p2->name);
+         _asn1_strcat (name, ".");
+         _asn1_strcat (name, p2->name);
 
          len = sizeof (value);
          result = asn1_read_value (definitions, name, value, &len);
@@ -2034,8 +2035,8 @@ asn1_expand_octet_string (asn1_node_const definitions, 
asn1_node * element,
              if (p2)
                {
                  strcpy (name, definitions->name);
-                 strcat (name, ".");
-                 strcat (name, p2->name);
+                 _asn1_strcat (name, ".");
+                 _asn1_strcat (name, p2->name);
 
                  result = asn1_create_element (definitions, name, &aux);
                  if (result == ASN1_SUCCESS)
diff --git a/grub-core/lib/libtasn1/lib/element.c 
b/grub-core/lib/libtasn1/lib/element.c
index 8cd6b662c..150b9b377 100644
--- a/grub-core/lib/libtasn1/lib/element.c
+++ b/grub-core/lib/libtasn1/lib/element.c
@@ -30,9 +30,10 @@
 #include "parser_aux.h"
 #include <gstr.h>
 #include "structure.h"
-#include "c-ctype.h"
 #include "element.h"
 
+#define c_isdigit grub_isdigit
+
 void
 _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size)
 {
diff --git a/grub-core/lib/libtasn1/lib/gstr.c 
b/grub-core/lib/libtasn1/lib/gstr.c
index 1475ed51b..b729089db 100644
--- a/grub-core/lib/libtasn1/lib/gstr.c
+++ b/grub-core/lib/libtasn1/lib/gstr.c
@@ -36,13 +36,13 @@ _asn1_str_cat (char *dest, size_t dest_tot_size, const char 
*src)
 
   if (dest_tot_size - dest_size > str_size)
     {
-      strcat (dest, src);
+      _asn1_strcat (dest, src);
     }
   else
     {
       if (dest_tot_size > dest_size)
        {
-         strncat (dest, src, (dest_tot_size - dest_size) - 1);
+         memcpy (dest + dest_size, src, (dest_tot_size - dest_size) - 1);
          dest[dest_tot_size - 1] = 0;
        }
     }
diff --git a/grub-core/lib/libtasn1/lib/int.h b/grub-core/lib/libtasn1/lib/int.h
index 404cd1562..edfe84a0e 100644
--- a/grub-core/lib/libtasn1/lib/int.h
+++ b/grub-core/lib/libtasn1/lib/int.h
@@ -35,7 +35,7 @@
 #  include <sys/types.h>
 # endif
 
-# include <libtasn1.h>
+# include "grub/libtasn1.h"
 
 # define ASN1_SMALL_VALUE_SIZE 16
 
@@ -115,7 +115,7 @@ extern const tag_and_class_st _asn1_tags[];
 # define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b)
 # define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b)
 # define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b)
-# define _asn1_strcat(a,b) strcat((char *)a, (const char *)b)
+# define _asn1_strcat(a,b) memcpy((char *)a + strlen((const char *)a), (const 
char *)b, strlen((const char *)b) + 1)
 
 # if SIZEOF_UNSIGNED_LONG_INT == 8
 #  define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b)
diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c 
b/grub-core/lib/libtasn1/lib/parser_aux.c
index c99c5a4cb..a933f03ed 100644
--- a/grub-core/lib/libtasn1/lib/parser_aux.c
+++ b/grub-core/lib/libtasn1/lib/parser_aux.c
@@ -26,7 +26,8 @@
 #include "gstr.h"
 #include "structure.h"
 #include "element.h"
-#include "c-ctype.h"
+
+#define c_isdigit grub_isdigit
 
 char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1];  /* identifier name not 
found */
 
@@ -40,7 +41,7 @@ char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* 
identifier name not fou
 #ifdef __clang__
 __attribute__((no_sanitize ("integer")))
 #endif
-     _GL_ATTRIBUTE_PURE static unsigned int _asn1_hash_name (const char *x)
+     __attribute__((__pure__)) static unsigned int _asn1_hash_name (const char 
*x)
 {
   const unsigned char *s = (unsigned char *) x;
   unsigned h = 0;
@@ -632,7 +633,7 @@ _asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE])
   count = 0;
   do
     {
-      d = val / 10;
+      d = grub_divmod64(val, 10, NULL);
       r = val - d * 10;
       temp[start + count] = '0' + (char) r;
       count++;
diff --git a/include/grub/libtasn1.h b/include/grub/libtasn1.h
index 0c3a44881..2ea058a3b 100644
--- a/include/grub/libtasn1.h
+++ b/include/grub/libtasn1.h
@@ -34,29 +34,16 @@
 #ifndef LIBTASN1_H
 # define LIBTASN1_H
 
-# ifndef ASN1_API
-#  if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY
-#   define ASN1_API __attribute__((__visibility__("default")))
-#  elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC
-#   define ASN1_API __declspec(dllexport)
-#  elif defined _MSC_VER && ! defined ASN1_STATIC
-#   define ASN1_API __declspec(dllimport)
-#  else
-#   define ASN1_API
-#  endif
-# endif
+/* grub: ASN1_API is not used */
+# define ASN1_API
+
+/* grub: all our supported compilers support these attributes */
+# define __LIBTASN1_CONST__  __attribute__((const))
+# define __LIBTASN1_PURE__  __attribute__((pure))
 
-# ifdef __GNUC__
-#  define __LIBTASN1_CONST__  __attribute__((const))
-#  define __LIBTASN1_PURE__  __attribute__((pure))
-# else
-#  define __LIBTASN1_CONST__
-#  define __LIBTASN1_PURE__
-# endif
 
-# include <sys/types.h>
-# include <time.h>
-# include <stdio.h>            /* for FILE* */
+# include <grub/types.h>
+# include <grub/time.h>
 
 # ifdef __cplusplus
 extern "C"
-- 
2.31.1


++++++ 0014-libtasn1-compile-into-asn1-module.patch ++++++
>From f3b818444fe8628d581f5efe23d55554f23718c8 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Fri, 5 Jun 2020 17:47:25 +1000
Subject: [PATCH 14/23] libtasn1: compile into asn1 module

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

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

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 5525aa194..f0df8ed94 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2575,3 +2575,18 @@ module = {
   name = cmdline;
   common = lib/cmdline.c;
 };
+
+module = {
+  name = asn1;
+  common = lib/libtasn1/lib/decoding.c;
+  common = lib/libtasn1/lib/coding.c;
+  common = lib/libtasn1/lib/element.c;
+  common = lib/libtasn1/lib/structure.c;
+  common = lib/libtasn1/lib/parser_aux.c;
+  common = lib/libtasn1/lib/gstr.c;
+  common = lib/libtasn1/lib/errors.c;
+  common = lib/libtasn1_wrap/wrap.c;
+  cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
+  // -Wno-type-limits comes from libtasn1's configure.ac
+  cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) 
-I$(srcdir)/lib/libtasn1/lib -Wno-type-limits';
+};
diff --git a/grub-core/lib/libtasn1_wrap/wrap.c 
b/grub-core/lib/libtasn1_wrap/wrap.c
new file mode 100644
index 000000000..622ba942e
--- /dev/null
+++ b/grub-core/lib/libtasn1_wrap/wrap.c
@@ -0,0 +1,26 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020 IBM Corporation
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+
+/*
+ * libtasn1 is provided under LGPL2.1+, which is compatible
+ * with GPL3+. As Grub as a whole is under GPL3+, this module
+ * is therefore under GPL3+ also.
+ */
+GRUB_MOD_LICENSE ("GPLv3+");
-- 
2.31.1


++++++ 0015-test_asn1-test-module-for-libtasn1.patch ++++++
++++ 1448 lines (skipped)

++++++ 0016-grub-install-support-embedding-x509-certificates.patch ++++++
>From a0e17ba00ac128759d40e2bfc751716f45542ac0 Mon Sep 17 00:00:00 2001
From: Alastair D'Silva <alast...@d-silva.org>
Date: Mon, 6 Jul 2020 13:33:04 +1000
Subject: [PATCH 16/23] grub-install: support embedding x509 certificates

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 <alast...@d-silva.org>
Signed-off-by: Daniel Axtens <d...@axtens.net>
---
 grub-core/commands/pgp.c    |  2 +-
 include/grub/kernel.h       |  3 ++-
 include/grub/util/install.h |  7 +++++--
 util/grub-install-common.c  | 22 +++++++++++++++++++-
 util/grub-mkimage.c         | 15 ++++++++++++--
 util/mkimage.c              | 41 ++++++++++++++++++++++++++++++++++---
 6 files changed, 80 insertions(+), 10 deletions(-)

diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index 355a43844..b81ac0ae4 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 abbca5ea3..d3aafc884 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -28,7 +28,8 @@ enum
   OBJ_TYPE_MEMDISK,
   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
 };
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 0b2e8a06d..c241a2a40 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -67,6 +67,8 @@
       N_("SBAT metadata"), 0 },                                                
\
   { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, \
       N_("disable shim_lock verifier"), 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},                                                                 \
@@ -189,8 +191,9 @@ void
 grub_install_generate_image (const char *dir, const char *prefix,
                             FILE *out,
                             const char *outname, char *mods[],
-                            char *memdisk_path, char **pubkey_paths,
-                            size_t npubkeys,
+                            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 954df20eb..44296afa0 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -460,6 +460,8 @@ static char **pubkeys;
 static size_t npubkeys;
 static char *sbat;
 static int disable_shim_lock;
+static char **x509keys;
+static size_t nx509keys;
 static grub_compression_t compression;
 static size_t appsig_size;
 
@@ -501,6 +503,12 @@ grub_install_parse (int key, char *arg)
     case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
       disable_shim_lock = 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++;
@@ -627,6 +635,9 @@ grub_install_make_image_wrap_file (const char *dir, const 
char *prefix,
   for (pk = pubkeys; pk < pubkeys + npubkeys; pk++)
     slen += 20 + grub_strlen (*pk);
 
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
+    slen += 10 + grub_strlen (*pk);
+
   for (md = modules.entries; *md; md++)
     {
       slen += 10 + grub_strlen (*md);
@@ -655,6 +666,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, "--x509 '");
+      p = grub_stpcpy (p, *pk);
+      *p++ = '\'';
+      *p++ = ' ';
+    }
+
   for (md = modules.entries; *md; md++)
     {
       *p++ = '\'';
@@ -683,7 +702,8 @@ 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,
                               disable_shim_lock);
   while (dc--)
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index d01eaeb84..7d61ef3ea 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -75,7 +75,8 @@ static struct argp_option options[] = {
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
   {"config",   'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0},
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
-  {"pubkey",   'k', N_("FILE"), 0, N_("embed FILE as public key for signature 
checking"), 0},
+  {"pubkey",   'k', N_("FILE"), 0, N_("embed FILE as public key for PGP 
signature checking"), 0},
+  {"x509",     'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for 
appended signature checking"), 0},
   /* TRANSLATORS: NOTE is a name of segment.  */
   {"note",   'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0},
   {"output",  'o', N_("FILE"), 0, N_("output a generated image to FILE 
[default=stdout]"), 0},
@@ -124,6 +125,8 @@ struct arguments
   char *dtb;
   char **pubkeys;
   size_t npubkeys;
+  char **x509keys;
+  size_t nx509keys;
   char *font;
   char *config;
   char *sbat;
@@ -206,6 +209,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg);
       break;
 
+    case 'x':
+      arguments->x509keys = xrealloc (arguments->x509keys,
+                                     sizeof (arguments->x509keys[0])
+                                     * (arguments->nx509keys + 1));
+      arguments->x509keys[arguments->nx509keys++] = xstrdup (arg);
+      break;
+
     case 'c':
       if (arguments->config)
        free (arguments->config);
@@ -332,7 +342,8 @@ main (int argc, char *argv[])
   grub_install_generate_image (arguments.dir, arguments.prefix, fp,
                               arguments.output, arguments.modules,
                               arguments.memdisk, arguments.pubkeys,
-                              arguments.npubkeys, arguments.config,
+                              arguments.npubkeys, arguments.x509keys,
+                              arguments.nx509keys, arguments.config,
                               arguments.image_target, arguments.note,
                               arguments.appsig_size,
                               arguments.comp, arguments.dtb,
diff --git a/util/mkimage.c b/util/mkimage.c
index d2cb33883..5a8021a21 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -866,8 +866,10 @@ init_pe_section(const struct 
grub_install_image_target_desc *image_target,
 void
 grub_install_generate_image (const char *dir, const char *prefix,
                             FILE *out, const char *outname, char *mods[],
-                            char *memdisk_path, char **pubkey_paths,
-                            size_t npubkeys, char *config_path,
+                            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, grub_compression_t 
comp,
                             const char *dtb_path, const char *sbat_path, 
@@ -913,6 +915,19 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
       }
   }
 
+  {
+    size_t i;
+    for (i = 0; i < nx509keys; i++)
+      {
+       size_t curs;
+       curs = ALIGN_ADDR (grub_util_get_image_size (x509key_paths[i]));
+       grub_util_info ("the size of x509 public key %u is 0x%"
+                       GRUB_HOST_PRIxLONG_LONG,
+                       (unsigned) i, (unsigned long long) curs);
+       total_module_size += curs + sizeof (struct grub_module_header);
+      }
+  }
+
   if (memdisk_path)
     {
       memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
@@ -1034,7 +1049,7 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
        curs = grub_util_get_image_size (pubkey_paths[i]);
 
        header = (struct grub_module_header *) (kernel_img + offset);
-       header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
+       header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY);
        header->size = grub_host_to_target32 (curs + sizeof (*header));
        offset += sizeof (*header);
 
@@ -1043,6 +1058,26 @@ grub_install_generate_image (const char *dir, const char 
*prefix,
       }
   }
 
+  {
+    size_t i;
+    for (i = 0; i < nx509keys; i++)
+      {
+       size_t curs;
+       struct grub_module_header *header;
+
+       curs = grub_util_get_image_size (x509key_paths[i]);
+
+       header = (struct grub_module_header *) (kernel_img + offset);
+       header->type = grub_host_to_target32 (OBJ_TYPE_X509_PUBKEY);
+       header->size = grub_host_to_target32 (curs + sizeof (*header));
+       offset += sizeof (*header);
+
+       grub_util_load_image (x509key_paths[i], kernel_img + offset);
+       offset += ALIGN_ADDR (curs);
+      }
+  }
+
+
   if (memdisk_path)
     {
       struct grub_module_header *header;
-- 
2.31.1


++++++ 0017-appended-signatures-import-GNUTLS-s-ASN.1-descriptio.patch ++++++
++++ 644 lines (skipped)

++++++ 0018-appended-signatures-parse-PKCS-7-signedData-and-X.50.patch ++++++
++++ 1892 lines (skipped)

++++++ 0019-appended-signatures-support-verifying-appended-signa.patch ++++++
++++ 765 lines (skipped)

++++++ 0020-appended-signatures-verification-tests.patch ++++++
++++ 1322 lines (skipped)

++++++ 0021-appended-signatures-documentation.patch ++++++
>From 4edb825a012e9e7b9ad08aa693cfdebf42ae40e6 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Thu, 1 Oct 2020 13:02:09 +1000
Subject: [PATCH 21/23] appended signatures: documentation

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 <d...@axtens.net>

---

v2: fix a grammar issue, thanks Stefan Berger.
---
 docs/grub.texi | 193 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 176 insertions(+), 17 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index dc1c58304..988ef8ddc 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3209,6 +3209,7 @@ These variables have special meaning to GRUB.
 
 @menu
 * biosnum::
+* check_appended_signatures::
 * check_signatures::
 * chosen::
 * cmdpath::
@@ -3268,11 +3269,18 @@ 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
@@ -3989,6 +3997,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
 * eval::                        Evaluate agruments as GRUB commands
@@ -4005,6 +4014,7 @@ you forget a command, you can run the command 
@command{help}
 * keystatus::                   Check key modifier status
 * linux::                       Load a Linux kernel
 * linux16::                     Load a Linux kernel (16-bit mode)
+* 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
@@ -4042,8 +4052,10 @@ you forget a command, you can run the command 
@command{help}
 * test::                        Check file types and compare values
 * 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
 @comment * xen_*::              Xen boot commands for AArch64
@@ -4371,9 +4383,28 @@ 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
 @subsection drivemap
 
@@ -4631,6 +4662,21 @@ This command is only available on x86 systems.
 @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 list_env
 @subsection list_env
 
@@ -4650,7 +4696,7 @@ The output is in GPG's v4 key fingerprint format (i.e., 
the output of
 @code{gpg --fingerprint}).  The least significant four bytes (last
 eight hexadecimal digits) can be used as an argument to
 @command{distrust} (@pxref{distrust}).
-@xref{Using digital signatures}, for more information about uses for
+@xref{Using GPG-style digital signatures}, for more information about uses for
 these keys.
 @end deffn
 
@@ -4685,8 +4731,12 @@ When used with care, @option{--skip-sig} and the 
whitelist enable an
 administrator to configure a system to boot only signed
 configurations, but to allow the user to select from among multiple
 configurations, and to enable ``one-shot'' boot attempts and
-``savedefault'' behavior.  @xref{Using digital signatures}, for more
+``savedefault'' behavior.  @xref{Using GPG-style digital signatures}, for more
 information.
+
+Extra care should be taken when combining this command with appended signatures
+(@pxref{Using appended signatures}), as this file is not validated by an
+appended signature and could set @code{check_appended_signatures=no}.
 @end deffn
 
 
@@ -4982,7 +5032,7 @@ read.  It is possible to modify a digitally signed 
environment block
 file from within GRUB using this command, such that its signature will
 no longer be valid on subsequent boots.  Care should be taken in such
 advanced configurations to avoid rendering the system
-unbootable. @xref{Using digital signatures}, for more information.
+unbootable. @xref{Using GPG-style digital signatures}, for more information.
 @end deffn
 
 
@@ -5382,11 +5432,31 @@ signatures when environment variable 
@code{check_signatures} is set to
 must itself be properly signed.  The @option{--skip-sig} option can be
 used to disable signature-checking when reading @var{pubkey_file}
 itself. It is expected that @option{--skip-sig} is useful for testing
-and manual booting. @xref{Using digital signatures}, for more
+and manual booting. @xref{Using GPG-style digital signatures}, for more
 information.
 @end deffn
 
 
+@node trust_certificate
+@subsection trust_certificate
+
+@deffn Command trust_certificate x509_certificate
+Read a DER-formatted x509 certificate from the file @var{x509_certificate}
+and add it to GRUB's internal list of trusted x509 certificates. These
+certificates are used to validate appended signatures when the environment
+variable @code{check_appended_signatures} is set to @code{enforce}.
+
+Note that if @code{check_appended_signatures} is set to @code{enforce}
+when @command{trust_certificate} is executed, then @var{x509_certificate}
+must itself bear an appended signature. (It is not sufficient that
+@var{x509_certificate} be signed by a trusted certificate according to the
+x509 rules: grub does not include support for validating signatures within x509
+certificates themselves.)
+
+See @xref{Using appended signatures} for more information.
+@end deffn
+
+
 @node unset
 @subsection unset
 
@@ -5405,6 +5475,18 @@ only on PC BIOS platforms.
 @end deffn
 @end ignore
 
+@node verify_appended
+@subsection verify_appended
+
+@deffn Command verify_appended file
+Verifies an appended signature on @var{file} against the trusted certificates
+known to GRUB (See @pxref{list_certificates}, @pxref{trust_certificate}, and
+@pxref{distrust_certificate}).
+
+Exit code @code{$?} is set to 0 if the signature validates
+successfully.  If validation fails, it is set to a non-zero value.
+See @xref{Using appended signatures}, for more information.
+@end deffn
 
 @node verify_detached
 @subsection verify_detached
@@ -5423,7 +5505,7 @@ tried.
 
 Exit code @code{$?} is set to 0 if the signature validates
 successfully.  If validation fails, it is set to a non-zero value.
-@xref{Using digital signatures}, for more information.
+@xref{Using GPG-style digital signatures}, for more information.
 @end deffn
 
 @node videoinfo
@@ -5808,13 +5890,14 @@ environment variables and commands are listed in the 
same order.
 @chapter Security
 
 @menu
-* Authentication and authorisation:: Users and access control
-* Using digital signatures::         Booting digitally signed code
-* UEFI secure boot and shim::        Booting digitally signed PE files
-* Secure Boot Advanced Targeting::   Embedded information for generation 
number based revocation
-* Measured Boot::                    Measuring boot components
-* Lockdown::                         Lockdown when booting on a secure setup
-* Signing GRUB itself::              Ensuring the integrity of the GRUB core 
image
+* Authentication and authorisation::   Users and access control
+* Using GPG-style digital signatures:: Booting digitally signed code
+* Using appended signatures::          An alternative approach to booting 
digitally signed code
+* UEFI secure boot and shim::          Booting digitally signed PE files
+* Secure Boot Advanced Targeting::     Embedded information for generation 
number based revocation
+* Measured Boot::                      Measuring boot components
+* Lockdown::                           Lockdown when booting on a secure setup
+* Signing GRUB itself::                Ensuring the integrity of the GRUB core 
image
 @end menu
 
 @node Authentication and authorisation
@@ -5888,8 +5971,8 @@ generating configuration files with authentication.  You 
can use
 adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2}
 commands.
 
-@node Using digital signatures
-@section Using digital signatures in GRUB
+@node Using GPG-style digital signatures
+@section Using GPG-style digital signatures in GRUB
 
 GRUB's @file{core.img} can optionally provide enforcement that all files
 subsequently read from disk are covered by a valid digital signature.
@@ -5972,6 +6055,82 @@ or BIOS) configuration to cause the machine to boot from 
a different
 (attacker-controlled) device.  GRUB is at best only one link in a
 secure boot chain.
 
+@node Using appended signatures
+@section Using appended signatures in GRUB
+
+GRUB supports verifying Linux-style 'appended signatures' for secure boot.
+Appended signatures are PKCS#7 messages containing a signature over the
+contents of a file, plus some metadata, appended to the end of a file. A file
+with an appended signature ends with the magic string:
+
+@example
+~Module signature appended~\n
+@end example
+
+where @code{\n} represents the carriage-return character, @code{0x0a}.
+
+To enable appended signature verification, load the appendedsig module and an
+x509 certificate for verification. Building the appendedsig module into the
+core grub image is recommended.
+
+Certificates can be managed at boot time using the @pxref{trust_certificate},
+@pxref{distrust_certificate} and @pxref{list_certificates} commands.
+Certificates can also be built in to the core image using the @code{--x509}
+parameter to @command{grub-install} or @command{grub-mkimage}.
+
+A file can be explictly verified using the @pxref{verify_appended} command.
+
+Only signatures made with the SHA-256 or SHA-512 hash algorithm are supported,
+and only RSA signatures are supported.
+
+A file can be signed with the @command{sign-file} utility supplied with the
+Linux kernel source. For example, if you have @code{signing.key} as the private
+key and @code{certificate.der} as the x509 certificate containing the public 
key:
+
+@example
+sign-file SHA256 signing.key certificate.der vmlinux vmlinux.signed
+@end example
+
+Enforcement of signature verification is controlled by the
+@code{check_appended_signatures} variable. Verification will only take place
+when files are loaded if the variable is set to @code{enforce}. If a
+certificate is built into the grub core image with the @code{--x509} parameter,
+the variable will be automatically set to @code{enforce} when the appendedsig
+module is loaded.
+
+Unlike GPG-style signatures, not all files loaded by GRUB are required to be
+signed. Once verification is turned on, the following file types must carry
+appended signatures:
+
+@enumerate
+@item Linux, Multiboot, BSD, XNU and Plan9 kernels
+@item Grub modules, except those built in to the core image
+@item Any new certificate files to be trusted
+@end enumerate
+
+ACPI tables and Device Tree images will not be checked for appended signatures
+but must be verified by another mechanism such as GPG-style signatures before
+they will be loaded.
+
+No attempt is made to validate any other file type. In particular,
+chain-loaded binaries are not verified - if your platform supports
+chain-loading and this cannot be disabled, consider an alternative secure
+boot mechanism.
+
+As with GPG-style appended signatures, signature checking does @strong{not}
+stop an attacker with console access from dropping manually to the GRUB
+console and executing:
+
+@example
+set check_appended_signatures=no
+@end example
+
+Refer to the section on password-protecting GRUB (@pxref{Authentication
+and authorisation}) for more information on preventing this.
+
+Additionally, special care must be taken around the @command{loadenv} command,
+which can be used to turn off @code{check_appended_signature}.
+
 @node UEFI secure boot and shim
 @section UEFI secure boot and shim support
 
-- 
2.31.1


++++++ 0022-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch ++++++
>From 806bb18c3493537530b6b0387143752478078f5b Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Mon, 28 Sep 2020 11:11:17 +1000
Subject: [PATCH 22/23] ieee1275: enter lockdown based on /ibm,secure-boot

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

Signed-off-by: Daniel Axtens <d...@axtens.net>
---
 docs/grub.texi                |  4 ++--
 grub-core/Makefile.core.def    |  1 +
 grub-core/kern/ieee1275/init.c | 27 +++++++++++++++++++++++++++
 include/grub/lockdown.h        |  3 ++-
 4 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 988ef8ddc..f4794fdda 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6208,8 +6208,8 @@ Measured boot is currently only supported on EFI 
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
-be restricted and some operations/commands cannot be executed.
+if UEFI or Power secure boot is enabled. On a locked down configuration, the
+GRUB will be restricted and some operations/commands cannot be executed.
 
 The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down.
 Otherwise it does not exit.
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 88eedd16d..49bdb63b6 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -317,6 +317,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 446201165..d77d89604 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -44,6 +44,7 @@
 #ifdef __sparc__
 #include <grub/machine/kernel.h>
 #endif
+#include <grub/lockdown.h>
 
 /* The maximum heap size we're going to claim. Not used by sparc.
    We allocate 1/4 of the available memory under 4G, up to this limit. */
@@ -440,6 +441,30 @@ grub_parse_cmdline (void)
     }
 }
 
+static void
+grub_get_ieee1275_secure_boot (void)
+{
+  grub_ieee1275_phandle_t root;
+  int rc;
+  grub_uint32_t is_sb;
+
+  grub_ieee1275_finddevice ("/", &root);
+
+  rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb,
+                                           sizeof (is_sb), 0);
+
+  /* ibm,secure-boot:
+   * 0 - disabled
+   * 1 - audit
+   * 2 - enforce
+   * 3 - enforce + OS-specific behaviour
+   *
+   * We only support enforce.
+   */
+  if (rc >= 0 && is_sb >= 2)
+    grub_lockdown ();
+}
+
 grub_addr_t grub_modbase;
 
 void
@@ -465,6 +490,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_ENABLED        1
 
-#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.31.1


++++++ 0023-x509-allow-Digitial-Signature-plus-other-Key-Usages.patch ++++++
>From 5a690183091c2c161481123b17e1925148e516e4 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <d...@axtens.net>
Date: Tue, 30 Nov 2021 15:00:57 +1100
Subject: [PATCH 23/23] x509: allow Digitial Signature plus other Key Usages

Currently the x509 certificate parser for appended signature
verification requires that the certificate have the Digitial Signature
key usage and _only_ the Digitial Signature use. This is overly strict
and becomes policy enforcement rather than a security property.

Require that the Digitial Signature usage is present, but do not
require that it is the only usage present.

Reported-by: Michal Suchanek <msucha...@suse.com>
Signed-off-by: Daniel Axtens <d...@axtens.net>
---
 grub-core/commands/appendedsig/x509.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/grub-core/commands/appendedsig/x509.c 
b/grub-core/commands/appendedsig/x509.c
index 70480aa73..6ae985b30 100644
--- a/grub-core/commands/appendedsig/x509.c
+++ b/grub-core/commands/appendedsig/x509.c
@@ -547,7 +547,7 @@ cleanup:
 
 /*
  * Verify the Key Usage extension.
- * We only permit the Digital signature usage.
+ * We require the Digital signature usage.
  */
 static grub_err_t
 verify_key_usage (grub_uint8_t *value, int value_size)
@@ -586,10 +586,10 @@ verify_key_usage (grub_uint8_t *value, int value_size)
       goto cleanup;
     }
 
-  if (usage != digitalSignatureUsage)
+  if (!(usage & digitalSignatureUsage))
     {
       err =
-       grub_error (GRUB_ERR_BAD_FILE_TYPE, "Unexpected Key Usage value: %x",
+       grub_error (GRUB_ERR_BAD_FILE_TYPE, "Key Usage (0x%x) missing Digital 
Signature usage",
                    usage);
       goto cleanup;
     }
-- 
2.31.1



++++++ grub2-systemd-sleep.sh ++++++
--- /var/tmp/diff_new_pack.d9XIXO/_old  2022-01-14 23:13:59.902661099 +0100
+++ /var/tmp/diff_new_pack.d9XIXO/_new  2022-01-14 23:13:59.902661099 +0100
@@ -10,6 +10,7 @@
 GRUB_CONF="/boot/grub2/grub.cfg"
 GRUB_SETUP=
 BLKID="/usr/sbin/blkid"
+LSBLK="/usr/bin/lsblk"
 ARCH=`uname -m`
 VMLINUZ="vmlinuz"
 case $ARCH in
@@ -31,6 +32,15 @@
        [ -r "${GRUB_CONF}" ] || error_quit "ERROR: cannot find or read 
${GRUB_CONF}"
 }
 
+compare-fsuuid()
+{
+       local uuids=($($LSBLK -n -o UUID $1 $2 2>/dev/null))
+       if [ ${#uuids[@]} -eq 2 ] && [ "${uuids[0]}" = "${uuids[1]}" ]; then
+               return 0
+       fi
+       return 1
+}
+
 #####################################################################
 # gets a list of available kernels from /boot/grub2/grub.cfg
 # kernels are in the array $KERNELS
@@ -87,9 +97,13 @@
                fi
 
                if [ "$(stat -Lc '%t:%T' $ROOT || true)" != "$(stat -Lc '%t:%T' 
$ROOTDEV || true)" ]; then
-                       echo "  Skipping ${MENU_ENTRIES[$I]}, because its root= 
parameter ($ROOT)" >&2
-                       echo "    does not match the current root device 
($ROOTDEV)." >&2
-                       continue
+                       if compare-fsuuid "$ROOT" "$ROOTDEV" ; then
+                               echo "  $ROOTDEV and $ROOT have the same 
filesystem UUID"
+                       else
+                               echo "  Skipping ${MENU_ENTRIES[$I]}, because 
its root= parameter ($ROOT)" >&2
+                               echo "    does not match the current root 
device ($ROOTDEV)." >&2
+                               continue
+                       fi
                fi
 
                DUMMY=($LINE) # kernel (hd0,1)/boot/vmlinuz-ABC root=/dev/hda2

Reply via email to