Re: [PATCH] arm/efi: fix ram base detection

2021-03-30 Thread Vincent Stehlé via Grub-devel
On Mon, Mar 22, 2021 at 06:28:51PM +, Leif Lindholm wrote:
..
> > > diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
> > > index 0cdb063bb..abf8772bc 100644
> > > --- a/grub-core/kern/efi/mm.c
> > > +++ b/grub-core/kern/efi/mm.c
> > > @@ -677,7 +677,8 @@ grub_efi_get_ram_base(grub_addr_t *base_addr)
> > >for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS;
> > > (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size);
> > > desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
> > > -if (desc->attribute & GRUB_EFI_MEMORY_WB)
> > > +if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY &&
> > > +desc->attribute & GRUB_EFI_MEMORY_WB)
> 
> Can we safely assume we don't also need to check against
> GRUB_EFI_PERSISTENT_MEMORY? If so, this is fine.

Hi Leif,

Thanks for the review.

This is a good question about persistent memory; I don't know if we should
check it or not.

I am "fighting" with qemu to add an nvdimm above or below the first normal
memory region to see how this behaves. I will let you know when I have
succeeded.

Best regards,
Vincent.

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


RE: Dell BIOS issue reading Disk Extended data

2021-03-30 Thread K, Narendra
Internal Use - Confidential

> -Original Message-
> From: Guilherme Piccoli 
> Sent: Friday, March 12, 2021 9:14 PM
> To: Limonciello, Mario; K, Narendra
> Cc: Barabash, Alexander; Engel, Amit; Guilherme G. Piccoli;
> hal...@canonical.com; Jay Vosburgh; Dan Streetman; Gavin Guo;
> x...@kernel.org; grub-devel@gnu.org
> Subject: Re: Dell BIOS issue reading Disk Extended data
> 
> 
> [EXTERNAL EMAIL]
> 
> On Fri, Jan 22, 2021 at 3:41 PM Limonciello, Mario
>  wrote:
> >
> > >
> > > Hello Dell folks, I'm Guilherme Piccoli from Canonical - first of
> > > all, apologies for the out-of-nowhere communication. We've been
> > > investigating an issue that seems to date long time ago, and
> > > eventually we could narrow it to what appears to be a Dell BIOS bug.
> > > Notice I'm also looping a kernel x86 ML and grub-devel, just for the
> > > purpose of archiving such discussion in public lists, to help others
> > > that may find such an issue in the future.
> > >
> > > Since I don't have contacts of Dell representatives, I've just
> > > raised a list of people from Dell contributing to kernel in the last
> > > 2 years - maybe one of you could point me towards the path of a
> > > proper contact/channel to discuss such an issue. If not, I'm sorry for the
> noise.
> > > Let me detail the problem we're observing - notice all of this is
> > > about legacy BIOS mode, not UEFI.
> >
> > Most of the guys you CC'ed from Dell work on client related things,
> > not servers.  So I'll move some of the client guys off of this thread into 
> > BCC.
> > @K, Narendra can you please raise this with the appropriate team?
> >
> 
> Thanks Mario and K, Narendra - do we have any news about that?
> Cheers,

Hi Guilherme,

Sorry for the delay in responding.  

I checked with the team about the findings shared in this thread. Please find 
the details -

The behavior seems to be working as designed. Legacy BIOS Option ROM implements 
logical block addressing support only up to 2TB. 
The option ROM will respond with 2TB as the size when queried by INT13h 
function 48h. For booting from volumes > 2TB, UEFI is needed.

With regards,
Narendra K
___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


Re: multiboot2 and module2 boot issues via GRUB2

2021-03-30 Thread Andrew Cooper via Grub-devel
On 30/03/2021 19:28, Roman Shaposhnik wrote:
> Hi!
>
> seems like I've run into an issue with multiboot2 and module2
> commands that I can't quite explain. Since it may be something
> super simply and silly -- I wanted to reach out here before I do
> a GRUB/Xen/LK source deepdive.
>
> So here's the deal: whenever I boot straight up Linux kernel
> I can do the following sequence of commands:
>    linux /kernel
>    initrd foo.cpio.gz bar.cpio.gz
> and have linux kernel effectively stack content of bar.cpio.gz
> on top of foo.cpio.gz and present a unified initramfs that way.
>
> I'm trying to replicate it with Xen, but:
>      multiboot2 /boot/xen.gz
>      module2 /kernel
>      module2 foo.cpio.gz
>      module2 bar.cpio.gz
> only seems to be picking up foo.cpio.gz
>
> Has anyone run into this issue before?

