Thank you Daniel for the review.

> On 27 Aug 2025, at 8:43 PM, Daniel Kiper <dki...@net-space.pl> wrote:
> 
> On Mon, Aug 25, 2025 at 04:38:32PM +0530, Sudhakar Kuppusamy wrote:
>> Building on the parsers and the ability to embed X.509 certificates, as
>> well as the existing gcrypt functionality, add a module for verifying
>> appended signatures.
>> 
>> This includes a signature verifier that requires that the Linux kernel and
>> GRUB modules have appended signatures for verification.
>> 
>> Signature verification must be enabled by setting check_appended_signatures.
>> If secure boot is enabled with enforced mode when the appendedsig
>> module is loaded, signature verification will be enabled, and trusted
>> keys will be extracted from the GRUB ELF Note and stored in the db and
>> locked automatically.
>> 
>> Signed-off-by: Daniel Axtens <d...@axtens.net>
>> Signed-off-by: Sudhakar Kuppusamy <sudha...@linux.ibm.com>
> 
> Except two nits below Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>...
> 
> [...]
> 
>> diff --git a/grub-core/commands/appendedsig/appendedsig.c 
>> b/grub-core/commands/appendedsig/appendedsig.c
>> new file mode 100644
>> index 000000000..5eb7b768a
>> --- /dev/null
>> +++ b/grub-core/commands/appendedsig/appendedsig.c
>> @@ -0,0 +1,597 @@
>> +/*
>> + *  GRUB  --  GRand Unified Bootloader
>> + *  Copyright (C) 2020, 2021, 2022 Free Software Foundation, Inc.
>> + *  Copyright (C) 2020, 2021, 2022, 2025 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/types.h>
>> +#include <grub/misc.h>
>> +#include <grub/mm.h>
>> +#include <grub/err.h>
>> +#include <grub/dl.h>
>> +#include <grub/file.h>
>> +#include <grub/command.h>
>> +#include <grub/crypto.h>
>> +#include <grub/i18n.h>
>> +#include <grub/gcrypt/gcrypt.h>
>> +#include <grub/kernel.h>
>> +#include <grub/extcmd.h>
>> +#include <grub/verify.h>
>> +#include <libtasn1.h>
>> +#include <grub/env.h>
>> +#include <grub/lockdown.h>
>> +
>> +#include "appendedsig.h"
>> +
>> +GRUB_MOD_LICENSE ("GPLv3+");
>> +
>> +/* Max size of hash data. */
>> +#define MAX_HASH_SIZE      64
>> +
>> +/* Public key type. */
>> +#define PKEY_ID_PKCS7      2
>> +
>> +/* Appended signature magic string and size. */
>> +#define SIG_MAGIC          "~Module signature appended~\n"
>> +#define SIG_MAGIC_SIZE     ((sizeof(SIG_MAGIC) - 1))
>> +
>> +/*
>> + * 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 [GRUB_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;
>> +
>> +#define SIG_METADATA_SIZE  (sizeof (struct module_signature))
>> +#define APPENDED_SIG_SIZE(pkcs7_data_size) \
>> +                           (pkcs7_data_size + SIG_MAGIC_SIZE + 
>> SIG_METADATA_SIZE)
>> +
>> +/* 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. */
>> +};
>> +
>> +/* This represents a trusted certificates. */
>> +struct grub_database
>> +{
>> +  struct x509_certificate *certs; /* Certificates. */
>> +  grub_uint32_t cert_entries;     /* Number of certificates. */
>> +};
>> +
>> +/* The db list is used to validate appended signatures. */
>> +struct grub_database db = {.certs = NULL, .cert_entries = 0};
>> +
>> +/*
>> + * Signature verification flag (check_sigs).
>> + * check_sigs: false
>> + *  - No signature verification. This is the default.
>> + * check_sigs: true
>> + *  - Enforce signature verification, and if signature verification fails,
>> + *    post the errors and stop the boot.
>> + */
>> +static bool check_sigs = false;
>> +
>> +static grub_ssize_t
>> +pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
>> +{
>> +  grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len);
>> +  return len;
>> +}
>> +
>> +/* Filesystem descriptor. */
>> +static struct grub_fs pseudo_fs = {
>> +  .name = "pseudo",
>> +  .fs_read = pseudo_read
>> +};
>> +
>> +static void
>> +add_cert_fingerprint (const grub_uint8_t *data, const grub_size_t data_size,
>> +                      struct x509_certificate *const cert)
>> +{
>> +  gcry_md_spec_t *hash_func = NULL;
>> +
>> +  /* Add SHA256 hash of certificate. */
>> +  hash_func = &_gcry_digest_spec_sha256;
>> +  grub_memset (&cert->fingerprint[0], 0, MAX_HASH_SIZE);
>> +  grub_crypto_hash (hash_func, &cert->fingerprint[0], data, data_size);
> 
> grub_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha256, ...
> 
> And you can drop hash_func vaiable then…
Sure, will do it.
> 
>> +}
> 
> [...]
> 
>> +static char *
>> +grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), 
>> const char *val)
>> +{
>> +  char *ret;
>> +
>> +  /*
>> +   * Do not allow the value to be changed If signature verification is
> 
> s/If/if/
Sure, will change it.

Thanks,
Sudhakar
> 
>> +   * (check_sigs is set to enforce) enabled and GRUB is locked down.
>> +   */
>> +  if (check_sigs == true && grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
>> +    {
>> +      ret = grub_strdup ("enforce");
>> +      if (ret == NULL)
>> +        grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not duplicate a string 
>> enforce");
>> +
>> +      return ret;
>> +    }
>> +
>> +  if ((*val == '1') || (*val == 'e'))
>> +    check_sigs = true;
>> +  else if ((*val == '0') || (*val == 'n'))
>> +    check_sigs = false;
>> +
>> +  ret = grub_strdup (grub_env_read_sec (NULL, NULL));
>> +  if (ret == NULL)
>> +    grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not duplicate a string %s",
>> +                grub_env_read_sec (NULL, NULL));
>> +
>> +  return ret;
>> +}
> 
> Daniel



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

Reply via email to