I can explain why that happens.  Not sure if it counts as a feature, bug
or mis-expectation, but CC'ing grub-devel for their input.

The initrd command is presumably concatenating those two files together
in memory, and presenting Linux a single initrd pointer.

For the module2 example, you're putting 3 distinct files in memory, and
giving Xen a list 3 modules.

Xen is capable of taking various things via modules, such as an
XSM/Flask policy, or microcode, so has logic to identify these if
present and separate them from "other stuff".  However, there is a
hardcoded expectation that the first module is the dom0 kernel, and the
next unrecognised module, if present, is *the* initrd.

I expect that Xen isn't handing bar.cpio.gz on to dom0, but I'm not sure
whether passing two distinct initrd-like-things to Linux is even possible.

What you presumably want is some `initrd` side effect in Grub so you can
write `module2 foo.cpio.gz bar.cpio.gz` and have it concatenate things
together in memory and present one MB2 module, but I suspect that exact
syntax might be ambiguous with command line handling.  I have no idea
whether such a command currently exists.

~Andrew


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


[PATCH 16/19] appended signatures: support verifying appended signatures

2021-03-30 Thread Daniel Axtens
Building on the parsers and the ability to embed x509 certificates, as
well as the existing gcrypt functionality, add a module for verifying
appended signatures.

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

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

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

Signed-off-by: Daniel Axtens 
---
 grub-core/Makefile.core.def  |  12 +
 grub-core/commands/appendedsig/appendedsig.c | 645 +++
 include/grub/file.h  |   2 +
 3 files changed, 659 insertions(+)
 create mode 100644 grub-core/commands/appendedsig/appendedsig.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index d63f216111ca..049c83b82018 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -946,6 +946,18 @@ module = {
   cppflags = '-I$(srcdir)/lib/posix_wrap';
 };
 
+module = {
+  name = appendedsig;
+  common = commands/appendedsig/appendedsig.c;
+  common = commands/appendedsig/x509.c;
+  common = commands/appendedsig/pkcs7.c;
+  common = commands/appendedsig/asn1util.c;
+  common = commands/appendedsig/gnutls_asn1_tab.c;
+  common = commands/appendedsig/pkix_asn1_tab.c;
+  cflags = '$(CFLAGS_POSIX)';
+  cppflags = '-I$(srcdir)/lib/posix_wrap';
+};
+
 module = {
   name = hdparm;
   common = commands/hdparm.c;
diff --git a/grub-core/commands/appendedsig/appendedsig.c 
b/grub-core/commands/appendedsig/appendedsig.c
new file mode 100644
index ..1b8a80780615
--- /dev/null
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -0,0 +1,645 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020-2021  IBM Corporation.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "appendedsig.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+const char magic[] = "~Module signature appended~\n";
+
+/*
+ * This structure is extracted from scripts/sign-file.c in the linux kernel
+ * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible.
+ */
+struct module_signature
+{
+  grub_uint8_t algo;   /* Public-key crypto algorithm [0] */
+  grub_uint8_t hash;   /* Digest algorithm [0] */
+  grub_uint8_t id_type;/* Key identifier type [PKEY_ID_PKCS7] 
*/
+  grub_uint8_t signer_len; /* Length of signer's name [0] */
+  grub_uint8_t key_id_len; /* Length of key identifier [0] */
+  grub_uint8_t __pad[3];
+  grub_uint32_t sig_len;   /* Length of signature data */
+} GRUB_PACKED;
+
+
+/* This represents an entire, parsed, appended signature */
+struct grub_appended_signature
+{
+  grub_size_t signature_len;   /* Length of PKCS#7 data +
+ * metadata + magic */
+
+  struct module_signature sig_metadata;/* Module signature metadata */
+  struct pkcs7_signedData pkcs7;   /* Parsed PKCS#7 data */
+};
+
+/* Trusted certificates for verifying appended signatures */
+struct x509_certificate *grub_trusted_key;
+
+/*
+ * Force gcry_rsa to be a module dependency.
+ *
+ * If we use grub_crypto_pk_rsa, then then the gcry_rsa module won't be built
+ * in if you add 'appendedsig' to grub-install --modules. You would need to
+ * add 'gcry_rsa' too. That's confusing and seems suboptimal, especially when
+ * we only support RSA.
+ *
+ * Dynamic loading also causes some concerns. We can't load gcry_rsa from the
+ * the filesystem after we install the verifier - we won't be able to verify
+ * it without having it already present. We also shouldn't load it before we
+ * install the verifier, because that would mean it wouldn't be verified - an
+ * attacker could insert any code they wanted into the module.
+ *
+ * So instead, reference the internal symbol from gcry_rsa. That creates a
+ * direct dependency on gcry_rsa, so it will b

[PATCH 15/19] appended signatures: parse PKCS#7 signedData and X.509 certificates

2021-03-30 Thread Daniel Axtens
This code allows us to parse:

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

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

Signed-off-by: Daniel Axtens 
---
 grub-core/commands/appendedsig/appendedsig.h | 110 +++
 grub-core/commands/appendedsig/asn1util.c| 102 ++
 grub-core/commands/appendedsig/pkcs7.c   | 305 ++
 grub-core/commands/appendedsig/x509.c| 972 +++
 4 files changed, 1489 insertions(+)
 create mode 100644 grub-core/commands/appendedsig/appendedsig.h
 create mode 100644 grub-core/commands/appendedsig/asn1util.c
 create mode 100644 grub-core/commands/appendedsig/pkcs7.c
 create mode 100644 grub-core/commands/appendedsig/x509.c

diff --git a/grub-core/commands/appendedsig/appendedsig.h 
b/grub-core/commands/appendedsig/appendedsig.h
new file mode 100644
index ..9792ef3901e8
--- /dev/null
+++ b/grub-core/commands/appendedsig/appendedsig.h
@@ -0,0 +1,110 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  IBM Corporation.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see .
+ */
+
+#include 
+#include 
+
+extern asn1_node _gnutls_gnutls_asn;
+extern asn1_node _gnutls_pkix_asn;
+
+#define MAX_OID_LEN 32
+
+/*
+ * One or more x509 certificates.
+ *
+ * We do limited parsing: extracting only the serial, CN and RSA public key.
+ */
+struct x509_certificate
+{
+  struct x509_certificate *next;
+
+  grub_uint8_t *serial;
+  grub_size_t serial_len;
+
+  char *subject;
+  grub_size_t subject_len;
+
+  /* We only support RSA public keys. This encodes [modulus, publicExponent] */
+  gcry_mpi_t mpis[2];
+};
+
+/*
+ * A PKCS#7 signedData message.
+ *
+ * We make no attempt to match intelligently, so we don't save any info about
+ * the signer. We also support only 1 signerInfo, so we only store a single
+ * MPI for the signature.
+ */
+struct pkcs7_signedData
+{
+  const gcry_md_spec_t *hash;
+  gcry_mpi_t sig_mpi;
+};
+
+
+/* Do libtasn1 init */
+int asn1_init (void);
+
+/*
+ * Import a DER-encoded certificate at 'data', of size 'size'.
+ *
+ * Place the results into 'results', which must be already allocated.
+ */
+grub_err_t
+certificate_import (void *data, grub_size_t size,
+   struct x509_certificate *results);
+
+/*
+ * Release all the storage associated with the x509 certificate.
+ * If the caller dynamically allocated the certificate, it must free it.
+ * The caller is also responsible for maintenance of the linked list.
+ */
+void certificate_release (struct x509_certificate *cert);
+
+/*
+ * Parse a PKCS#7 message, which must be a signedData message.
+ *
+ * The message must be in 'sigbuf' and of size 'data_size'. The result is
+ * placed in 'msg', which must already be allocated.
+ */
+grub_err_t
+parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size,
+   struct pkcs7_signedData *msg);
+
+/*
+ * Release all the storage associated with the PKCS#7 message.
+ * If the caller dynamically allocated the message, it must free it.
+ */
+void pkcs7_signedData_release (struct pkcs7_signedData *msg);
+
+/*
+ * Read a value from an ASN1 node, allocating memory to store it.
+ *
+ * It will work for anything where the size libtasn1 returns is right:
+ *  - Integers
+ *  - Octet strings
+ *  - DER encoding of other structures
+ * It will _not_ work for things where libtasn1 size requires adjustment:
+ *  - Strings that require an extra NULL byte at the end
+ *  - Bit strings because libtasn1 returns the length in bits, not bytes.
+ *
+ * If the function returns a non-NULL value, the caller must free it.
+ */
+void *grub_asn1_allocate_and_read (asn1_node node, const char *name,
+  const char *friendly_name,
+  int *content_size);
diff --git a/grub-core/commands/appendedsig/asn1util.c 
b/grub-core/commands/appendedsig/asn1util.c
new file mode 100644
index ..eff095a9df23
--- /dev/null
+++ b/grub-core/commands/appendedsig/asn1util.c
@@ -0,0 +1,102 @@
+/*
+ *  GRUB  -

[PATCH 18/19] appended signatures: documentation

2021-03-30 Thread Daniel Axtens
This explains how appended signatures can be used to form part of
a secure boot chain, and documents the commands and variables
introduced.

Signed-off-by: Daniel Axtens 
---
 docs/grub.texi | 193 -
 1 file changed, 176 insertions(+), 17 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 34a2708bc070..9a737683e64f 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
@@ -3987,6 +3995,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
@@ -4003,6 +4012,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
@@ -4040,8 +4050,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
@@ -4366,9 +4378,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
 
@@ -4626,6 +4657,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
 
@@ -4645,7 +4691,7 @@ The output is in GPG's v4 key fingerprint format (i.e., 
the output of
 @code{gpg --fingerprint}).  The 

[PATCH 14/19] appended signatures: import GNUTLS's ASN.1 description files

2021-03-30 Thread Daniel Axtens
In order to parse PKCS#7 messages and X.509 certificates with libtasn1,
we need some information about how they are encoded.

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

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

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

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

[PATCH 13/19] grub-install: support embedding x509 certificates

2021-03-30 Thread Daniel Axtens
From: Alastair D'Silva 

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

Signed-off-by: Alastair D'Silva 
Signed-off-by: Daniel Axtens 
---
 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 355a43844acc..b81ac0ae46ce 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 abbca5ea3359..d3aafc8848d2 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 b3307fef9b41..faecf7b26e23 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}, \
@@ -188,8 +190,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 0eeb12c4784c..2a0964a73fd5 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -334,6 +334,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;
 
@@ -375,6 +377,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++;
@@ -501,6 +509,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);
@@ -529,6 +540,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++ = '\'';
@@ -557,7 +576,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,
+  

[PATCH 09/19] libtasn1: disable code not needed in grub

2021-03-30 Thread Daniel Axtens
We don't expect to be able to write ASN.1, only read it,
so we can disable some code.

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

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

Signed-off-by: Daniel Axtens 
---
 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 245ea64cf0aa..52def5983685 100644
--- a/grub-core/lib/libtasn1/lib/coding.c
+++ b/grub-core/lib/libtasn1/lib/coding.c
@@ -30,11 +30,11 @@
 #include "parser_aux.h"
 #include 
 #include "element.h"
-#include "minmax.h"
 #include 
 
 #define MAX_TAG_LEN 16
 
+#if 0
 /**/
 /* Function : _asn1_error_description_value_not_found */
 /* Description: creates the ErrorDescription string   */
@@ -58,6 +58,7 @@ _asn1_error_description_value_not_found (asn1_node node,
   Estrcat (ErrorDescription, "' not found");
 
 }
+#endif
 
 /**
  * asn1_length_der:
@@ -244,6 +245,7 @@ asn1_encode_simple_der (unsigned int etype, const unsigned 
char *str,
   return ASN1_SUCCESS;
 }
 
+#if 0
 /**/
 /* Function : _asn1_time_der  */
 /* Description: creates the DER coding for a TIME */
@@ -281,7 +283,7 @@ _asn1_time_der (unsigned char *str, int str_len, unsigned 
char *der,
 
   return ASN1_SUCCESS;
 }
-
+#endif
 
 /*
 void
@@ -520,6 +522,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 */
@@ -596,6 +599,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] =
@@ -648,6 +652,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 */
@@ -1413,3 +1419,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 ff04eb778cba..42f9a92b5d44 100644
--- a/grub-core/lib/libtasn1/lib/decoding.c
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -1613,6 +1613,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
@@ -1643,6 +1644,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 997eb2725dca..539008d8e949 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
@@ -645,7 +645,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 cee74daf7959..42785e8622b7 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 8189c56a4c93..fcfde01a3930 100644
--- a/grub-core/lib/libtasn1/lib/structure.c
+++ b/grub-core/lib/libtasn1/lib/structure.c
@@ -76,7 +76,7 @@ _asn

[PATCH 19/19] ieee1275: enter lockdown based on /ibm,secure-boot

2021-03-30 Thread Daniel Axtens
If the 'ibm,secure-boot' property of the root node is 2 or greater,
enter lockdown.

Signed-off-by: Daniel Axtens 
---
 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 9a737683e64f..7cd45f5c5255 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6184,8 +6184,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 4bef6dd0b99e..3f8194fcd43d 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 d483e35eed2b..7a1ebdf94e06 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -44,6 +44,7 @@
 #ifdef __sparc__
 #include 
 #endif
+#include 
 
 /* The minimal heap size we can live with. */
 #define HEAP_MIN_SIZE  (unsigned long) (2 * 1024 * 1024)
@@ -270,6 +271,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
@@ -295,6 +320,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 40531fa823bf..ebfee4bf06e7 100644
--- a/include/grub/lockdown.h
+++ b/include/grub/lockdown.h
@@ -24,7 +24,8 @@
 #define GRUB_LOCKDOWN_DISABLED   0
 #define GRUB_LOCKDOWN_ENABLED1
 
-#ifdef GRUB_MACHINE_EFI
+#if defined(GRUB_MACHINE_EFI) || \
+(defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275))
 extern void
 EXPORT_FUNC (grub_lockdown) (void);
 extern int
-- 
2.27.0


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


[PATCH 11/19] libtasn1: compile into asn1 module

2021-03-30 Thread Daniel Axtens
Create a wrapper file that specifies the module license.
Set up the makefile so it is built.

Signed-off-by: Daniel Axtens 
---
 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 915287d44c13..6fbae150c687 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2535,3 +2535,18 @@ module = {
   common = commands/i386/wrmsr.c;
   enable = x86;
 };
+
+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 ..622ba942e33f
--- /dev/null
+++ b/grub-core/lib/libtasn1_wrap/wrap.c
@@ -0,0 +1,26 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020 IBM Corporation
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see .
+ */
+
+#include 
+
+/*
+ * libtasn1 is provided under LGPL2.1+, which is compatible
+ * with GPL3+. As Grub as a whole is under GPL3+, this module
+ * is therefore under GPL3+ also.
+ */
+GRUB_MOD_LICENSE ("GPLv3+");
-- 
2.27.0


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


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

2021-03-30 Thread Daniel Axtens
The way gcry_rsa and friends (the asymmetric ciphers) are loaded for the
pgp module is a bit quirky.

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

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

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

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

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

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

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

Signed-off-by: Daniel Axtens 
---
 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 2408db4994f6..355a43844acc 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 ca334d5a40e0..c578128a59db 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.27.0


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


[PATCH 10/19] libtasn1: changes for grub compatibility

2021-03-30 Thread Daniel Axtens
Do a few things to make libtasn1 compile as part of grub:

 - replace strcat. grub removed strcat so replace it with the appropriate
   calls to memcpy and strlen.

 - 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 
---
 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 | 26 ++---
 6 files changed, 22 insertions(+), 33 deletions(-)

diff --git a/grub-core/lib/libtasn1/lib/decoding.c 
b/grub-core/lib/libtasn1/lib/decoding.c
index 42f9a92b5d44..7856858b2727 100644
--- a/grub-core/lib/libtasn1/lib/decoding.c
+++ b/grub-core/lib/libtasn1/lib/decoding.c
@@ -32,7 +32,8 @@
 #include 
 #include 
 #include 
-#include 
+
+#define c_isdigit grub_isdigit
 
 #ifdef DEBUG
 # define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
@@ -2008,8 +2009,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);
+ memcpy (name + strlen(name), ".", sizeof(" . "));
+ memcpy (name + strlen(name), p2->name, strlen(p2->name) + 1);
 
  len = sizeof (value);
  result = asn1_read_value (definitions, name, value, &len);
@@ -2026,8 +2027,8 @@ asn1_expand_octet_string (asn1_node_const definitions, 
asn1_node * element,
  if (p2)
{
  strcpy (name, definitions->name);
- strcat (name, ".");
- strcat (name, p2->name);
+ memcpy (name + strlen(name), ".", sizeof(" . "));
+ memcpy (name + strlen(name), p2->name, strlen(p2->name) + 1);
 
  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 539008d8e949..ed761ff56bd9 100644
--- a/grub-core/lib/libtasn1/lib/element.c
+++ b/grub-core/lib/libtasn1/lib/element.c
@@ -30,9 +30,10 @@
 #include "parser_aux.h"
 #include 
 #include "structure.h"
-#include "c-ctype.h"
 #include "element.h"
 
+#define c_isdigit grub_isdigit
+
 void
 _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size)
 {
diff --git a/grub-core/lib/libtasn1/lib/gstr.c 
b/grub-core/lib/libtasn1/lib/gstr.c
index e91a3a151c0d..e33875c2c7c5 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);
+  memcpy (dest + dest_size, src, str_size + 1);
 }
   else
 {
   if (dest_tot_size - dest_size > 0)
{
- 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 ea1625786c1b..4a568efee9c1 100644
--- a/grub-core/lib/libtasn1/lib/int.h
+++ b/grub-core/lib/libtasn1/lib/int.h
@@ -35,7 +35,7 @@
 #include 
 #endif
 
-#include 
+#include "grub/libtasn1.h"
 
 #define ASN1_SMALL_VALUE_SIZE 16
 
@@ -115,7 +115,7 @@ extern const tag_and_class_st _asn1_tags[];
 #define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b)
 #define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b)
 #define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b)
-#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b)
+#define _asn1_strcat(a,b) memcpy((char *)a + strlen((const char *)a), (const 
char *)b, strlen((const char *)b) + 1)
 
 #if SIZEOF_UNSIGNED_LONG_INT == 8
 # define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b)
diff --git a/grub-core/lib/libtasn1/lib/parser_aux.c 
b/grub-core/lib/libtasn1/lib/parser_aux.c
index d5dbbf8765da..89c9be69dc2a 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"
 #in

[PATCH 17/19] appended signatures: verification tests

2021-03-30 Thread Daniel Axtens
These tests are run through all_functional_test and test a range
of commands and behaviours.

Signed-off-by: Daniel Axtens 
---
 grub-core/Makefile.core.def   |   6 +
 grub-core/tests/appended_signature_test.c | 281 +++
 grub-core/tests/appended_signatures.h | 557 ++
 grub-core/tests/lib/functional_test.c |   1 +
 4 files changed, 845 insertions(+)
 create mode 100644 grub-core/tests/appended_signature_test.c
 create mode 100644 grub-core/tests/appended_signatures.h

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 049c83b82018..4bef6dd0b99e 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2129,6 +2129,12 @@ module = {
   common = tests/setjmp_test.c;
 };
 
+module = {
+  name = appended_signature_test;
+  common = tests/appended_signature_test.c;
+  common = tests/appended_signatures.h;
+};
+
 module = {
   name = signature_test;
   common = tests/signature_test.c;
diff --git a/grub-core/tests/appended_signature_test.c 
b/grub-core/tests/appended_signature_test.c
new file mode 100644
index ..88a485200d8b
--- /dev/null
+++ b/grub-core/tests/appended_signature_test.c
@@ -0,0 +1,281 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2020  IBM Corporation.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "appended_signatures.h"
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#define DEFINE_TEST_CASE(case_name) \
+static char * \
+get_ ## case_name (grub_size_t *sz) \
+{ \
+  char *ret; \
+  *sz = case_name ## _len; \
+  ret = grub_malloc (*sz); \
+  if (ret) \
+grub_memcpy (ret, case_name, *sz); \
+  return ret; \
+} \
+\
+static struct grub_procfs_entry case_name ## _entry = \
+{ \
+  .name = #case_name, \
+  .get_contents = get_ ## case_name \
+}
+
+#define DO_TEST(case_name, is_valid) \
+{ \
+  grub_procfs_register (#case_name, &case_name ## _entry); \
+  do_verify ("(proc)/" #case_name, is_valid); \
+  grub_procfs_unregister (&case_name ## _entry); \
+}
+
+
+DEFINE_TEST_CASE (hi_signed);
+DEFINE_TEST_CASE (hi_signed_sha256);
+DEFINE_TEST_CASE (hj_signed);
+DEFINE_TEST_CASE (short_msg);
+DEFINE_TEST_CASE (unsigned_msg);
+DEFINE_TEST_CASE (hi_signed_2nd);
+
+static char *
+get_certificate_der (grub_size_t * sz)
+{
+  char *ret;
+  *sz = certificate_der_len;
+  ret = grub_malloc (*sz);
+  if (ret)
+grub_memcpy (ret, certificate_der, *sz);
+  return ret;
+}
+
+static struct grub_procfs_entry certificate_der_entry = {
+  .name = "certificate.der",
+  .get_contents = get_certificate_der
+};
+
+static char *
+get_certificate2_der (grub_size_t * sz)
+{
+  char *ret;
+  *sz = certificate2_der_len;
+  ret = grub_malloc (*sz);
+  if (ret)
+grub_memcpy (ret, certificate2_der, *sz);
+  return ret;
+}
+
+static struct grub_procfs_entry certificate2_der_entry = {
+  .name = "certificate2.der",
+  .get_contents = get_certificate2_der
+};
+
+static char *
+get_certificate_printable_der (grub_size_t * sz)
+{
+  char *ret;
+  *sz = certificate_printable_der_len;
+  ret = grub_malloc (*sz);
+  if (ret)
+grub_memcpy (ret, certificate_printable_der, *sz);
+  return ret;
+}
+
+static struct grub_procfs_entry certificate_printable_der_entry = {
+  .name = "certificate_printable.der",
+  .get_contents = get_certificate_printable_der
+};
+
+
+static void
+do_verify (const char *f, int is_valid)
+{
+  grub_command_t cmd;
+  char *args[] = { (char *) f, NULL };
+  grub_err_t err;
+
+  cmd = grub_command_find ("verify_appended");
+  if (!cmd)
+{
+  grub_test_assert (0, "can't find command `%s'", "verify_appended");
+  return;
+}
+  err = (cmd->func) (cmd, 1, args);
+  if (is_valid)
+{
+  grub_test_assert (err == GRUB_ERR_NONE,
+   "verification of %s failed: %d: %s", f, grub_errno,
+   grub_errmsg);
+}
+  else
+{
+  grub_test_assert (err == GRUB_ERR_BAD_SIGNATURE,
+   "verification of %s unexpectedly succeeded", f);
+}
+  grub_errno = GRUB_ERR_NONE;
+
+}
+
+static void
+appended_signature_test (void)
+{
+  grub_command_t cmd_trust, cmd_distrust;
+  char *trust_args[] = { (char *) "(proc)/certificate.der", NULL };
+  char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL };
+  char *trust_a

[PATCH 05/19] pgp: factor out rsa_pad

2021-03-30 Thread Daniel Axtens
rsa_pad does the PKCS#1 v1.5 padding for the RSA signature scheme.
We want to use it in other RSA signature verification applications.

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

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

Signed-off-by: Daniel Axtens 
---
 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 8022e1c0a794..915287d44c13 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2469,6 +2469,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 5daa1e9d00c7..2408db4994f6 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -411,32 +412,7 @@ static int
 rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval,
 const gcry_md_spec_t *hash, struct grub_public_subkey *sk)
 {
-  grub_size_t tlen, emlen, fflen;
-  grub_uint8_t *em, *emptr;
-  unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]);
-  int ret;
-  tlen = hash->mdlen + hash->asnlen;
-  emlen = (nbits + 7) / 8;
-  if (emlen < tlen + 11)
-return 1;
-
-  em = grub_malloc (emlen);
-  if (!em)
-return 1;
-
-  em[0] = 0x00;
-  em[1] = 0x01;
-  fflen = emlen - tlen - 3;
-  for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
-*emptr = 0xff;
-  *emptr++ = 0x00;
-  grub_memcpy (emptr, hash->asnoid, hash->asnlen);
-  emptr += hash->asnlen;
-  grub_memcpy (emptr, hval, hash->mdlen);
-
-  ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
-  grub_free (em);
-  return ret;
+  return grub_crypto_rsa_pad(hmpi, hval, hash, sk->mpis[0]);
 }
 
 struct grub_pubkey_context
diff --git a/grub-core/lib/pkcs1_v15.c b/grub-core/lib/pkcs1_v15.c
new file mode 100644
index ..dbacd563d014
--- /dev/null
+++ b/grub-core/lib/pkcs1_v15.c
@@ -0,0 +1,59 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see .
+ */
+
+#include 
+#include 
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+/*
+ * Given a hash value 'hval', of hash specification 'hash', perform
+ * the EMSA-PKCS1-v1_5 padding suitable for a key with modulus 'mod'
+ * (see RFC 8017 s 9.2) and place the result in 'hmpi'.
+ */
+gcry_err_code_t
+grub_crypto_rsa_pad (gcry_mpi_t * hmpi, grub_uint8_t * hval,
+const gcry_md_spec_t * hash, gcry_mpi_t mod)
+{
+  grub_size_t tlen, emlen, fflen;
+  grub_uint8_t *em, *emptr;
+  unsigned nbits = gcry_mpi_get_nbits (mod);
+  int ret;
+  tlen = hash->mdlen + hash->asnlen;
+  emlen = (nbits + 7) / 8;
+  if (emlen < tlen + 11)
+return GPG_ERR_TOO_SHORT;
+
+  em = grub_malloc (emlen);
+  if (!em)
+return 1;
+
+  em[0] = 0x00;
+  em[1] = 0x01;
+  fflen = emlen - tlen - 3;
+  for (emptr = em + 2; emptr < em + 2 + fflen; emptr++)
+*emptr = 0xff;
+  *emptr++ = 0x00;
+  grub_memcpy (emptr, hash->asnoid, hash->asnlen);
+  emptr += hash->asnlen;
+  grub_memcpy (emptr, hval, hash->mdlen);
+
+  ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0);
+  grub_free (em);
+  return ret;
+}
diff --git a/include/grub/pkcs1_v15.h b/include/grub/pkcs1_v15.h
new file mode 100644
index ..5c338c84a158
--- /dev/null
+++ b/include/grub/pkcs1_v15.h
@@ -0,0 +1,27 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  Free Software Foundation, Inc.
+ *
+ *  GR

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

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

Provide an empty function for the emu case.

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

diff --git a/include/grub/dl.h b/include/grub/dl.h
index b3753c9ca262..5decbe2f2fb9 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.27.0


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


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

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

Signed-off-by: Daniel Axtens 
---
 docs/grub.texi | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index b1a0e2761691..34a2708bc070 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6050,6 +6050,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.27.0


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


[PATCH 07/19] posix_wrap: tweaks in preparation for libtasn1

2021-03-30 Thread Daniel Axtens
 - Define SIZEOF_UNSIGNED_LONG_INT, it's the same as
   SIZEOF_UNSIGNED_LONG.

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

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

Signed-off-by: Daniel Axtens 
---
 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 7217138ffd6b..591dbf3289d8 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 7a8d385e973a..4634db09f294 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 854eb0122efa..f63412c8da06 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.27.0


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


[PATCH 01/19] Add suport for signing grub with an appended signature

2021-03-30 Thread Daniel Axtens
From: Rashmica Gupta 

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

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

To address this, we add a new ELF note.

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

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

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

Signed-off-by: Daniel Axtens 
Signed-off-by: Rashmica Gupta 

---

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 b93c73caac64..b3307fef9b41 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 }
 
@@ -128,7 +131,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;
@@ -188,7 +192,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 3819a67441c8..6f1da89b9b65 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 b4f28840f10e..0eeb12c4784c 100644
--- a/util/grub-install-common.c
+++ b/util/grub-ins

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

2021-03-30 Thread Daniel Axtens
Before adding information about how grub is signed with an appended
signature scheme, it's worth adding some information about how it
can currently be signed for UEFI.

Signed-off-by: Daniel Axtens 
---
 docs/grub.texi | 22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index eeb3118ebdec..b1a0e2761691 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5790,6 +5790,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
@@ -5868,7 +5869,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}
@@ -6030,6 +6031,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.27.0


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


[PATCH 00/19] appended signature secure boot support

2021-03-30 Thread Daniel Axtens
This patch set contains a consolidated version of the patch sets sent
for secure boot using appended signatures on powerpc, rebased on top
of 2.06~rc1. This has required some changes, mostly around lockdown
and the change to shim handling. I have also extended the X.509 parser
to support printableString as well as utf8String. I don't think there
are any other major changes.

The series consists of 3 main parts:

 1) Patches 1-3: signing grub.elf with an appended signature

Part of a secure boot chain is allowing boot firmware to verify the
grub core image. For UEFI platforms, this is done by signing the PE
binary with a tool like pesign or sb-sign. However, for platforms that
don't implement UEFI, an alternative scheme is required.

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

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

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

This has attracted some controversy in the past, with suggestions that
we could avoid the ELF note by placing the signature at the end of
core.elf if the image was loaded from a filesystem or network, and by
placing it at the end of the PReP partition if it is loaded from
there. This is not currently supported by either proprietary or open
source firmware, but the current solution does not preclude this
solution being added in the future.

There was also a suggestion of allowing grub-{install,mkimage} to call
out to openssl directly to sign itself. I'm not opposed to doing this,
but as I expect signing to mostly be something done by distros rather
than the average grub-install user, I'm interested to hear any
thoughts on whether that's actually going to be useful.



 2) Patches 4 - 18: Teach grub to verify appended signatures

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

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

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

This section is composed of the following patches:
 
 - patch 4 is a small fix to allow persistent modules to work on the
   emu target.

 - patches 5 and 6 are small refactorings.

 - patch 7 prepares posix_wrap for importing libtasn1

 - patches 8 through 12 import libtasn1 and add tests. I've taken a
   different approach from gcrypt. We import gcrypt via a script that
   transforms the code into something that works for grub. Rather than
   taking that approach, we import libtasn1 through first just copying
   a subset of the code in (patch 8), then disabling parts we don't
   need for grub (patch 9), making changes for grub compatibility
   (patch 10) and then compiling it into a module (patch 11) and
   testing it (patch 12).

   This means that should we want to upgrade our version of libtasn1,
   we should be able to copy the new files in (repeat the process in
   patch 8) and then just cherry-pick/reapply patches 9 and 10 to
   repeat the process of disabling unused code and making grub
   compatiblity fixes. Hopefully that makes sense!

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

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

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

 - patch 16 is the guts of the appended signature verifier. It uses
   the verifier infrastructure like pgp, and adds a number of
   user-friendly commands that mirror the pgp module.

 - patch 17 adds tests, and patch 18 adds documentation.



 3) Patch 19: Enter lockdown if in powerpc secure boot

This is now a much neater and nicer solution than before - it detects
if the DT property advertising SB is set, and enters lockdown if it
is. The main appended signature series now tests for lockdown to enter
'forced' mode.




I've pushed this all to
https://github.com/daxtens/grub/tree/appendedsi