powerpc: Add appended signature feature
Resolves: #RHEL-24510 Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
This commit is contained in:
parent
f4f7a97672
commit
17ffd9b3e0
261873
0374-libgcrypt-Import-libgcrypt-1.11.patch
Normal file
261873
0374-libgcrypt-Import-libgcrypt-1.11.patch
Normal file
File diff suppressed because one or more lines are too long
299
0375-b64dec-Import-b64dec-from-gpg-error.patch
Normal file
299
0375-b64dec-Import-b64dec-from-gpg-error.patch
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:08 +0000
|
||||||
|
Subject: [PATCH] b64dec: Import b64dec from gpg-error
|
||||||
|
|
||||||
|
Imported from libgpg-error 1.51.
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/lib/b64dec.c | 279 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 279 insertions(+)
|
||||||
|
create mode 100644 grub-core/lib/b64dec.c
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/b64dec.c b/grub-core/lib/b64dec.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..868d985
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/b64dec.c
|
||||||
|
@@ -0,0 +1,279 @@
|
||||||
|
+/* b64dec.c - Simple Base64 decoder.
|
||||||
|
+ * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2008, 2011, 2016 g10 Code GmbH
|
||||||
|
+ *
|
||||||
|
+ * This file is part of Libgpg-error.
|
||||||
|
+ *
|
||||||
|
+ * This file is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU Lesser General Public License as
|
||||||
|
+ * published by the Free Software Foundation; either version 2.1 of
|
||||||
|
+ * the License, or (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This file 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 Lesser General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||||||
|
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+ * SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
+ *
|
||||||
|
+ * This file was originally a part of GnuPG.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <config.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+#include "gpgrt-int.h"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* The reverse base-64 list used for base-64 decoding. */
|
||||||
|
+static unsigned char const asctobin[128] =
|
||||||
|
+ {
|
||||||
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||||
|
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||||
|
+ 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||||
|
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||||
|
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||||
|
+ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||||
|
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||||
|
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+enum decoder_states
|
||||||
|
+ {
|
||||||
|
+ s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
|
||||||
|
+ s_b64_0, s_b64_1, s_b64_2, s_b64_3,
|
||||||
|
+ s_waitendtitle, s_waitend
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Allocate and initialize the context for the base64 decoder. If
|
||||||
|
+ TITLE is NULL a plain base64 decoding is done. If it is the empty
|
||||||
|
+ string the decoder will skip everything until a "-----BEGIN " line
|
||||||
|
+ has been seen, decoding ends at a "----END " line. */
|
||||||
|
+gpgrt_b64state_t
|
||||||
|
+_gpgrt_b64dec_start (const char *title)
|
||||||
|
+{
|
||||||
|
+ gpgrt_b64state_t state;
|
||||||
|
+ char *t = NULL;
|
||||||
|
+
|
||||||
|
+ if (title)
|
||||||
|
+ {
|
||||||
|
+ t = xtrystrdup (title);
|
||||||
|
+ if (!t)
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ state = xtrycalloc (1, sizeof (struct _gpgrt_b64state));
|
||||||
|
+ if (!state)
|
||||||
|
+ {
|
||||||
|
+ xfree (t);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (t)
|
||||||
|
+ {
|
||||||
|
+ state->title = t;
|
||||||
|
+ state->idx = s_init;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ state->idx = s_b64_0;
|
||||||
|
+
|
||||||
|
+ state->using_decoder = 1;
|
||||||
|
+
|
||||||
|
+ return state;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the
|
||||||
|
+ new length of the buffer at R_NBYTES. */
|
||||||
|
+gpg_err_code_t
|
||||||
|
+_gpgrt_b64dec_proc (gpgrt_b64state_t state, void *buffer, size_t length,
|
||||||
|
+ size_t *r_nbytes)
|
||||||
|
+{
|
||||||
|
+ enum decoder_states ds = state->idx;
|
||||||
|
+ unsigned char val = state->radbuf[0];
|
||||||
|
+ int pos = state->quad_count;
|
||||||
|
+ char *d, *s;
|
||||||
|
+
|
||||||
|
+ if (state->lasterr)
|
||||||
|
+ return state->lasterr;
|
||||||
|
+
|
||||||
|
+ if (state->stop_seen)
|
||||||
|
+ {
|
||||||
|
+ *r_nbytes = 0;
|
||||||
|
+ state->lasterr = GPG_ERR_EOF;
|
||||||
|
+ xfree (state->title);
|
||||||
|
+ state->title = NULL;
|
||||||
|
+ return state->lasterr;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (s=d=buffer; length && !state->stop_seen; length--, s++)
|
||||||
|
+ {
|
||||||
|
+ again:
|
||||||
|
+ switch (ds)
|
||||||
|
+ {
|
||||||
|
+ case s_idle:
|
||||||
|
+ if (*s == '\n')
|
||||||
|
+ {
|
||||||
|
+ ds = s_lfseen;
|
||||||
|
+ pos = 0;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case s_init:
|
||||||
|
+ ds = s_lfseen;
|
||||||
|
+ /* Fall through */
|
||||||
|
+ case s_lfseen:
|
||||||
|
+ if (*s != "-----BEGIN "[pos])
|
||||||
|
+ {
|
||||||
|
+ ds = s_idle;
|
||||||
|
+ goto again;
|
||||||
|
+ }
|
||||||
|
+ else if (pos == 10)
|
||||||
|
+ {
|
||||||
|
+ pos = 0;
|
||||||
|
+ ds = s_beginseen;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ pos++;
|
||||||
|
+ break;
|
||||||
|
+ case s_beginseen:
|
||||||
|
+ if (*s != "PGP "[pos])
|
||||||
|
+ ds = s_begin; /* Not a PGP armor. */
|
||||||
|
+ else if (pos == 3)
|
||||||
|
+ ds = s_waitheader;
|
||||||
|
+ else
|
||||||
|
+ pos++;
|
||||||
|
+ break;
|
||||||
|
+ case s_waitheader:
|
||||||
|
+ if (*s == '\n')
|
||||||
|
+ ds = s_waitblank;
|
||||||
|
+ break;
|
||||||
|
+ case s_waitblank:
|
||||||
|
+ if (*s == '\n')
|
||||||
|
+ ds = s_b64_0; /* blank line found. */
|
||||||
|
+ else if (*s == ' ' || *s == '\r' || *s == '\t')
|
||||||
|
+ ; /* Ignore spaces. */
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ /* Armor header line. Note that we don't care that our
|
||||||
|
+ * FSM accepts a header prefixed with spaces. */
|
||||||
|
+ ds = s_waitheader; /* Wait for next header. */
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case s_begin:
|
||||||
|
+ if (*s == '\n')
|
||||||
|
+ ds = s_b64_0;
|
||||||
|
+ break;
|
||||||
|
+ case s_b64_0:
|
||||||
|
+ case s_b64_1:
|
||||||
|
+ case s_b64_2:
|
||||||
|
+ case s_b64_3:
|
||||||
|
+ {
|
||||||
|
+ int c;
|
||||||
|
+
|
||||||
|
+ if (*s == '-' && state->title)
|
||||||
|
+ {
|
||||||
|
+ /* Not a valid Base64 character: assume end
|
||||||
|
+ header. */
|
||||||
|
+ ds = s_waitend;
|
||||||
|
+ }
|
||||||
|
+ else if (*s == '=')
|
||||||
|
+ {
|
||||||
|
+ /* Pad character: stop */
|
||||||
|
+ if (ds == s_b64_1)
|
||||||
|
+ *d++ = val;
|
||||||
|
+ ds = state->title? s_waitendtitle : s_waitend;
|
||||||
|
+ }
|
||||||
|
+ else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
|
||||||
|
+ ; /* Skip white spaces. */
|
||||||
|
+ else if ( (*s & 0x80)
|
||||||
|
+ || (c = asctobin[*(unsigned char *)s]) == 255)
|
||||||
|
+ {
|
||||||
|
+ /* Skip invalid encodings. */
|
||||||
|
+ state->invalid_encoding = 1;
|
||||||
|
+ }
|
||||||
|
+ else if (ds == s_b64_0)
|
||||||
|
+ {
|
||||||
|
+ val = c << 2;
|
||||||
|
+ ds = s_b64_1;
|
||||||
|
+ }
|
||||||
|
+ else if (ds == s_b64_1)
|
||||||
|
+ {
|
||||||
|
+ val |= (c>>4)&3;
|
||||||
|
+ *d++ = val;
|
||||||
|
+ val = (c<<4)&0xf0;
|
||||||
|
+ ds = s_b64_2;
|
||||||
|
+ }
|
||||||
|
+ else if (ds == s_b64_2)
|
||||||
|
+ {
|
||||||
|
+ val |= (c>>2)&15;
|
||||||
|
+ *d++ = val;
|
||||||
|
+ val = (c<<6)&0xc0;
|
||||||
|
+ ds = s_b64_3;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ val |= c&0x3f;
|
||||||
|
+ *d++ = val;
|
||||||
|
+ ds = s_b64_0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ case s_waitendtitle:
|
||||||
|
+ if (*s == '-')
|
||||||
|
+ ds = s_waitend;
|
||||||
|
+ break;
|
||||||
|
+ case s_waitend:
|
||||||
|
+ if ( *s == '\n')
|
||||||
|
+ state->stop_seen = 1;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ gpgrt_assert (!"invalid state");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ state->idx = ds;
|
||||||
|
+ state->radbuf[0] = val;
|
||||||
|
+ state->quad_count = pos;
|
||||||
|
+ *r_nbytes = (d -(char*) buffer);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Return an error code in case an encoding error has been found
|
||||||
|
+ during decoding. */
|
||||||
|
+gpg_err_code_t
|
||||||
|
+_gpgrt_b64dec_finish (gpgrt_b64state_t state)
|
||||||
|
+{
|
||||||
|
+ gpg_error_t err;
|
||||||
|
+
|
||||||
|
+ if (!state)
|
||||||
|
+ return 0; /* Already released. */
|
||||||
|
+
|
||||||
|
+ if (!state->using_decoder)
|
||||||
|
+ err = GPG_ERR_CONFLICT; /* State was allocated for the encoder. */
|
||||||
|
+ else if (state->lasterr)
|
||||||
|
+ err = state->lasterr;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ xfree (state->title);
|
||||||
|
+ err = state->invalid_encoding? GPG_ERR_BAD_DATA : 0;
|
||||||
|
+ }
|
||||||
|
+ xfree (state);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:09 +0000
|
||||||
|
Subject: [PATCH] b64dec: Add harness for compilation in GRUB environment
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/lib/gpgrt-int.h | 24 ++++++++++++++++++++++++
|
||||||
|
1 file changed, 24 insertions(+)
|
||||||
|
create mode 100644 grub-core/lib/gpgrt-int.h
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/gpgrt-int.h b/grub-core/lib/gpgrt-int.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..45d6358
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/gpgrt-int.h
|
||||||
|
@@ -0,0 +1,24 @@
|
||||||
|
+#include <grub/crypto.h>
|
||||||
|
+
|
||||||
|
+struct _gpgrt_b64state
|
||||||
|
+{
|
||||||
|
+ int idx;
|
||||||
|
+ int quad_count;
|
||||||
|
+ char *title;
|
||||||
|
+ unsigned char radbuf[4];
|
||||||
|
+ unsigned int crc;
|
||||||
|
+ gpg_err_code_t lasterr;
|
||||||
|
+ unsigned int flags;
|
||||||
|
+ unsigned int stop_seen:1;
|
||||||
|
+ unsigned int invalid_encoding:1;
|
||||||
|
+ unsigned int using_decoder:1;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define _gpgrt_b64dec_start gpgrt_b64dec_start
|
||||||
|
+#define xtrystrdup grub_strdup
|
||||||
|
+#define xtrycalloc grub_calloc
|
||||||
|
+#define xfree grub_free
|
||||||
|
+#define _gpgrt_b64dec_finish gpgrt_b64dec_finish
|
||||||
|
+#define gpgrt_assert(expr) ((expr)? (void)0 \
|
||||||
|
+ : _gcry_assert_failed (#expr, __FILE__, __LINE__, __FUNCTION__))
|
||||||
|
+#define _gpgrt_b64dec_proc gpgrt_b64dec_proc
|
||||||
2255
0377-libgcrypt-Adjust-import-script-definitions-and-API-u.patch
Normal file
2255
0377-libgcrypt-Adjust-import-script-definitions-and-API-u.patch
Normal file
File diff suppressed because it is too large
Load Diff
285
0378-tests-Add-DSA-and-RSA-SEXP-tests.patch
Normal file
285
0378-tests-Add-DSA-and-RSA-SEXP-tests.patch
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:11 +0000
|
||||||
|
Subject: [PATCH] tests: Add DSA and RSA SEXP tests
|
||||||
|
|
||||||
|
This allows us to test purely the integration of the implementation of
|
||||||
|
DSA and RSA from libgcrypt without concerning with additional code.
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/Makefile.core.def | 16 +++++
|
||||||
|
grub-core/tests/dsa_sexp_test.c | 127 ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
grub-core/tests/rsa_sexp_test.c | 101 ++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 244 insertions(+)
|
||||||
|
create mode 100644 grub-core/tests/dsa_sexp_test.c
|
||||||
|
create mode 100644 grub-core/tests/rsa_sexp_test.c
|
||||||
|
|
||||||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||||
|
index 4ba5d94..0b6b996 100644
|
||||||
|
--- a/grub-core/Makefile.core.def
|
||||||
|
+++ b/grub-core/Makefile.core.def
|
||||||
|
@@ -2215,6 +2215,22 @@ module = {
|
||||||
|
common = tests/setjmp_test.c;
|
||||||
|
};
|
||||||
|
|
||||||
|
+module = {
|
||||||
|
+ name = dsa_sexp_test;
|
||||||
|
+ common = tests/dsa_sexp_test.c;
|
||||||
|
+
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
|
||||||
|
+ cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module = {
|
||||||
|
+ name = rsa_sexp_test;
|
||||||
|
+ common = tests/rsa_sexp_test.c;
|
||||||
|
+
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
|
||||||
|
+ cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
module = {
|
||||||
|
name = appended_signature_test;
|
||||||
|
common = tests/appended_signature_test.c;
|
||||||
|
diff --git a/grub-core/tests/dsa_sexp_test.c b/grub-core/tests/dsa_sexp_test.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..31600d9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/tests/dsa_sexp_test.c
|
||||||
|
@@ -0,0 +1,127 @@
|
||||||
|
+/*
|
||||||
|
+ * GRUB -- GRand Unified Bootloader
|
||||||
|
+ * Copyright (C) 2025 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/test.h>
|
||||||
|
+#include <grub/crypto.h>
|
||||||
|
+#include <grub/gcrypt/gcrypt.h>
|
||||||
|
+
|
||||||
|
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
+
|
||||||
|
+/* Sample DSA public key. */
|
||||||
|
+static char pubkey_dump[] = {
|
||||||
|
+ 0x28, 0x31, 0x30, 0x3a, 0x70, 0x75, 0x62, 0x6c,
|
||||||
|
+ 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x28, 0x33,
|
||||||
|
+ 0x3a, 0x64, 0x73, 0x61, 0x28, 0x31, 0x3a, 0x70,
|
||||||
|
+ 0x31, 0x32, 0x39, 0x3a, 0x00, 0xc0, 0x50, 0x14,
|
||||||
|
+ 0x4c, 0x97, 0x10, 0x69, 0x07, 0xa7, 0xe9, 0x2b,
|
||||||
|
+ 0xe5, 0xc6, 0x88, 0xe1, 0x6d, 0xd8, 0x38, 0x28,
|
||||||
|
+ 0x09, 0x49, 0x5b, 0xe8, 0xa3, 0x04, 0xb8, 0xc4,
|
||||||
|
+ 0x6e, 0x98, 0xc1, 0xc2, 0xb0, 0x2a, 0xe0, 0xe2,
|
||||||
|
+ 0x1a, 0x30, 0xd2, 0xdb, 0x45, 0x1a, 0x88, 0x80,
|
||||||
|
+ 0x28, 0x24, 0xb0, 0xbf, 0xc2, 0xbd, 0xe9, 0xf6,
|
||||||
|
+ 0x9d, 0xa2, 0x01, 0x94, 0xe6, 0x7f, 0xa0, 0xb6,
|
||||||
|
+ 0xe4, 0x39, 0xfc, 0x54, 0xba, 0x99, 0xb6, 0xbe,
|
||||||
|
+ 0x39, 0xee, 0xa5, 0xd9, 0xa0, 0x35, 0x3c, 0x2d,
|
||||||
|
+ 0x3e, 0x96, 0xc3, 0x96, 0xa5, 0x0d, 0x2b, 0xbf,
|
||||||
|
+ 0x3b, 0xa3, 0xe2, 0xe8, 0x89, 0xed, 0x60, 0xe0,
|
||||||
|
+ 0x43, 0x61, 0xb6, 0x73, 0xf6, 0xa7, 0xb4, 0x56,
|
||||||
|
+ 0x76, 0x04, 0xf7, 0x8b, 0xf1, 0x84, 0xaa, 0x3e,
|
||||||
|
+ 0xe0, 0x08, 0xad, 0xdd, 0xc2, 0x36, 0xfd, 0x3d,
|
||||||
|
+ 0xd0, 0xad, 0xf4, 0x3a, 0x7e, 0x80, 0x8c, 0x52,
|
||||||
|
+ 0x2b, 0x04, 0xa8, 0x03, 0x27, 0x29, 0x28, 0x31,
|
||||||
|
+ 0x3a, 0x71, 0x32, 0x31, 0x3a, 0x00, 0xd5, 0x34,
|
||||||
|
+ 0xd2, 0xc5, 0x1c, 0x26, 0xdf, 0xb0, 0xba, 0x78,
|
||||||
|
+ 0x75, 0xe5, 0xe9, 0x36, 0x6b, 0x04, 0x03, 0xe2,
|
||||||
|
+ 0x57, 0x3f, 0x29, 0x28, 0x31, 0x3a, 0x67, 0x31,
|
||||||
|
+ 0x32, 0x38, 0x3a, 0x3b, 0xa0, 0xac, 0xa3, 0xa1,
|
||||||
|
+ 0xd1, 0x04, 0x23, 0x5f, 0x9f, 0xbc, 0x6d, 0x9e,
|
||||||
|
+ 0x88, 0x2a, 0x28, 0xc1, 0x48, 0xaf, 0xa5, 0x17,
|
||||||
|
+ 0x59, 0x3a, 0x17, 0x33, 0x56, 0xaa, 0x8d, 0x27,
|
||||||
|
+ 0x64, 0xfe, 0x8e, 0x8a, 0x2e, 0xba, 0xf2, 0x66,
|
||||||
|
+ 0xcc, 0x66, 0xbd, 0xa4, 0xfe, 0xa9, 0x07, 0x0d,
|
||||||
|
+ 0xae, 0x8c, 0x9f, 0x70, 0xf7, 0x87, 0xaa, 0x01,
|
||||||
|
+ 0x47, 0x6b, 0xf9, 0x0f, 0x09, 0x18, 0x42, 0x76,
|
||||||
|
+ 0xc4, 0xa3, 0xb9, 0x55, 0x11, 0x8d, 0xa3, 0xa5,
|
||||||
|
+ 0x69, 0x30, 0x91, 0xb7, 0x03, 0xef, 0x7f, 0x12,
|
||||||
|
+ 0xe6, 0xb9, 0x78, 0x73, 0xe0, 0xc0, 0x4f, 0xc6,
|
||||||
|
+ 0xd9, 0x43, 0x99, 0x95, 0x0b, 0x4d, 0x58, 0xd3,
|
||||||
|
+ 0x6b, 0x76, 0xb0, 0x6a, 0xcf, 0x68, 0x6d, 0xf0,
|
||||||
|
+ 0xd9, 0xc1, 0x88, 0x43, 0x9d, 0xf9, 0x04, 0xcb,
|
||||||
|
+ 0xc9, 0x82, 0x6c, 0xee, 0xd4, 0x9c, 0xbd, 0x1c,
|
||||||
|
+ 0x4d, 0x54, 0x29, 0x83, 0xa9, 0x5e, 0xaa, 0x10,
|
||||||
|
+ 0xa7, 0xc1, 0x04, 0x29, 0x28, 0x31, 0x3a, 0x79,
|
||||||
|
+ 0x31, 0x32, 0x39, 0x3a, 0x00, 0x82, 0x33, 0xf1,
|
||||||
|
+ 0x91, 0xe3, 0xf2, 0x12, 0x93, 0x5a, 0xed, 0x0c,
|
||||||
|
+ 0x9d, 0xec, 0x67, 0xaa, 0xa7, 0x97, 0x7f, 0x9f,
|
||||||
|
+ 0x5e, 0xef, 0x6a, 0x3e, 0xa4, 0x7f, 0x9b, 0xed,
|
||||||
|
+ 0x65, 0xd7, 0xba, 0x40, 0x6d, 0xe1, 0xde, 0xc1,
|
||||||
|
+ 0x14, 0x4c, 0x9b, 0x28, 0x5c, 0x03, 0x8e, 0x1a,
|
||||||
|
+ 0xd4, 0x1b, 0x80, 0x1b, 0x07, 0xd6, 0x84, 0x04,
|
||||||
|
+ 0x49, 0x6c, 0x1b, 0x08, 0x84, 0x15, 0x54, 0x62,
|
||||||
|
+ 0xca, 0xd5, 0x75, 0xff, 0xc8, 0xb3, 0x81, 0x76,
|
||||||
|
+ 0x82, 0x91, 0x35, 0x80, 0x20, 0x73, 0x2a, 0x21,
|
||||||
|
+ 0xca, 0x22, 0x06, 0xa7, 0x73, 0x99, 0x75, 0x7e,
|
||||||
|
+ 0x5e, 0xa6, 0x09, 0x59, 0x66, 0x2c, 0xcd, 0xb1,
|
||||||
|
+ 0x8d, 0x3b, 0xc0, 0x68, 0xc5, 0x41, 0xa0, 0x9d,
|
||||||
|
+ 0x82, 0x15, 0xc4, 0xdd, 0x47, 0x1c, 0x5b, 0xa9,
|
||||||
|
+ 0x74, 0x18, 0xaf, 0x72, 0x63, 0x6b, 0x0a, 0x4e,
|
||||||
|
+ 0x95, 0x09, 0x7a, 0xb5, 0x4b, 0x98, 0x85, 0xb9,
|
||||||
|
+ 0x6d, 0x9d, 0x3b, 0x73, 0x8c, 0x29, 0x29, 0x29,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Sample DSA signature of message "hello" with sample key. */
|
||||||
|
+static char sig_dump[] = {
|
||||||
|
+ 0x28, 0x37, 0x3a, 0x73, 0x69, 0x67, 0x2d, 0x76,
|
||||||
|
+ 0x61, 0x6c, 0x28, 0x33, 0x3a, 0x64, 0x73, 0x61,
|
||||||
|
+ 0x28, 0x31, 0x3a, 0x72, 0x32, 0x30, 0x3a, 0xb6,
|
||||||
|
+ 0x60, 0x37, 0xef, 0x02, 0x7c, 0x7c, 0x6e, 0x4f,
|
||||||
|
+ 0x66, 0x8c, 0x7c, 0x26, 0x77, 0xd9, 0x33, 0x90,
|
||||||
|
+ 0xba, 0x7c, 0xfb, 0x29, 0x28, 0x31, 0x3a, 0x73,
|
||||||
|
+ 0x32, 0x30, 0x3a, 0x83, 0xc0, 0x84, 0x72, 0xc6,
|
||||||
|
+ 0x1c, 0x85, 0x6f, 0x8b, 0x9b, 0xb0, 0x38, 0x38,
|
||||||
|
+ 0xb2, 0xb6, 0xdf, 0x1c, 0x52, 0x96, 0x1b, 0x29,
|
||||||
|
+ 0x29, 0x29,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+extern gcry_pk_spec_t _gcry_pubkey_spec_dsa;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+dsa_sexp_test (void)
|
||||||
|
+{
|
||||||
|
+ gcry_sexp_t sign_parms, sign_parms_invalid, pubkey, sig;
|
||||||
|
+ int rc;
|
||||||
|
+ grub_size_t errof;
|
||||||
|
+
|
||||||
|
+ rc = _gcry_sexp_build (&sign_parms_invalid, &errof,
|
||||||
|
+ "(data (value \"hi\"))\n");
|
||||||
|
+ grub_test_assert (rc == 0, "sexp build failed");
|
||||||
|
+
|
||||||
|
+ rc = _gcry_sexp_build (&sign_parms, &errof,
|
||||||
|
+ "(data (value \"hello\"))\n");
|
||||||
|
+ grub_test_assert (rc == 0, "sexp build failed");
|
||||||
|
+ rc = _gcry_sexp_new (&pubkey, pubkey_dump, sizeof(pubkey_dump), 0);
|
||||||
|
+ grub_test_assert (rc == 0, "sexp new failed");
|
||||||
|
+ rc = _gcry_sexp_new (&sig, sig_dump, sizeof(sig_dump), 0);
|
||||||
|
+ grub_test_assert (rc == 0, "sexp new failed");
|
||||||
|
+ rc = _gcry_pubkey_spec_dsa.verify (sig, sign_parms, pubkey);
|
||||||
|
+ grub_test_assert (rc == 0, "signature verification failed: %d", rc);
|
||||||
|
+ rc = _gcry_pubkey_spec_dsa.verify (sig, sign_parms_invalid, pubkey);
|
||||||
|
+ grub_test_assert (rc != 0, "signature verification succeded wrongly");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GRUB_FUNCTIONAL_TEST (dsa_sexp_test, dsa_sexp_test);
|
||||||
|
diff --git a/grub-core/tests/rsa_sexp_test.c b/grub-core/tests/rsa_sexp_test.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..6ebba81
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/tests/rsa_sexp_test.c
|
||||||
|
@@ -0,0 +1,101 @@
|
||||||
|
+/*
|
||||||
|
+ * GRUB -- GRand Unified Bootloader
|
||||||
|
+ * Copyright (C) 2025 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/test.h>
|
||||||
|
+#include <grub/crypto.h>
|
||||||
|
+#include <grub/gcrypt/gcrypt.h>
|
||||||
|
+
|
||||||
|
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
+
|
||||||
|
+/* Sample RSA key. */
|
||||||
|
+static char pubkey_dump[] = {
|
||||||
|
+ 0x28, 0x31, 0x30, 0x3a, 0x70, 0x75, 0x62, 0x6c,
|
||||||
|
+ 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x28, 0x33,
|
||||||
|
+ 0x3a, 0x72, 0x73, 0x61, 0x28, 0x31, 0x3a, 0x6e,
|
||||||
|
+ 0x31, 0x32, 0x39, 0x3a, 0x00, 0xe1, 0x35, 0xc1,
|
||||||
|
+ 0x97, 0x90, 0xe8, 0x54, 0xa8, 0x3b, 0x97, 0x05,
|
||||||
|
+ 0xaf, 0x45, 0xaf, 0x67, 0xbf, 0xec, 0x07, 0xbe,
|
||||||
|
+ 0x9b, 0x55, 0x9c, 0x3f, 0x47, 0xae, 0x25, 0xb6,
|
||||||
|
+ 0xe3, 0x23, 0x99, 0x10, 0x5e, 0x17, 0x1a, 0xda,
|
||||||
|
+ 0x33, 0xe6, 0x73, 0x0d, 0x96, 0x9c, 0x5c, 0x25,
|
||||||
|
+ 0x13, 0x5d, 0x49, 0xb9, 0x86, 0xc0, 0xb1, 0x80,
|
||||||
|
+ 0x29, 0x20, 0xb2, 0x91, 0x72, 0x43, 0xcc, 0x2a,
|
||||||
|
+ 0x67, 0xd3, 0x11, 0xe8, 0x7b, 0x21, 0x75, 0xf6,
|
||||||
|
+ 0x1b, 0xc0, 0xb2, 0x01, 0xc8, 0x35, 0xaa, 0xfb,
|
||||||
|
+ 0xa7, 0x29, 0xb4, 0xb9, 0x94, 0x4e, 0x53, 0x49,
|
||||||
|
+ 0x82, 0x74, 0xe9, 0x23, 0x69, 0xa4, 0xf6, 0xdf,
|
||||||
|
+ 0x40, 0x2a, 0x73, 0x01, 0xfa, 0xe7, 0xf8, 0x32,
|
||||||
|
+ 0x6b, 0x57, 0xfe, 0xb9, 0x7d, 0x02, 0xc2, 0xfb,
|
||||||
|
+ 0x7f, 0x99, 0x1f, 0x6e, 0x8d, 0x53, 0x01, 0x56,
|
||||||
|
+ 0xaf, 0x46, 0x62, 0xb3, 0xe0, 0xa8, 0xa6, 0x0a,
|
||||||
|
+ 0x55, 0x2c, 0x4b, 0x85, 0x5b, 0x29, 0x28, 0x31,
|
||||||
|
+ 0x3a, 0x65, 0x33, 0x3a, 0x01, 0x00, 0x01, 0x29,
|
||||||
|
+ 0x29, 0x29,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Sample RSA signature of message "hello" with sample key. */
|
||||||
|
+static char sig_dump[] = {
|
||||||
|
+ 0x28, 0x37, 0x3a, 0x73, 0x69, 0x67, 0x2d, 0x76,
|
||||||
|
+ 0x61, 0x6c, 0x28, 0x33, 0x3a, 0x72, 0x73, 0x61,
|
||||||
|
+ 0x28, 0x31, 0x3a, 0x73, 0x31, 0x32, 0x38, 0x3a,
|
||||||
|
+ 0x5b, 0x2d, 0xeb, 0xa5, 0x4b, 0x8b, 0xd9, 0x92,
|
||||||
|
+ 0x66, 0x57, 0x89, 0xd8, 0x31, 0xc0, 0x0e, 0x53,
|
||||||
|
+ 0xf8, 0x1c, 0x4f, 0xc8, 0x79, 0x67, 0xb9, 0x10,
|
||||||
|
+ 0xe5, 0x63, 0x5f, 0xef, 0xb1, 0x0b, 0x0e, 0x7f,
|
||||||
|
+ 0xed, 0x86, 0x06, 0xa8, 0x05, 0xbf, 0x6b, 0xd1,
|
||||||
|
+ 0x36, 0x41, 0x08, 0x3b, 0xd0, 0xbd, 0xef, 0xb7,
|
||||||
|
+ 0xc2, 0x69, 0xb8, 0xb4, 0x3e, 0x2c, 0xb5, 0x39,
|
||||||
|
+ 0x13, 0x03, 0xca, 0xad, 0x5f, 0xd2, 0x57, 0x23,
|
||||||
|
+ 0x19, 0xdd, 0x71, 0xdd, 0x93, 0xe1, 0x3e, 0x43,
|
||||||
|
+ 0xaf, 0xdd, 0x94, 0x07, 0xf3, 0x78, 0xb3, 0x2a,
|
||||||
|
+ 0x57, 0x24, 0x97, 0x04, 0x58, 0xc1, 0xaf, 0xd3,
|
||||||
|
+ 0xe7, 0xa7, 0x65, 0xd1, 0x23, 0xa3, 0x93, 0x18,
|
||||||
|
+ 0xc7, 0x52, 0x70, 0x53, 0x60, 0x8b, 0x5a, 0x5d,
|
||||||
|
+ 0x6e, 0xf9, 0x83, 0x52, 0x99, 0xbb, 0x0a, 0x53,
|
||||||
|
+ 0x0e, 0x2a, 0x7f, 0x81, 0x52, 0x02, 0x32, 0xa4,
|
||||||
|
+ 0xfc, 0xe0, 0x17, 0x0c, 0x0e, 0x96, 0xbd, 0x01,
|
||||||
|
+ 0x29, 0x29, 0x29,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+rsa_sexp_test (void)
|
||||||
|
+{
|
||||||
|
+ gcry_sexp_t sign_parms, sign_parms_invalid, pubkey, sig;
|
||||||
|
+ int rc;
|
||||||
|
+ grub_size_t errof;
|
||||||
|
+
|
||||||
|
+ rc = _gcry_sexp_build (&sign_parms_invalid, &errof,
|
||||||
|
+ "(data (flags) (value \"hi\"))\n");
|
||||||
|
+ grub_test_assert (rc == 0, "sexp build failed");
|
||||||
|
+
|
||||||
|
+ rc = _gcry_sexp_build (&sign_parms, &errof,
|
||||||
|
+ "(data (flags) (value \"hello\"))\n");
|
||||||
|
+ grub_test_assert (rc == 0, "sexp build failed");
|
||||||
|
+ rc = _gcry_sexp_new (&pubkey, pubkey_dump, sizeof(pubkey_dump), 0);
|
||||||
|
+ grub_test_assert (rc == 0, "sexp new failed");
|
||||||
|
+ rc = _gcry_sexp_new (&sig, sig_dump, sizeof(sig_dump), 0);
|
||||||
|
+ grub_test_assert (rc == 0, "sexp new failed");
|
||||||
|
+ rc = _gcry_pubkey_spec_rsa.verify (sig, sign_parms, pubkey);
|
||||||
|
+ grub_test_assert (rc == 0, "signature verification failed: %d", rc);
|
||||||
|
+ rc = _gcry_pubkey_spec_rsa.verify (sig, sign_parms_invalid, pubkey);
|
||||||
|
+ grub_test_assert (rc != 0, "signature verification succeded wrongly");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+GRUB_FUNCTIONAL_TEST (rsa_sexp_test, rsa_sexp_test);
|
||||||
47
0379-keccak-Disable-acceleration-with-SSE-asm.patch
Normal file
47
0379-keccak-Disable-acceleration-with-SSE-asm.patch
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:12 +0000
|
||||||
|
Subject: [PATCH] keccak: Disable acceleration with SSE asm
|
||||||
|
|
||||||
|
Libgcrypt code assumes that on x64 all SSE registers are fair game.
|
||||||
|
While it's true that CPUs in question support it, we disable it in
|
||||||
|
our compilation options. Disable the offending optimization.
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
.../lib/libgcrypt-patches/02_keccak_sse.patch | 25 ++++++++++++++++++++++
|
||||||
|
1 file changed, 25 insertions(+)
|
||||||
|
create mode 100644 grub-core/lib/libgcrypt-patches/02_keccak_sse.patch
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/libgcrypt-patches/02_keccak_sse.patch b/grub-core/lib/libgcrypt-patches/02_keccak_sse.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..4deda12
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/libgcrypt-patches/02_keccak_sse.patch
|
||||||
|
@@ -0,0 +1,25 @@
|
||||||
|
+commit b0cf06271da5fe20360953a53a47c69da89669cd
|
||||||
|
+Author: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
+Date: Sun Apr 7 03:33:11 2024 +0000
|
||||||
|
+
|
||||||
|
+ keccak: Disable acceleration with SSE asm
|
||||||
|
+
|
||||||
|
+ Libgcrypt code assumes that on x64 all SSE registers are fair game.
|
||||||
|
+ While it's true that CPUs in question support it, we disable it in
|
||||||
|
+ our compilation options. Disable the offending optimization.
|
||||||
|
+
|
||||||
|
+ Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
+
|
||||||
|
+diff --git a/grub-core/lib/libgcrypt/cipher/keccak.c b/grub-core/lib/libgcrypt/cipher/keccak.c
|
||||||
|
+index 11e64b3e7..8b570263b 100644
|
||||||
|
+--- a/grub-core/lib/libgcrypt-grub/cipher/keccak.c
|
||||||
|
++++ b/grub-core/lib/libgcrypt-grub/cipher/keccak.c
|
||||||
|
+@@ -275,7 +275,7 @@ keccak_absorb_lane32bi(u32 *lane, u32 x0, u32 x1)
|
||||||
|
+ /* Construct generic 64-bit implementation. */
|
||||||
|
+ #ifdef USE_64BIT
|
||||||
|
+
|
||||||
|
+-#if __GNUC__ >= 4 && defined(__x86_64__)
|
||||||
|
++#if __GNUC__ >= 4 && defined(__x86_64__) && 0
|
||||||
|
+
|
||||||
|
+ static inline void absorb_lanes64_8(u64 *dst, const byte *in)
|
||||||
|
+ {
|
||||||
79
0380-libgcrypt-Fix-Coverity-warnings.patch
Normal file
79
0380-libgcrypt-Fix-Coverity-warnings.patch
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:13 +0000
|
||||||
|
Subject: [PATCH] libgcrypt: Fix Coverity warnings
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
.../lib/libgcrypt-patches/03_mpiutil_alloc.patch | 18 +++++++++++
|
||||||
|
grub-core/lib/libgcrypt-patches/03_sexp_free.patch | 35 ++++++++++++++++++++++
|
||||||
|
2 files changed, 53 insertions(+)
|
||||||
|
create mode 100644 grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch
|
||||||
|
create mode 100644 grub-core/lib/libgcrypt-patches/03_sexp_free.patch
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch b/grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..42c6b2b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/libgcrypt-patches/03_mpiutil_alloc.patch
|
||||||
|
@@ -0,0 +1,18 @@
|
||||||
|
+mpiutil: Fix NULL pointer dereference in case of failed alloc
|
||||||
|
+
|
||||||
|
+Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
+
|
||||||
|
+diff --git a/grub-core/lib/libgcrypt/mpi/mpiutil.c b/grub-core/lib/libgcrypt/mpi/mpiutil.c
|
||||||
|
+index 3a372374f..dc53db09d 100644
|
||||||
|
+--- a/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c
|
||||||
|
++++ b/grub-core/lib/libgcrypt-grub/mpi/mpiutil.c
|
||||||
|
+@@ -432,6 +432,9 @@ _gcry_mpi_alloc_like( gcry_mpi_t a )
|
||||||
|
+ int n = (a->sign+7)/8;
|
||||||
|
+ void *p = _gcry_is_secure(a->d)? xtrymalloc_secure (n)
|
||||||
|
+ : xtrymalloc (n);
|
||||||
|
++ if ( !p ) {
|
||||||
|
++ _gcry_fatal_error (GPG_ERR_ENOMEM, NULL);
|
||||||
|
++ }
|
||||||
|
+ memcpy( p, a->d, n );
|
||||||
|
+ b = mpi_set_opaque( NULL, p, a->sign );
|
||||||
|
+ }
|
||||||
|
diff --git a/grub-core/lib/libgcrypt-patches/03_sexp_free.patch b/grub-core/lib/libgcrypt-patches/03_sexp_free.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..1c0ffd6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/libgcrypt-patches/03_sexp_free.patch
|
||||||
|
@@ -0,0 +1,35 @@
|
||||||
|
+sexp: Add missing free on error path
|
||||||
|
+
|
||||||
|
+Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
+
|
||||||
|
+diff --git a/grub-core/lib/libgcrypt/src/sexp.c b/grub-core/lib/libgcrypt/src/sexp.c
|
||||||
|
+index d15f1a790..250559f75 100644
|
||||||
|
+--- a/grub-core/lib/libgcrypt-grub/src/sexp.c
|
||||||
|
++++ b/grub-core/lib/libgcrypt-grub/src/sexp.c
|
||||||
|
+@@ -1157,6 +1157,17 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
|
||||||
|
+ } \
|
||||||
|
+ } while (0)
|
||||||
|
+
|
||||||
|
++#define MAKE_SPACE_EXTRA_CLEANUP(n, cleanup) do { \
|
||||||
|
++ gpg_err_code_t _ms_err = make_space (&c, (n)); \
|
||||||
|
++ if (_ms_err) \
|
||||||
|
++ { \
|
||||||
|
++ err = _ms_err; \
|
||||||
|
++ *erroff = p - buffer; \
|
||||||
|
++ cleanup; \
|
||||||
|
++ goto leave; \
|
||||||
|
++ } \
|
||||||
|
++ } while (0)
|
||||||
|
++
|
||||||
|
+ /* The STORE_LEN macro is used to store the length N at buffer P. */
|
||||||
|
+ #define STORE_LEN(p,n) do { \
|
||||||
|
+ DATALEN ashort = (n); \
|
||||||
|
+@@ -1368,7 +1379,7 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
|
||||||
|
+ goto leave;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+- MAKE_SPACE (datalen);
|
||||||
|
++ MAKE_SPACE_EXTRA_CLEANUP (datalen, xfree (b64buf));
|
||||||
|
+ *c.pos++ = ST_DATA;
|
||||||
|
+ STORE_LEN (c.pos, datalen);
|
||||||
|
+ for (i = 0; i < datalen; i++)
|
||||||
40
0381-libgcrypt-Remove-now-unneeded-compilation-flag.patch
Normal file
40
0381-libgcrypt-Remove-now-unneeded-compilation-flag.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:14 +0000
|
||||||
|
Subject: [PATCH] libgcrypt: Remove now unneeded compilation flag
|
||||||
|
|
||||||
|
HAVE_STRTOUL is now defined in stdlib.h. Include it in g10lib.h rather
|
||||||
|
than defining on command line.
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
conf/Makefile.common | 2 +-
|
||||||
|
util/import_gcry.py | 1 +
|
||||||
|
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/conf/Makefile.common b/conf/Makefile.common
|
||||||
|
index c11ab27..5344a08 100644
|
||||||
|
--- a/conf/Makefile.common
|
||||||
|
+++ b/conf/Makefile.common
|
||||||
|
@@ -85,7 +85,7 @@ CFLAGS_POSIX = -fno-builtin
|
||||||
|
CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap
|
||||||
|
|
||||||
|
CFLAGS_GCRY = -Wno-error=sign-compare -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX)
|
||||||
|
-CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -D_GCRYPT_CONFIG_H_INCLUDED=1 -DHAVE_STRTOUL=1 -I$(top_srcdir)/include/grub/gcrypt
|
||||||
|
+CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -D_GCRYPT_CONFIG_H_INCLUDED=1 -I$(top_srcdir)/include/grub/gcrypt
|
||||||
|
|
||||||
|
CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime
|
||||||
|
|
||||||
|
diff --git a/util/import_gcry.py b/util/import_gcry.py
|
||||||
|
index 489356d..1be18cf 100644
|
||||||
|
--- a/util/import_gcry.py
|
||||||
|
+++ b/util/import_gcry.py
|
||||||
|
@@ -617,6 +617,7 @@ for src in sorted (os.listdir (os.path.join (indir, "src"))):
|
||||||
|
if src == "g10lib.h":
|
||||||
|
fw.write("#include <cipher_wrap.h>\n")
|
||||||
|
fw.write("#include <grub/crypto.h>\n")
|
||||||
|
+ fw.write("#include <stdlib.h>\n")
|
||||||
|
fw.write (f.read ().replace ("(printf,f,a)", "(__printf__,f,a)").replace ("#include \"../compat/libcompat.h\"", "").replace("#define N_(a) (a)", ""))
|
||||||
|
f.close ()
|
||||||
|
fw.close ()
|
||||||
90
0382-libgcrypt-Ignore-sign-compare-warnings.patch
Normal file
90
0382-libgcrypt-Ignore-sign-compare-warnings.patch
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:15 +0000
|
||||||
|
Subject: [PATCH] libgcrypt: Ignore sign-compare warnings
|
||||||
|
|
||||||
|
libgcrypt itself is compiled with -Wno-sign-compare. Do the same for consistency.
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
conf/Makefile.common | 2 +-
|
||||||
|
grub-core/Makefile.core.def | 10 +++++-----
|
||||||
|
util/import_gcry.py | 2 +-
|
||||||
|
3 files changed, 7 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/conf/Makefile.common b/conf/Makefile.common
|
||||||
|
index 5344a08..f25abeb 100644
|
||||||
|
--- a/conf/Makefile.common
|
||||||
|
+++ b/conf/Makefile.common
|
||||||
|
@@ -84,7 +84,7 @@ CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-co
|
||||||
|
CFLAGS_POSIX = -fno-builtin
|
||||||
|
CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap
|
||||||
|
|
||||||
|
-CFLAGS_GCRY = -Wno-error=sign-compare -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX)
|
||||||
|
+CFLAGS_GCRY = -Wno-sign-compare -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX)
|
||||||
|
CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -D_GCRYPT_CONFIG_H_INCLUDED=1 -I$(top_srcdir)/include/grub/gcrypt
|
||||||
|
|
||||||
|
CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime
|
||||||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||||
|
index 0b6b996..ba4ed96 100644
|
||||||
|
--- a/grub-core/Makefile.core.def
|
||||||
|
+++ b/grub-core/Makefile.core.def
|
||||||
|
@@ -1012,7 +1012,7 @@ module = {
|
||||||
|
module = {
|
||||||
|
name = pgp;
|
||||||
|
common = commands/pgp.c;
|
||||||
|
- cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls';
|
||||||
|
cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -2219,7 +2219,7 @@ module = {
|
||||||
|
name = dsa_sexp_test;
|
||||||
|
common = tests/dsa_sexp_test.c;
|
||||||
|
|
||||||
|
- cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls';
|
||||||
|
cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -2227,7 +2227,7 @@ module = {
|
||||||
|
name = rsa_sexp_test;
|
||||||
|
common = tests/rsa_sexp_test.c;
|
||||||
|
|
||||||
|
- cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls';
|
||||||
|
cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -2607,7 +2607,7 @@ module = {
|
||||||
|
common = lib/libgcrypt_wrap/mem.c;
|
||||||
|
common = lib/libgcrypt-grub/cipher/md.c;
|
||||||
|
|
||||||
|
- cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare -Wno-unused-but-set-variable';
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-unused-but-set-variable';
|
||||||
|
cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -2619,7 +2619,7 @@ module = {
|
||||||
|
common = lib/libgcrypt-grub/src/sexp.c;
|
||||||
|
common = lib/b64dec.c;
|
||||||
|
|
||||||
|
- cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';
|
||||||
|
+ cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls';
|
||||||
|
cppflags = '$(CPPFLAGS_GCRY)';
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/util/import_gcry.py b/util/import_gcry.py
|
||||||
|
index 1be18cf..a4411ec 100644
|
||||||
|
--- a/util/import_gcry.py
|
||||||
|
+++ b/util/import_gcry.py
|
||||||
|
@@ -551,7 +551,7 @@ for cipher_file in cipher_files:
|
||||||
|
confutil.write (" common = grub-core/lib/libgcrypt-grub/cipher/%s;\n" % src)
|
||||||
|
if modname == "gcry_ecc":
|
||||||
|
conf.write (" common = lib/libgcrypt-grub/mpi/ec.c;\n")
|
||||||
|
- conf.write (" cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare';\n")
|
||||||
|
+ conf.write (" cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls';\n")
|
||||||
|
elif modname == "gcry_rijndael" or modname == "gcry_md4" or modname == "gcry_md5" or modname == "gcry_rmd160" or modname == "gcry_sha1" or modname == "gcry_sha256" or modname == "gcry_sha512" or modname == "gcry_tiger":
|
||||||
|
# Alignment checked by hand
|
||||||
|
conf.write (" cflags = '$(CFLAGS_GCRY) -Wno-cast-align';\n");
|
||||||
217
0383-libgcrypt-Import-blake-family-of-hashes.patch
Normal file
217
0383-libgcrypt-Import-blake-family-of-hashes.patch
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:16 +0000
|
||||||
|
Subject: [PATCH] libgcrypt: Import blake family of hashes
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/lib/libgcrypt-patches/06_blake.patch | 80 ++++++++++++++++++++++++++
|
||||||
|
include/grub/crypto.h | 9 +++
|
||||||
|
util/import_gcry.py | 36 +++++++++---
|
||||||
|
3 files changed, 118 insertions(+), 7 deletions(-)
|
||||||
|
create mode 100644 grub-core/lib/libgcrypt-patches/06_blake.patch
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/libgcrypt-patches/06_blake.patch b/grub-core/lib/libgcrypt-patches/06_blake.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..c3b9d6f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/libgcrypt-patches/06_blake.patch
|
||||||
|
@@ -0,0 +1,80 @@
|
||||||
|
+--- a/grub-core/lib/libgcrypt-grub/cipher/blake2.c
|
||||||
|
++++ b/grub-core/lib/libgcrypt-grub/cipher/blake2.c
|
||||||
|
+@@ -841,68 +841,6 @@
|
||||||
|
+ return blake2s_init(c, key, keylen);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+-/* Selftests from "RFC 7693, Appendix E. BLAKE2b and BLAKE2s Self-Test
|
||||||
|
+- * Module C Source". */
|
||||||
|
+-static void selftest_seq(byte *out, size_t len, u32 seed)
|
||||||
|
+-{
|
||||||
|
+- size_t i;
|
||||||
|
+- u32 t, a, b;
|
||||||
|
+-
|
||||||
|
+- a = 0xDEAD4BAD * seed;
|
||||||
|
+- b = 1;
|
||||||
|
+-
|
||||||
|
+- for (i = 0; i < len; i++)
|
||||||
|
+- {
|
||||||
|
+- t = a + b;
|
||||||
|
+- a = b;
|
||||||
|
+- b = t;
|
||||||
|
+- out[i] = (t >> 24) & 0xFF;
|
||||||
|
+- }
|
||||||
|
+-}
|
||||||
|
+-
|
||||||
|
+-
|
||||||
|
+-
|
||||||
|
+-
|
||||||
|
+-gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags,
|
||||||
|
+- const unsigned char *key,
|
||||||
|
+- size_t keylen, int algo)
|
||||||
|
+-{
|
||||||
|
+- gcry_err_code_t rc;
|
||||||
|
+- switch (algo)
|
||||||
|
+- {
|
||||||
|
+- case GCRY_MD_BLAKE2B_512:
|
||||||
|
+- rc = blake2b_init_ctx (ctx, flags, key, keylen, 512);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2B_384:
|
||||||
|
+- rc = blake2b_init_ctx (ctx, flags, key, keylen, 384);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2B_256:
|
||||||
|
+- rc = blake2b_init_ctx (ctx, flags, key, keylen, 256);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2B_160:
|
||||||
|
+- rc = blake2b_init_ctx (ctx, flags, key, keylen, 160);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2S_256:
|
||||||
|
+- rc = blake2s_init_ctx (ctx, flags, key, keylen, 256);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2S_224:
|
||||||
|
+- rc = blake2s_init_ctx (ctx, flags, key, keylen, 224);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2S_160:
|
||||||
|
+- rc = blake2s_init_ctx (ctx, flags, key, keylen, 160);
|
||||||
|
+- break;
|
||||||
|
+- case GCRY_MD_BLAKE2S_128:
|
||||||
|
+- rc = blake2s_init_ctx (ctx, flags, key, keylen, 128);
|
||||||
|
+- break;
|
||||||
|
+- default:
|
||||||
|
+- rc = GPG_ERR_DIGEST_ALGO;
|
||||||
|
+- break;
|
||||||
|
+- }
|
||||||
|
+-
|
||||||
|
+- return rc;
|
||||||
|
+-}
|
||||||
|
+-
|
||||||
|
+-
|
||||||
|
+ #define DEFINE_BLAKE2_VARIANT(bs, BS, dbits, oid_branch) \
|
||||||
|
+ static void blake2##bs##_##dbits##_init(void *ctx, unsigned int flags) \
|
||||||
|
+ { \
|
||||||
|
+@@ -936,7 +874,7 @@
|
||||||
|
+ dbits / 8, blake2##bs##_##dbits##_init, blake2##bs##_write, \
|
||||||
|
+ blake2##bs##_final, blake2##bs##_read, NULL, \
|
||||||
|
+ _gcry_blake2##bs##_##dbits##_hash_buffers, \
|
||||||
|
+- sizeof (BLAKE2##BS##_CONTEXT), selftests_blake2##bs \
|
||||||
|
++ sizeof (BLAKE2##BS##_CONTEXT) \
|
||||||
|
+ , \
|
||||||
|
+ GRUB_UTIL_MODNAME("gcry_blake2") \
|
||||||
|
+ .blocksize = GRUB_BLAKE2 ## BS ## _BLOCK_SIZE \
|
||||||
|
diff --git a/include/grub/crypto.h b/include/grub/crypto.h
|
||||||
|
index 25b1188..b0d7add 100644
|
||||||
|
--- a/include/grub/crypto.h
|
||||||
|
+++ b/include/grub/crypto.h
|
||||||
|
@@ -586,8 +586,14 @@ void grub_gcry_fini_all (void);
|
||||||
|
int
|
||||||
|
grub_get_random (void *out, grub_size_t len);
|
||||||
|
|
||||||
|
+#define GRUB_UTIL_MODNAME(x) .modname = x,
|
||||||
|
+#else
|
||||||
|
+#define GRUB_UTIL_MODNAME(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#define GRUB_BLAKE2B_BLOCK_SIZE 128
|
||||||
|
+#define GRUB_BLAKE2S_BLOCK_SIZE 64
|
||||||
|
+
|
||||||
|
typedef struct _gpgrt_b64state *gpgrt_b64state_t;
|
||||||
|
gpgrt_b64state_t gpgrt_b64dec_start (const char *title);
|
||||||
|
gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state,
|
||||||
|
@@ -595,4 +601,7 @@ gpg_error_t gpgrt_b64dec_proc (gpgrt_b64state_t state,
|
||||||
|
grub_size_t *r_nbytes);
|
||||||
|
gpg_error_t gpgrt_b64dec_finish (gpgrt_b64state_t state);
|
||||||
|
const char *gpg_strerror (gpg_error_t err);
|
||||||
|
+
|
||||||
|
+gcry_err_code_t blake2b_vl_hash (const void *in, grub_size_t inlen,
|
||||||
|
+ grub_size_t outputlen, void *output);
|
||||||
|
#endif
|
||||||
|
diff --git a/util/import_gcry.py b/util/import_gcry.py
|
||||||
|
index a4411ec..ca918c7 100644
|
||||||
|
--- a/util/import_gcry.py
|
||||||
|
+++ b/util/import_gcry.py
|
||||||
|
@@ -120,7 +120,8 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
|
||||||
|
"_gcry_digest_spec_gost3411_94": 32,
|
||||||
|
"_gcry_digest_spec_gost3411_cp": 32,
|
||||||
|
"_gcry_digest_spec_cshake128": 64,
|
||||||
|
- "_gcry_digest_spec_cshake256": 64}
|
||||||
|
+ "_gcry_digest_spec_cshake256": 64,
|
||||||
|
+ "_gcry_digest_spec_blake2": "GRUB_BLAKE2 ## BS ## _BLOCK_SIZE"}
|
||||||
|
|
||||||
|
cryptolist = codecs.open (os.path.join (cipher_dir_out, "crypto.lst"), "w", "utf-8")
|
||||||
|
|
||||||
|
@@ -209,6 +210,7 @@ for cipher_file in cipher_files:
|
||||||
|
skip = 0
|
||||||
|
skip2 = False
|
||||||
|
ismd = False
|
||||||
|
+ ismddefine = False
|
||||||
|
mdarg = 0
|
||||||
|
ispk = False
|
||||||
|
iscipher = False
|
||||||
|
@@ -245,19 +247,19 @@ for cipher_file in cipher_files:
|
||||||
|
mdarg = mdarg + len (spl) - 1
|
||||||
|
if ismd or iscipher or ispk:
|
||||||
|
if not re.search (" *};", line) is None:
|
||||||
|
+ escapenl = " \\" if ismddefine else ""
|
||||||
|
if not iscomma:
|
||||||
|
- fw.write (" ,\n")
|
||||||
|
- fw.write ("#ifdef GRUB_UTIL\n");
|
||||||
|
- fw.write (" .modname = \"%s\",\n" % modname);
|
||||||
|
- fw.write ("#endif\n");
|
||||||
|
+ fw.write (f" ,{escapenl}\n")
|
||||||
|
+ fw.write (f" GRUB_UTIL_MODNAME(\"%s\"){escapenl}\n" % modname);
|
||||||
|
if ismd:
|
||||||
|
if not (mdname in mdblocksizes):
|
||||||
|
print ("ERROR: Unknown digest blocksize: %s\n"
|
||||||
|
% mdname)
|
||||||
|
exit (1)
|
||||||
|
- fw.write (" .blocksize = %s\n"
|
||||||
|
+ fw.write (f" .blocksize = %s{escapenl}\n"
|
||||||
|
% mdblocksizes [mdname])
|
||||||
|
ismd = False
|
||||||
|
+ ismddefine = False
|
||||||
|
mdarg = 0
|
||||||
|
iscipher = False
|
||||||
|
ispk = False
|
||||||
|
@@ -281,7 +283,7 @@ for cipher_file in cipher_files:
|
||||||
|
hold = False
|
||||||
|
# We're optimising for size and exclude anything needing good
|
||||||
|
# randomness.
|
||||||
|
- if re.match ("(_gcry_hash_selftest_check_one|bulk_selftest_setkey|run_selftests|do_tripledes_set_extra_info|selftest|sm4_selftest|_gcry_[a-z0-9_]*_hash_buffers|_gcry_sha1_hash_buffer|tripledes_set2keys|_gcry_rmd160_mixblock|serpent_test|dsa_generate_ext|test_keys|gen_k|sign|gen_x931_parm_xp|generate_x931|generate_key|dsa_generate|dsa_sign|ecc_sign|generate|generate_fips186|_gcry_register_pk_dsa_progress|_gcry_register_pk_ecc_progress|progress|scanval|ec2os|ecc_generate_ext|ecc_generate|ecc_get_param|_gcry_register_pk_dsa_progress|gen_x931_parm_xp|gen_x931_parm_xi|rsa_decrypt|rsa_sign|rsa_generate_ext|rsa_generate|secret|check_exponent|rsa_blind|rsa_unblind|extract_a_from_sexp|curve_free|curve_copy|point_set|_gcry_dsa_gen_rfc6979_k|bits2octets|int2octets|_gcry_md_debug|_gcry_md_selftest|_gcry_md_is_enabled|_gcry_md_is_secure|_gcry_md_init|_gcry_md_info|md_get_algo|md_extract|_gcry_md_get |_gcry_md_get_algo |_gcry_md_extract|_gcry_md_setkey|md_setkey|prepare_macpads|_gcry_md_algo_name|search_oid|spec_from_oid|spec_from_name|spec_from_algo|map_algo|cshake_hash_buffers)", line) is not None:
|
||||||
|
+ if re.match ("(_gcry_hash_selftest_check_one|bulk_selftest_setkey|run_selftests|do_tripledes_set_extra_info|selftest|sm4_selftest|_gcry_[a-z0-9_]*_hash_buffers|_gcry_sha1_hash_buffer|tripledes_set2keys|_gcry_rmd160_mixblock|serpent_test|dsa_generate_ext|test_keys|gen_k|sign|gen_x931_parm_xp|generate_x931|generate_key|dsa_generate|dsa_sign|ecc_sign|generate|generate_fips186|_gcry_register_pk_dsa_progress|_gcry_register_pk_ecc_progress|progress|scanval|ec2os|ecc_generate_ext|ecc_generate|ecc_get_param|_gcry_register_pk_dsa_progress|gen_x931_parm_xp|gen_x931_parm_xi|rsa_decrypt|rsa_sign|rsa_generate_ext|rsa_generate|secret|check_exponent|rsa_blind|rsa_unblind|extract_a_from_sexp|curve_free|curve_copy|point_set|_gcry_dsa_gen_rfc6979_k|bits2octets|int2octets|_gcry_md_debug|_gcry_md_selftest|_gcry_md_is_enabled|_gcry_md_is_secure|_gcry_md_init|_gcry_md_info|md_get_algo|md_extract|_gcry_md_get |_gcry_md_get_algo |_gcry_md_extract|_gcry_md_setkey|md_setkey|prepare_macpads|_gcry_md_algo_name|search_oid|spec_from_oid|spec_from_name|spec_from_algo|map_algo|cshake_hash_buffers|selftest_seq)", line) is not None:
|
||||||
|
|
||||||
|
skip = 1
|
||||||
|
if not re.match ("selftest", line) is None and cipher_file == "idea.c":
|
||||||
|
@@ -355,6 +357,13 @@ for cipher_file in cipher_files:
|
||||||
|
ispk = True
|
||||||
|
iscryptostart = True
|
||||||
|
|
||||||
|
+ m = re.match (r"DEFINE_BLAKE2_VARIANT\((.), (.), ([0-9]*)", line)
|
||||||
|
+ if isc and not m is None:
|
||||||
|
+ bs = m.groups()[0]
|
||||||
|
+ bits = m.groups()[2]
|
||||||
|
+ mdname = f"_gcry_digest_spec_blake2{bs}_{bits}"
|
||||||
|
+ mdnames.append (mdname)
|
||||||
|
+
|
||||||
|
m = re.match ("(const )?gcry_md_spec_t", line)
|
||||||
|
if isc and not m is None:
|
||||||
|
assert (not ismd)
|
||||||
|
@@ -366,6 +375,19 @@ for cipher_file in cipher_files:
|
||||||
|
mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
|
||||||
|
mdnames.append (mdname)
|
||||||
|
ismd = True
|
||||||
|
+ ismddefine = False
|
||||||
|
+ mdarg = 0
|
||||||
|
+ iscryptostart = True
|
||||||
|
+ m = re.match (" (const )?gcry_md_spec_t _gcry_digest_spec_blake2.*\\\\", line)
|
||||||
|
+ if isc and not m is None:
|
||||||
|
+ assert (not ismd)
|
||||||
|
+ assert (not ispk)
|
||||||
|
+ assert (not iscipher)
|
||||||
|
+ assert (not iscryptostart)
|
||||||
|
+ line = removeprefix(line, " const ")
|
||||||
|
+ ismd = True
|
||||||
|
+ ismddefine = True
|
||||||
|
+ mdname = "_gcry_digest_spec_blake2"
|
||||||
|
mdarg = 0
|
||||||
|
iscryptostart = True
|
||||||
|
m = re.match (r"static const char \*selftest.*;$", line)
|
||||||
44
0384-util-import_gcry-Make-compatible-with-Python-3.4.patch
Normal file
44
0384-util-import_gcry-Make-compatible-with-Python-3.4.patch
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:17 +0000
|
||||||
|
Subject: [PATCH] util/import_gcry: Make compatible with Python 3.4
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
util/import_gcry.py | 10 +++++-----
|
||||||
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/util/import_gcry.py b/util/import_gcry.py
|
||||||
|
index ca918c7..9b0e8d9 100644
|
||||||
|
--- a/util/import_gcry.py
|
||||||
|
+++ b/util/import_gcry.py
|
||||||
|
@@ -249,15 +249,15 @@ for cipher_file in cipher_files:
|
||||||
|
if not re.search (" *};", line) is None:
|
||||||
|
escapenl = " \\" if ismddefine else ""
|
||||||
|
if not iscomma:
|
||||||
|
- fw.write (f" ,{escapenl}\n")
|
||||||
|
- fw.write (f" GRUB_UTIL_MODNAME(\"%s\"){escapenl}\n" % modname);
|
||||||
|
+ fw.write (" ,%s\n" % escapenl)
|
||||||
|
+ fw.write (" GRUB_UTIL_MODNAME(\"%s\")%s\n" % (modname, escapenl))
|
||||||
|
if ismd:
|
||||||
|
if not (mdname in mdblocksizes):
|
||||||
|
print ("ERROR: Unknown digest blocksize: %s\n"
|
||||||
|
% mdname)
|
||||||
|
exit (1)
|
||||||
|
- fw.write (f" .blocksize = %s{escapenl}\n"
|
||||||
|
- % mdblocksizes [mdname])
|
||||||
|
+ fw.write (" .blocksize = %s%s\n"
|
||||||
|
+ % (mdblocksizes [mdname], escapenl))
|
||||||
|
ismd = False
|
||||||
|
ismddefine = False
|
||||||
|
mdarg = 0
|
||||||
|
@@ -361,7 +361,7 @@ for cipher_file in cipher_files:
|
||||||
|
if isc and not m is None:
|
||||||
|
bs = m.groups()[0]
|
||||||
|
bits = m.groups()[2]
|
||||||
|
- mdname = f"_gcry_digest_spec_blake2{bs}_{bits}"
|
||||||
|
+ mdname = "_gcry_digest_spec_blake2%s_%s" % (bs, bits)
|
||||||
|
mdnames.append (mdname)
|
||||||
|
|
||||||
|
m = re.match ("(const )?gcry_md_spec_t", line)
|
||||||
1324
0385-util-import_gcry-Fix-pylint-warnings.patch
Normal file
1324
0385-util-import_gcry-Fix-pylint-warnings.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:19 +0000
|
||||||
|
Subject: [PATCH] libgcrypt: Don't use 64-bit division on platforms where it's
|
||||||
|
slow
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/lib/libgcrypt-patches/07_disable_64div.patch | 15 +++++++++++++++
|
||||||
|
1 file changed, 15 insertions(+)
|
||||||
|
create mode 100644 grub-core/lib/libgcrypt-patches/07_disable_64div.patch
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/libgcrypt-patches/07_disable_64div.patch b/grub-core/lib/libgcrypt-patches/07_disable_64div.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..bb47bdf
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/libgcrypt-patches/07_disable_64div.patch
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+Don't use 64-bit division on platforms where it's slow
|
||||||
|
+
|
||||||
|
+diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h
|
||||||
|
+index 21bd1a7ef..672448724 100644
|
||||||
|
+--- a/grub-core/lib/libgcrypt-grub/mpi/longlong.h
|
||||||
|
++++ b/grub-core/lib/libgcrypt-grub/mpi/longlong.h
|
||||||
|
+@@ -1711,7 +1711,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
|
||||||
|
+ } while (0)
|
||||||
|
+
|
||||||
|
+ /* Use double word type if available. */
|
||||||
|
+-#if !defined (udiv_qrnnd) && defined (UDWtype)
|
||||||
|
++#if !defined (udiv_qrnnd) && defined (UDWtype) && !defined(__arm__) && !defined(__mips__) && !defined(__powerpc__)
|
||||||
|
+ # define udiv_qrnnd(q, r, nh, nl, d) \
|
||||||
|
+ do { \
|
||||||
|
+ UWtype __d = (d); \
|
||||||
41
0387-libgcrypt-Fix-a-memory-leak.patch
Normal file
41
0387-libgcrypt-Fix-a-memory-leak.patch
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:20 +0000
|
||||||
|
Subject: [PATCH] libgcrypt: Fix a memory leak
|
||||||
|
|
||||||
|
Fixes: CID 468917
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/lib/libgcrypt-patches/08_sexp_leak.patch | 21 +++++++++++++++++++++
|
||||||
|
1 file changed, 21 insertions(+)
|
||||||
|
create mode 100644 grub-core/lib/libgcrypt-patches/08_sexp_leak.patch
|
||||||
|
|
||||||
|
diff --git a/grub-core/lib/libgcrypt-patches/08_sexp_leak.patch b/grub-core/lib/libgcrypt-patches/08_sexp_leak.patch
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..eefd031
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/lib/libgcrypt-patches/08_sexp_leak.patch
|
||||||
|
@@ -0,0 +1,21 @@
|
||||||
|
+sexp: Fix a memory leak
|
||||||
|
+
|
||||||
|
+Fixes: CID 468917
|
||||||
|
+
|
||||||
|
+Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
+
|
||||||
|
+diff -ur ../libgcrypt-1.11.0/src/sexp.c grub-core/lib/libgcrypt/src/sexp.c
|
||||||
|
+--- a/grub-core/lib/libgcrypt-grub/src/sexp.c 2024-03-28 10:07:27.000000000 +0000
|
||||||
|
++++ b/grub-core/lib/libgcrypt-grub/src/sexp.c 2025-07-02 17:10:32.714864459 +0000
|
||||||
|
+@@ -2725,8 +2725,10 @@
|
||||||
|
+ length = 0;
|
||||||
|
+ for (s=string; *s; s +=2 )
|
||||||
|
+ {
|
||||||
|
+- if (!hexdigitp (s) || !hexdigitp (s+1))
|
||||||
|
++ if (!hexdigitp (s) || !hexdigitp (s+1)) {
|
||||||
|
++ free (buffer);
|
||||||
|
+ return NULL; /* Invalid hex digits. */
|
||||||
|
++ }
|
||||||
|
+ ((unsigned char*)buffer)[length++] = xtoi_2 (s);
|
||||||
|
+ }
|
||||||
|
+ *r_length = length;
|
||||||
67
0388-docs-Write-how-to-import-new-libgcrypt.patch
Normal file
67
0388-docs-Write-how-to-import-new-libgcrypt.patch
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Date: Mon, 7 Jul 2025 14:52:21 +0000
|
||||||
|
Subject: [PATCH] docs: Write how to import new libgcrypt
|
||||||
|
|
||||||
|
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
docs/grub-dev.texi | 38 ++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 38 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi
|
||||||
|
index 8ad5494..090cc88 100644
|
||||||
|
--- a/docs/grub-dev.texi
|
||||||
|
+++ b/docs/grub-dev.texi
|
||||||
|
@@ -506,6 +506,7 @@ to update it.
|
||||||
|
* Gnulib::
|
||||||
|
* jsmn::
|
||||||
|
* minilzo::
|
||||||
|
+* libgcrypt::
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@node Gnulib
|
||||||
|
@@ -596,6 +597,43 @@ cp minilzo-2.10/*.[hc] grub-core/lib/minilzo
|
||||||
|
rm -r minilzo-2.10*
|
||||||
|
@end example
|
||||||
|
|
||||||
|
+@node libgcrypt
|
||||||
|
+@section libgcrypt
|
||||||
|
+
|
||||||
|
+libgcrypt is a GNU implementation of crypto library. To import a new version
|
||||||
|
+you need to unpack the release tarball into grub-core/lib/libgcrypt. Delete
|
||||||
|
+following files/directories:
|
||||||
|
+* acinclude.m4
|
||||||
|
+* aclocal.m4
|
||||||
|
+* autogen.rc
|
||||||
|
+* autogen.sh
|
||||||
|
+* build-aux
|
||||||
|
+* ChangeLog
|
||||||
|
+* ChangeLog-2011
|
||||||
|
+* doc
|
||||||
|
+* INSTALL
|
||||||
|
+* m4
|
||||||
|
+* Makefile.am
|
||||||
|
+* Makefile.in
|
||||||
|
+* NEWS
|
||||||
|
+* random
|
||||||
|
+* tests
|
||||||
|
+* TODO
|
||||||
|
+* */Makefile.in
|
||||||
|
+* mpi/hppa1.1
|
||||||
|
+
|
||||||
|
+Regenerate the file gost-sb.h:
|
||||||
|
+grub-core/lib/libgcrypt/cipher$ gcc -o gost-s-box gost-s-box.c
|
||||||
|
+grub-core/lib/libgcrypt/cipher$ ./gost-s-box gost-sb.h
|
||||||
|
+
|
||||||
|
+Then rerun ./bootstrap and pay attention to the errors. Especially to warnings
|
||||||
|
+that a file isn't a module as it means that some file is actually unused by
|
||||||
|
+GRUB. If any, find where it declares its cipher or hash and add a pattern to
|
||||||
|
+import_gcry.py. See commit ``libgcrypt: Import blake family of hashes'' for an
|
||||||
|
+example. If file reallly is useless to GRUB in its current state, add it to
|
||||||
|
+whitelist in import_gcry.py.
|
||||||
|
+Compile and fix any new errors. Put patches into grub-core/lib/libgcrypt-patches
|
||||||
|
+
|
||||||
|
@node Debugging
|
||||||
|
@chapter Debugging
|
||||||
|
|
||||||
36
0389-pgp-Rename-OBJ_TYPE_PUBKEY-to-OBJ_TYPE_GPG_PUBKEY.patch
Normal file
36
0389-pgp-Rename-OBJ_TYPE_PUBKEY-to-OBJ_TYPE_GPG_PUBKEY.patch
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:48 +0530
|
||||||
|
Subject: [PATCH] pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY
|
||||||
|
|
||||||
|
Prior to the addition of the X.509 public key support for appended signature,
|
||||||
|
current PGP signature relied on the GPG public key. Changing the enum name
|
||||||
|
from "OBJ_TYPE_PUBKEY" to "OBJ_TYPE_GPG_PUBKEY" to differentiate between x509
|
||||||
|
certificate based appended signature and GPG certificate based PGP signature.
|
||||||
|
|
||||||
|
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
include/grub/kernel.h | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
|
||||||
|
index f98a780..8fdbde2 100644
|
||||||
|
--- a/include/grub/kernel.h
|
||||||
|
+++ b/include/grub/kernel.h
|
||||||
|
@@ -28,10 +28,9 @@ enum
|
||||||
|
OBJ_TYPE_MEMDISK,
|
||||||
|
OBJ_TYPE_CONFIG,
|
||||||
|
OBJ_TYPE_PREFIX,
|
||||||
|
- OBJ_TYPE_PUBKEY,
|
||||||
|
+ OBJ_TYPE_GPG_PUBKEY,
|
||||||
|
OBJ_TYPE_DTB,
|
||||||
|
OBJ_TYPE_DISABLE_SHIM_LOCK,
|
||||||
|
- OBJ_TYPE_GPG_PUBKEY,
|
||||||
|
OBJ_TYPE_X509_PUBKEY,
|
||||||
|
OBJ_TYPE_DISABLE_CLI
|
||||||
|
};
|
||||||
210
0390-grub-install-Support-embedding-x509-certificates.patch
Normal file
210
0390-grub-install-Support-embedding-x509-certificates.patch
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:49 +0530
|
||||||
|
Subject: [PATCH] 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 <alastair@d-silva.org>
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
include/grub/kernel.h | 2 +-
|
||||||
|
include/grub/util/install.h | 9 ++++-----
|
||||||
|
util/grub-install-common.c | 18 ++++++++----------
|
||||||
|
util/grub-mkimage.c | 6 +++---
|
||||||
|
util/mkimage.c | 38 +++++++++++++++++++++-----------------
|
||||||
|
5 files changed, 37 insertions(+), 36 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
|
||||||
|
index 8fdbde2b0613..05f141201c61 100644
|
||||||
|
--- a/include/grub/kernel.h
|
||||||
|
+++ b/include/grub/kernel.h
|
||||||
|
@@ -29,9 +29,9 @@ enum
|
||||||
|
OBJ_TYPE_CONFIG,
|
||||||
|
OBJ_TYPE_PREFIX,
|
||||||
|
OBJ_TYPE_GPG_PUBKEY,
|
||||||
|
+ OBJ_TYPE_X509_PUBKEY,
|
||||||
|
OBJ_TYPE_DTB,
|
||||||
|
OBJ_TYPE_DISABLE_SHIM_LOCK,
|
||||||
|
- OBJ_TYPE_X509_PUBKEY,
|
||||||
|
OBJ_TYPE_DISABLE_CLI
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
|
||||||
|
index dbf3c216d413..93c1f0ed4e0d 100644
|
||||||
|
--- a/include/grub/util/install.h
|
||||||
|
+++ b/include/grub/util/install.h
|
||||||
|
@@ -67,13 +67,12 @@
|
||||||
|
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}, \
|
||||||
|
{ "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
|
||||||
|
N_("disabled command line interface access"), 0 }, \
|
||||||
|
+ { "x509key", 'x', N_("FILE"), 0, \
|
||||||
|
+ N_("embed FILE as an x509 certificate for appended signature checking"), 0}, \
|
||||||
|
+ { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE, \
|
||||||
|
+ "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 1}, \
|
||||||
|
{ "verbose", 'v', 0, 0, \
|
||||||
|
N_("print verbose messages."), 1 }
|
||||||
|
|
||||||
|
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
|
||||||
|
index 42aec141e444..41251cee798b 100644
|
||||||
|
--- a/util/grub-install-common.c
|
||||||
|
+++ b/util/grub-install-common.c
|
||||||
|
@@ -463,10 +463,10 @@ handle_install_list (struct install_list *il, const char *val,
|
||||||
|
|
||||||
|
static char **pubkeys;
|
||||||
|
static size_t npubkeys;
|
||||||
|
-static char *sbat;
|
||||||
|
-static int disable_shim_lock;
|
||||||
|
static char **x509keys;
|
||||||
|
static size_t nx509keys;
|
||||||
|
+static char *sbat;
|
||||||
|
+static int disable_shim_lock;
|
||||||
|
static grub_compression_t compression;
|
||||||
|
static size_t appsig_size;
|
||||||
|
static int disable_cli;
|
||||||
|
@@ -509,15 +509,13 @@ 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_DISABLE_CLI:
|
||||||
|
disable_cli = 1;
|
||||||
|
return 1;
|
||||||
|
+ case 'x':
|
||||||
|
+ x509keys = xrealloc (x509keys, sizeof (x509keys[0]) * (nx509keys + 1));
|
||||||
|
+ x509keys[nx509keys++] = xstrdup (arg);
|
||||||
|
+ return 1;
|
||||||
|
|
||||||
|
case GRUB_INSTALL_OPTIONS_VERBOSITY:
|
||||||
|
verbosity++;
|
||||||
|
@@ -649,7 +647,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
|
||||||
|
slen += sizeof (" --pubkey ''") + grub_strlen (*pk);
|
||||||
|
|
||||||
|
for (pk = x509keys; pk < x509keys + nx509keys; pk++)
|
||||||
|
- slen += 10 + grub_strlen (*pk);
|
||||||
|
+ slen += sizeof (" --x509key ''") + grub_strlen (*pk);
|
||||||
|
|
||||||
|
for (md = modules.entries; *md; md++)
|
||||||
|
slen += sizeof (" ''") + grub_strlen (*md);
|
||||||
|
@@ -693,7 +691,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
|
||||||
|
|
||||||
|
for (pk = x509keys; pk < x509keys + nx509keys; pk++)
|
||||||
|
{
|
||||||
|
- p = grub_stpcpy (p, "--x509 '");
|
||||||
|
+ p = grub_stpcpy (p, "--x509key '");
|
||||||
|
p = grub_stpcpy (p, *pk);
|
||||||
|
*p++ = '\'';
|
||||||
|
*p++ = ' ';
|
||||||
|
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
|
||||||
|
index 13bdc6cf0397..89ca81ce6b10 100644
|
||||||
|
--- a/util/grub-mkimage.c
|
||||||
|
+++ b/util/grub-mkimage.c
|
||||||
|
@@ -76,7 +76,7 @@ static struct argp_option options[] = {
|
||||||
|
{"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 PGP signature checking"), 0},
|
||||||
|
- {"x509", 'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for appended signature checking"), 0},
|
||||||
|
+ {"x509key", '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},
|
||||||
|
@@ -213,11 +213,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
arguments->x509keys = xrealloc (arguments->x509keys,
|
||||||
|
- sizeof (arguments->x509keys[0])
|
||||||
|
- * (arguments->nx509keys + 1));
|
||||||
|
+ sizeof (arguments->x509keys[0]) * (arguments->nx509keys + 1));
|
||||||
|
arguments->x509keys[arguments->nx509keys++] = xstrdup (arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
+
|
||||||
|
case 'c':
|
||||||
|
if (arguments->config)
|
||||||
|
free (arguments->config);
|
||||||
|
diff --git a/util/mkimage.c b/util/mkimage.c
|
||||||
|
index f92949d1df25..8ae58ccef868 100644
|
||||||
|
--- a/util/mkimage.c
|
||||||
|
+++ b/util/mkimage.c
|
||||||
|
@@ -930,16 +930,21 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (nx509keys != 0 && image_target->id != IMAGE_PPC)
|
||||||
|
+ grub_util_error (_("x509 public key can be support only to appended signature"
|
||||||
|
+ " with powerpc-ieee1275 images"));
|
||||||
|
+
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
+ 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1078,24 +1083,23 @@ 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;
|
||||||
|
+ size_t curs;
|
||||||
|
+ struct grub_module_header *header;
|
||||||
|
|
||||||
|
- curs = grub_util_get_image_size (x509key_paths[i]);
|
||||||
|
+ 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));
|
||||||
|
|
||||||
|
- 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);
|
||||||
|
+ 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;
|
||||||
162
0391-appended-signatures-Import-GNUTLS-s-ASN.1-descriptio.patch
Normal file
162
0391-appended-signatures-Import-GNUTLS-s-ASN.1-descriptio.patch
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Tue, 18 Nov 2025 16:14:23 +0100
|
||||||
|
Subject: [PATCH] appended signatures: Import GNUTLS's ASN.1 description files
|
||||||
|
|
||||||
|
In order to parse PKCS#7 messages and X.509 certificates with libtasn1, we need
|
||||||
|
some information about how they are encoded. We get these from GNUTLS, which has
|
||||||
|
the benefit that they support the features we need and are well tested.
|
||||||
|
|
||||||
|
The GNUTLS files are from:
|
||||||
|
|
||||||
|
- https://github.com/gnutls/gnutls/blob/master/lib/gnutls.asn
|
||||||
|
- https://github.com/gnutls/gnutls/blob/master/lib/pkix.asn
|
||||||
|
|
||||||
|
The GNUTLS license is LGPLv2.1+, which is GPLv3 compatible, allowing us to import
|
||||||
|
it without issue.
|
||||||
|
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/gnutls_asn1_tab.c | 33 +++++++++++++++++++++---
|
||||||
|
grub-core/commands/appendedsig/pkix_asn1_tab.c | 27 +++++++++----------
|
||||||
|
2 files changed, 44 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/gnutls_asn1_tab.c b/grub-core/commands/appendedsig/gnutls_asn1_tab.c
|
||||||
|
index ddd1314..efc0c14 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/gnutls_asn1_tab.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/gnutls_asn1_tab.c
|
||||||
|
@@ -1,7 +1,11 @@
|
||||||
|
#include <grub/mm.h>
|
||||||
|
-#include <grub/libtasn1.h>
|
||||||
|
+#include <libtasn1.h>
|
||||||
|
|
||||||
|
-const asn1_static_node gnutls_asn1_tab[] = {
|
||||||
|
+/*
|
||||||
|
+ * Imported from gnutls.asn.
|
||||||
|
+ * https://github.com/gnutls/gnutls/blob/master/lib/gnutls.asn
|
||||||
|
+ */
|
||||||
|
+const asn1_static_node grub_gnutls_asn1_tab[] = {
|
||||||
|
{ "GNUTLS", 536872976, NULL },
|
||||||
|
{ NULL, 1073741836, NULL },
|
||||||
|
{ "RSAPublicKey", 1610612741, NULL },
|
||||||
|
@@ -55,6 +59,9 @@ const asn1_static_node gnutls_asn1_tab[] = {
|
||||||
|
{ "prime", 1073741827, NULL },
|
||||||
|
{ "base", 1073741827, NULL },
|
||||||
|
{ "privateValueLength", 16387, NULL },
|
||||||
|
+ { "pkcs-11-ec-Parameters", 1610612754, NULL },
|
||||||
|
+ { "oId", 1073741836, NULL },
|
||||||
|
+ { "curveName", 31, NULL },
|
||||||
|
{ "ECParameters", 1610612754, NULL },
|
||||||
|
{ "namedCurve", 12, NULL },
|
||||||
|
{ "ECPrivateKey", 1610612741, NULL },
|
||||||
|
@@ -86,6 +93,13 @@ const asn1_static_node gnutls_asn1_tab[] = {
|
||||||
|
{ "trailerField", 536911875, NULL },
|
||||||
|
{ NULL, 1073741833, "1"},
|
||||||
|
{ NULL, 2056, "3"},
|
||||||
|
+ { "RSAOAEPParameters", 1610612741, NULL },
|
||||||
|
+ { "hashAlgorithm", 1610637314, "AlgorithmIdentifier"},
|
||||||
|
+ { NULL, 2056, "0"},
|
||||||
|
+ { "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"},
|
||||||
|
+ { NULL, 2056, "1"},
|
||||||
|
+ { "pSourceFunc", 536895490, "AlgorithmIdentifier"},
|
||||||
|
+ { NULL, 2056, "2"},
|
||||||
|
{ "GOSTParameters", 1610612741, NULL },
|
||||||
|
{ "publicKeyParamSet", 1073741836, NULL },
|
||||||
|
{ "digestParamSet", 16396, NULL },
|
||||||
|
@@ -113,9 +127,22 @@ const asn1_static_node gnutls_asn1_tab[] = {
|
||||||
|
{ "ephemeralPublicKey", 1610637314, "SubjectPublicKeyInfo"},
|
||||||
|
{ NULL, 4104, "0"},
|
||||||
|
{ "ukm", 7, NULL },
|
||||||
|
- { "GostR3410-KeyTransport", 536870917, NULL },
|
||||||
|
+ { "GostR3410-KeyTransport", 1610612741, NULL },
|
||||||
|
{ "sessionEncryptedKey", 1073741826, "Gost28147-89-EncryptedKey"},
|
||||||
|
{ "transportParameters", 536895490, "GostR3410-TransportParameters"},
|
||||||
|
{ NULL, 4104, "0"},
|
||||||
|
+ { "TPMKey", 1610612741, NULL },
|
||||||
|
+ { "type", 1073741836, NULL },
|
||||||
|
+ { "emptyAuth", 1610637316, NULL },
|
||||||
|
+ { NULL, 2056, "0"},
|
||||||
|
+ { "parent", 1073741827, NULL },
|
||||||
|
+ { "pubkey", 1073741831, NULL },
|
||||||
|
+ { "privkey", 7, NULL },
|
||||||
|
+ { "MLDSAPrivateKey", 536870917, NULL },
|
||||||
|
+ { "version", 1073741827, NULL },
|
||||||
|
+ { "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
|
||||||
|
+ { "privateKey", 1073741831, NULL },
|
||||||
|
+ { "publicKey", 536895495, NULL },
|
||||||
|
+ { NULL, 2056, "1"},
|
||||||
|
{ NULL, 0, NULL }
|
||||||
|
};
|
||||||
|
diff --git a/grub-core/commands/appendedsig/pkix_asn1_tab.c b/grub-core/commands/appendedsig/pkix_asn1_tab.c
|
||||||
|
index adef69d..ec5f87b 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/pkix_asn1_tab.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/pkix_asn1_tab.c
|
||||||
|
@@ -1,7 +1,11 @@
|
||||||
|
#include <grub/mm.h>
|
||||||
|
-#include <grub/libtasn1.h>
|
||||||
|
+#include <libtasn1.h>
|
||||||
|
|
||||||
|
-const asn1_static_node pkix_asn1_tab[] = {
|
||||||
|
+/*
|
||||||
|
+ * Imported from pkix.asn.
|
||||||
|
+ * https://github.com/gnutls/gnutls/blob/master/lib/pkix.asn
|
||||||
|
+ */
|
||||||
|
+const asn1_static_node grub_pkix_asn1_tab[] = {
|
||||||
|
{ "PKIX1", 536875024, NULL },
|
||||||
|
{ NULL, 1073741836, NULL },
|
||||||
|
{ "PrivateKeyUsagePeriod", 1610612741, NULL },
|
||||||
|
@@ -27,9 +31,7 @@ const asn1_static_node pkix_asn1_tab[] = {
|
||||||
|
{ "MAX", 524298, "1"},
|
||||||
|
{ "utf8String", 1612709922, NULL },
|
||||||
|
{ "MAX", 524298, "1"},
|
||||||
|
- { "bmpString", 1612709921, NULL },
|
||||||
|
- { "MAX", 524298, "1"},
|
||||||
|
- { "ia5String", 538968093, NULL },
|
||||||
|
+ { "bmpString", 538968097, NULL },
|
||||||
|
{ "MAX", 524298, "1"},
|
||||||
|
{ "SubjectAltName", 1073741826, "GeneralNames"},
|
||||||
|
{ "GeneralNames", 1612709899, NULL },
|
||||||
|
@@ -64,8 +66,7 @@ const asn1_static_node pkix_asn1_tab[] = {
|
||||||
|
{ "BasicConstraints", 1610612741, NULL },
|
||||||
|
{ "cA", 1610645508, NULL },
|
||||||
|
{ NULL, 131081, NULL },
|
||||||
|
- { "pathLenConstraint", 537411587, NULL },
|
||||||
|
- { "0", 10, "MAX"},
|
||||||
|
+ { "pathLenConstraint", 16387, NULL },
|
||||||
|
{ "CRLDistributionPoints", 1612709899, NULL },
|
||||||
|
{ "MAX", 1074266122, "1"},
|
||||||
|
{ NULL, 2, "DistributionPoint"},
|
||||||
|
@@ -277,14 +278,15 @@ const asn1_static_node pkix_asn1_tab[] = {
|
||||||
|
{ "pkcs-5-PBES2-params", 1610612741, NULL },
|
||||||
|
{ "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
|
||||||
|
{ "encryptionScheme", 2, "AlgorithmIdentifier"},
|
||||||
|
+ { "pkcs-5-PBMAC1-params", 1610612741, NULL },
|
||||||
|
+ { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
|
||||||
|
+ { "messageAuthScheme", 2, "AlgorithmIdentifier"},
|
||||||
|
{ "pkcs-5-PBKDF2-params", 1610612741, NULL },
|
||||||
|
{ "salt", 1610612754, NULL },
|
||||||
|
{ "specified", 1073741831, NULL },
|
||||||
|
{ "otherSource", 2, "AlgorithmIdentifier"},
|
||||||
|
- { "iterationCount", 1611137027, NULL },
|
||||||
|
- { "1", 10, "MAX"},
|
||||||
|
- { "keyLength", 1611153411, NULL },
|
||||||
|
- { "1", 10, "MAX"},
|
||||||
|
+ { "iterationCount", 1073741827, NULL },
|
||||||
|
+ { "keyLength", 1073758211, NULL },
|
||||||
|
{ "prf", 16386, "AlgorithmIdentifier"},
|
||||||
|
{ "pkcs-12-PFX", 1610612741, NULL },
|
||||||
|
{ "version", 1610874883, NULL },
|
||||||
|
@@ -341,8 +343,7 @@ const asn1_static_node pkix_asn1_tab[] = {
|
||||||
|
{ "MAX", 1074266122, "1"},
|
||||||
|
{ NULL, 2, "Attribute"},
|
||||||
|
{ "ProxyCertInfo", 1610612741, NULL },
|
||||||
|
- { "pCPathLenConstraint", 1611153411, NULL },
|
||||||
|
- { "0", 10, "MAX"},
|
||||||
|
+ { "pCPathLenConstraint", 1073758211, NULL },
|
||||||
|
{ "proxyPolicy", 2, "ProxyPolicy"},
|
||||||
|
{ "ProxyPolicy", 1610612741, NULL },
|
||||||
|
{ "policyLanguage", 1073741836, NULL },
|
||||||
274
0392-appended-signatures-Parse-ASN1-node.patch
Normal file
274
0392-appended-signatures-Parse-ASN1-node.patch
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Tue, 18 Nov 2025 16:18:32 +0100
|
||||||
|
Subject: [PATCH] appended signatures: Parse ASN1 node
|
||||||
|
|
||||||
|
This code allows us to parse ASN1 node and 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.
|
||||||
|
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.h | 96 +++++-----------------------
|
||||||
|
grub-core/commands/appendedsig/asn1util.c | 59 ++++++++---------
|
||||||
|
2 files changed, 43 insertions(+), 112 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
index 9792ef3..601d616 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
- * Copyright (C) 2020 IBM Corporation.
|
||||||
|
+ * Copyright (C) 2020, 2022 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2020, 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
|
||||||
|
@@ -16,95 +17,28 @@
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-#include <grub/crypto.h>
|
||||||
|
-#include <grub/libtasn1.h>
|
||||||
|
+#include <libtasn1.h>
|
||||||
|
|
||||||
|
-extern asn1_node _gnutls_gnutls_asn;
|
||||||
|
-extern asn1_node _gnutls_pkix_asn;
|
||||||
|
+extern asn1_node grub_gnutls_gnutls_asn;
|
||||||
|
+extern asn1_node grub_gnutls_pkix_asn;
|
||||||
|
|
||||||
|
-#define MAX_OID_LEN 32
|
||||||
|
+/* Do libtasn1 init. */
|
||||||
|
+extern int
|
||||||
|
+grub_asn1_init (void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * 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:
|
||||||
|
+ * 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
|
||||||
|
+ * - 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);
|
||||||
|
+extern void *
|
||||||
|
+grub_asn1_allocate_and_read (asn1_node node, const char *name, const char *friendly_name,
|
||||||
|
+ grub_int32_t *content_size);
|
||||||
|
diff --git a/grub-core/commands/appendedsig/asn1util.c b/grub-core/commands/appendedsig/asn1util.c
|
||||||
|
index eff095a..9dd7898 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/asn1util.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/asn1util.c
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
- * Copyright (C) 2020 IBM Corporation.
|
||||||
|
+ * Copyright (C) 2020, 2022 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2020, 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
|
||||||
|
@@ -16,28 +17,29 @@
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-#include <grub/libtasn1.h>
|
||||||
|
+#include <libtasn1.h>
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
#include <grub/crypto.h>
|
||||||
|
+#include <grub/misc.h>
|
||||||
|
#include <grub/gcrypt/gcrypt.h>
|
||||||
|
|
||||||
|
#include "appendedsig.h"
|
||||||
|
|
||||||
|
-asn1_node _gnutls_gnutls_asn = ASN1_TYPE_EMPTY;
|
||||||
|
-asn1_node _gnutls_pkix_asn = ASN1_TYPE_EMPTY;
|
||||||
|
+asn1_node grub_gnutls_gnutls_asn = NULL;
|
||||||
|
+asn1_node grub_gnutls_pkix_asn = NULL;
|
||||||
|
|
||||||
|
-extern const ASN1_ARRAY_TYPE gnutls_asn1_tab[];
|
||||||
|
-extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
|
||||||
|
+extern const asn1_static_node grub_gnutls_asn1_tab[];
|
||||||
|
+extern const asn1_static_node grub_pkix_asn1_tab[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Read a value from an ASN1 node, allocating memory to store it.
|
||||||
|
- *
|
||||||
|
- * It will work for anything where the size libtasn1 returns is right:
|
||||||
|
+ * 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.
|
||||||
|
@@ -45,30 +47,26 @@ extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
|
||||||
|
* 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)
|
||||||
|
+grub_asn1_allocate_and_read (asn1_node node, const char *name, const char *friendly_name,
|
||||||
|
+ grub_int32_t *content_size)
|
||||||
|
{
|
||||||
|
- int result;
|
||||||
|
+ grub_int32_t result;
|
||||||
|
grub_uint8_t *tmpstr = NULL;
|
||||||
|
- int tmpstr_size = 0;
|
||||||
|
+ grub_int32_t tmpstr_size = 0;
|
||||||
|
|
||||||
|
result = asn1_read_value (node, name, NULL, &tmpstr_size);
|
||||||
|
if (result != ASN1_MEM_ERROR)
|
||||||
|
{
|
||||||
|
- grub_snprintf (grub_errmsg, sizeof (grub_errmsg),
|
||||||
|
- _
|
||||||
|
- ("Reading size of %s did not return expected status: %s"),
|
||||||
|
- friendly_name, asn1_strerror (result));
|
||||||
|
- grub_errno = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "reading size of %s did not return expected status: %s",
|
||||||
|
+ friendly_name, asn1_strerror (result)) ;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpstr = grub_malloc (tmpstr_size);
|
||||||
|
if (tmpstr == NULL)
|
||||||
|
{
|
||||||
|
- grub_snprintf (grub_errmsg, sizeof (grub_errmsg),
|
||||||
|
- "Could not allocate memory to store %s", friendly_name);
|
||||||
|
- grub_errno = GRUB_ERR_OUT_OF_MEMORY;
|
||||||
|
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not allocate memory to store %s",
|
||||||
|
+ friendly_name) ;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -76,10 +74,8 @@ grub_asn1_allocate_and_read (asn1_node node, const char *name,
|
||||||
|
if (result != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
grub_free (tmpstr);
|
||||||
|
- grub_snprintf (grub_errmsg, sizeof (grub_errmsg),
|
||||||
|
- "Error reading %s: %s",
|
||||||
|
- friendly_name, asn1_strerror (result));
|
||||||
|
- grub_errno = GRUB_ERR_BAD_FILE_TYPE;
|
||||||
|
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading %s: %s", friendly_name,
|
||||||
|
+ asn1_strerror (result)) ;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -89,14 +85,15 @@ grub_asn1_allocate_and_read (asn1_node node, const char *name,
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-asn1_init (void)
|
||||||
|
+grub_asn1_init (void)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
- res = asn1_array2tree (gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL);
|
||||||
|
+
|
||||||
|
+ res = asn1_array2tree (grub_gnutls_asn1_tab, &grub_gnutls_gnutls_asn, NULL);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
- {
|
||||||
|
- return res;
|
||||||
|
- }
|
||||||
|
- res = asn1_array2tree (pkix_asn1_tab, &_gnutls_pkix_asn, NULL);
|
||||||
|
+ return res;
|
||||||
|
+
|
||||||
|
+ res = asn1_array2tree (grub_pkix_asn1_tab, &grub_gnutls_pkix_asn, NULL);
|
||||||
|
+
|
||||||
|
return res;
|
||||||
|
}
|
||||||
659
0393-appended-signatures-Parse-PKCS-7-signed-data.patch
Normal file
659
0393-appended-signatures-Parse-PKCS-7-signed-data.patch
Normal file
@ -0,0 +1,659 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Tue, 18 Nov 2025 16:20:56 +0100
|
||||||
|
Subject: [PATCH] appended signatures: Parse PKCS#7 signed data
|
||||||
|
|
||||||
|
This code allows us to parse:
|
||||||
|
|
||||||
|
- PKCS#7 signed data messages. Only a single signer info 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.
|
||||||
|
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.h | 37 +++
|
||||||
|
grub-core/commands/appendedsig/pkcs7.c | 439 ++++++++++++++++++---------
|
||||||
|
2 files changed, 330 insertions(+), 146 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
index 601d616..b0beb89 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
@@ -17,11 +17,48 @@
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <grub/crypto.h>
|
||||||
|
#include <libtasn1.h>
|
||||||
|
|
||||||
|
extern asn1_node grub_gnutls_gnutls_asn;
|
||||||
|
extern asn1_node grub_gnutls_pkix_asn;
|
||||||
|
|
||||||
|
+#define GRUB_MAX_OID_LEN 32
|
||||||
|
+
|
||||||
|
+/* A PKCS#7 signed data signer info. */
|
||||||
|
+struct pkcs7_signer
|
||||||
|
+{
|
||||||
|
+ const gcry_md_spec_t *hash;
|
||||||
|
+ gcry_mpi_t sig_mpi;
|
||||||
|
+};
|
||||||
|
+typedef struct pkcs7_signer grub_pkcs7_signer_t;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * A PKCS#7 signed data message. We make no attempt to match intelligently, so
|
||||||
|
+ * we don't save any info about the signer.
|
||||||
|
+ */
|
||||||
|
+struct pkcs7_data
|
||||||
|
+{
|
||||||
|
+ grub_int32_t signer_count;
|
||||||
|
+ grub_pkcs7_signer_t *signers;
|
||||||
|
+};
|
||||||
|
+typedef struct pkcs7_data grub_pkcs7_data_t;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Parse a PKCS#7 message, which must be a signed data message. The message must
|
||||||
|
+ * be in 'sigbuf' and of size 'data_size'. The result is placed in 'msg', which
|
||||||
|
+ * must already be allocated.
|
||||||
|
+ */
|
||||||
|
+extern grub_err_t
|
||||||
|
+grub_pkcs7_data_parse (const void *sigbuf, grub_size_t data_size, grub_pkcs7_data_t *msg);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Release all the storage associated with the PKCS#7 message. If the caller
|
||||||
|
+ * dynamically allocated the message, it must free it.
|
||||||
|
+ */
|
||||||
|
+extern void
|
||||||
|
+grub_pkcs7_data_release (grub_pkcs7_data_t *msg);
|
||||||
|
+
|
||||||
|
/* Do libtasn1 init. */
|
||||||
|
extern int
|
||||||
|
grub_asn1_init (void);
|
||||||
|
diff --git a/grub-core/commands/appendedsig/pkcs7.c b/grub-core/commands/appendedsig/pkcs7.c
|
||||||
|
index dc6afe2..b8e2720 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/pkcs7.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/pkcs7.c
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
- * Copyright (C) 2020 IBM Corporation.
|
||||||
|
+ * Copyright (C) 2020, 2022 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2020, 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
|
||||||
|
@@ -20,57 +21,55 @@
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/crypto.h>
|
||||||
|
#include <grub/gcrypt/gcrypt.h>
|
||||||
|
-
|
||||||
|
+#include <sys/types.h>
|
||||||
|
|
||||||
|
static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * RFC 5652 s 5.1
|
||||||
|
- */
|
||||||
|
-const char *signedData_oid = "1.2.840.113549.1.7.2";
|
||||||
|
+/* RFC 5652 s 5.1. */
|
||||||
|
+static const char *signedData_oid = "1.2.840.113549.1.7.2";
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * RFC 4055 s 2.1
|
||||||
|
- */
|
||||||
|
-const char *sha256_oid = "2.16.840.1.101.3.4.2.1";
|
||||||
|
-const char *sha512_oid = "2.16.840.1.101.3.4.2.3";
|
||||||
|
+/* RFC 4055 s 2.1. */
|
||||||
|
+static const char *sha256_oid = "2.16.840.1.101.3.4.2.1";
|
||||||
|
+static const char *sha512_oid = "2.16.840.1.101.3.4.2.3";
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
-process_content (grub_uint8_t * content, int size,
|
||||||
|
- struct pkcs7_signedData *msg)
|
||||||
|
+process_content (grub_uint8_t *content, grub_int32_t size, grub_pkcs7_data_t *msg)
|
||||||
|
{
|
||||||
|
- int res;
|
||||||
|
+ grub_int32_t res;
|
||||||
|
asn1_node signed_part;
|
||||||
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
|
- char algo_oid[MAX_OID_LEN];
|
||||||
|
- int algo_oid_size = sizeof (algo_oid);
|
||||||
|
- int algo_count;
|
||||||
|
+ char algo_oid[GRUB_MAX_OID_LEN];
|
||||||
|
+ grub_int32_t algo_oid_size;
|
||||||
|
+ grub_int32_t algo_count;
|
||||||
|
+ grub_int32_t signer_count;
|
||||||
|
+ grub_int32_t i;
|
||||||
|
char version;
|
||||||
|
- int version_size = sizeof (version);
|
||||||
|
+ grub_int32_t version_size = sizeof (version);
|
||||||
|
grub_uint8_t *result_buf;
|
||||||
|
- int result_size = 0;
|
||||||
|
- int crls_size = 0;
|
||||||
|
+ grub_int32_t result_size = 0;
|
||||||
|
+ grub_int32_t crls_size = 0;
|
||||||
|
gcry_error_t gcry_err;
|
||||||
|
+ bool sha256_in_da, sha256_in_si, sha512_in_da, sha512_in_si;
|
||||||
|
+ char *da_path;
|
||||||
|
+ char *si_sig_path;
|
||||||
|
+ char *si_da_path;
|
||||||
|
|
||||||
|
- res = asn1_create_element (_gnutls_pkix_asn, "PKIX1.pkcs-7-SignedData",
|
||||||
|
- &signed_part);
|
||||||
|
+ res = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.pkcs-7-SignedData", &signed_part);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
- {
|
||||||
|
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
- "Could not create ASN.1 structure for PKCS#7 signed part.");
|
||||||
|
- }
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
+ "could not create ASN.1 structure for PKCS#7 signed part");
|
||||||
|
|
||||||
|
res = asn1_der_decoding2 (&signed_part, content, &size,
|
||||||
|
- ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
|
||||||
|
+ ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error reading PKCS#7 signed data: %s", asn1_error);
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "error reading PKCS#7 signed data: %s", asn1_error);
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* SignedData ::= SEQUENCE {
|
||||||
|
+ /*
|
||||||
|
+ * SignedData ::= SEQUENCE {
|
||||||
|
* version CMSVersion,
|
||||||
|
* digestAlgorithms DigestAlgorithmIdentifiers,
|
||||||
|
* encapContentInfo EncapsulatedContentInfo,
|
||||||
|
@@ -79,23 +78,19 @@ process_content (grub_uint8_t * content, int size,
|
||||||
|
* signerInfos SignerInfos }
|
||||||
|
*/
|
||||||
|
|
||||||
|
- /* version per the algo in 5.1, must be 1 */
|
||||||
|
res = asn1_read_value (signed_part, "version", &version, &version_size);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error reading signedData version: %s",
|
||||||
|
- asn1_strerror (res));
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error reading signedData version: %s",
|
||||||
|
+ asn1_strerror (res));
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Signature version must be 1 because appended signature only support v1. */
|
||||||
|
if (version != 1)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Unexpected signature version v%d, only v1 supported",
|
||||||
|
- version);
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "unexpected signature version v%d, only v1 supported", version);
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -104,147 +99,301 @@ process_content (grub_uint8_t * content, int size,
|
||||||
|
*
|
||||||
|
* DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
|
||||||
|
* DigestAlgorithmIdentifer is an X.509 AlgorithmIdentifier (10.1.1)
|
||||||
|
- *
|
||||||
|
+ *
|
||||||
|
* RFC 4055 s 2.1:
|
||||||
|
* sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL }
|
||||||
|
* sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL }
|
||||||
|
*
|
||||||
|
* We only support 1 element in the set, and we do not check parameters atm.
|
||||||
|
*/
|
||||||
|
- res =
|
||||||
|
- asn1_number_of_elements (signed_part, "digestAlgorithms", &algo_count);
|
||||||
|
+ res = asn1_number_of_elements (signed_part, "digestAlgorithms", &algo_count);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error counting number of digest algorithms: %s",
|
||||||
|
- asn1_strerror (res));
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error counting number of digest algorithms: %s",
|
||||||
|
+ asn1_strerror (res));
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (algo_count != 1)
|
||||||
|
+ if (algo_count <= 0)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
- "Only 1 digest algorithm is supported");
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "a minimum of 1 digest algorithm is required");
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
- res =
|
||||||
|
- asn1_read_value (signed_part, "digestAlgorithms.?1.algorithm", algo_oid,
|
||||||
|
- &algo_oid_size);
|
||||||
|
- if (res != ASN1_SUCCESS)
|
||||||
|
+ if (algo_count > 2)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error reading digest algorithm: %s",
|
||||||
|
- asn1_strerror (res));
|
||||||
|
+ err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "a maximum of 2 digest algorithms is supported");
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0)
|
||||||
|
- {
|
||||||
|
- msg->hash = grub_crypto_lookup_md_by_name ("sha512");
|
||||||
|
- }
|
||||||
|
- else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0)
|
||||||
|
- {
|
||||||
|
- msg->hash = grub_crypto_lookup_md_by_name ("sha256");
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
- {
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
- "Only SHA-256 and SHA-512 hashes are supported, found OID %s",
|
||||||
|
- algo_oid);
|
||||||
|
- goto cleanup_signed_part;
|
||||||
|
- }
|
||||||
|
+ sha256_in_da = false;
|
||||||
|
+ sha512_in_da = false;
|
||||||
|
|
||||||
|
- if (!msg->hash)
|
||||||
|
+ for (i = 0; i < algo_count; i++)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Hash algorithm for OID %s not loaded", algo_oid);
|
||||||
|
- goto cleanup_signed_part;
|
||||||
|
+ da_path = grub_xasprintf ("digestAlgorithms.?%d.algorithm", i + 1);
|
||||||
|
+ if (da_path == NULL)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
+ "could not allocate path for digest algorithm parsing path");
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ algo_oid_size = sizeof (algo_oid);
|
||||||
|
+ res = asn1_read_value (signed_part, da_path, algo_oid, &algo_oid_size);
|
||||||
|
+ if (res != ASN1_SUCCESS)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error reading digest algorithm: %s",
|
||||||
|
+ asn1_strerror (res));
|
||||||
|
+ grub_free (da_path);
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ if (sha512_in_da == false)
|
||||||
|
+ sha512_in_da = true;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "SHA-512 specified twice in digest algorithm list");
|
||||||
|
+ grub_free (da_path);
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ if (sha256_in_da == false)
|
||||||
|
+ sha256_in_da = true;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "SHA-256 specified twice in digest algorithm list");
|
||||||
|
+ grub_free (da_path);
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
+ "only SHA-256 and SHA-512 hashes are supported, found OID %s",
|
||||||
|
+ algo_oid);
|
||||||
|
+ grub_free (da_path);
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_free (da_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* At this point, at least one of sha{256,512}_in_da must be true. */
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
- * We ignore the certificates, but we don't permit CRLs.
|
||||||
|
- * A CRL entry might be revoking the certificate we're using, and we have
|
||||||
|
- * no way of dealing with that at the moment.
|
||||||
|
+ * We ignore the certificates, but we don't permit CRLs. A CRL entry might be
|
||||||
|
+ * revoking the certificate we're using, and we have no way of dealing with
|
||||||
|
+ * that at the moment.
|
||||||
|
*/
|
||||||
|
res = asn1_read_value (signed_part, "crls", NULL, &crls_size);
|
||||||
|
if (res != ASN1_ELEMENT_NOT_FOUND)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
- "PKCS#7 messages with embedded CRLs are not supported");
|
||||||
|
+ err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
+ "PKCS#7 messages with embedded CRLs are not supported");
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* read the signature */
|
||||||
|
- result_buf =
|
||||||
|
- grub_asn1_allocate_and_read (signed_part, "signerInfos.?1.signature",
|
||||||
|
- "signature data", &result_size);
|
||||||
|
- if (!result_buf)
|
||||||
|
+ /* Read the signatures */
|
||||||
|
+ res = asn1_number_of_elements (signed_part, "signerInfos", &signer_count);
|
||||||
|
+ if (res != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
- err = grub_errno;
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error counting number of signers: %s",
|
||||||
|
+ asn1_strerror (res));
|
||||||
|
goto cleanup_signed_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
- gcry_err =
|
||||||
|
- gcry_mpi_scan (&(msg->sig_mpi), GCRYMPI_FMT_USG, result_buf, result_size,
|
||||||
|
- NULL);
|
||||||
|
- if (gcry_err != GPG_ERR_NO_ERROR)
|
||||||
|
+ if (signer_count <= 0)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error loading signature into MPI structure: %d",
|
||||||
|
- gcry_err);
|
||||||
|
- goto cleanup_result;
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "a minimum of 1 signer is required");
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ msg->signers = grub_calloc (signer_count, sizeof (grub_pkcs7_signer_t));
|
||||||
|
+ if (msg->signers == NULL)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
+ "could not allocate space for %d signers", signer_count);
|
||||||
|
+ goto cleanup_signed_part;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ msg->signer_count = 0;
|
||||||
|
+ for (i = 0; i < signer_count; i++)
|
||||||
|
+ {
|
||||||
|
+ si_da_path = grub_xasprintf ("signerInfos.?%d.digestAlgorithm.algorithm", i + 1);
|
||||||
|
+ if (si_da_path == NULL)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
+ "could not allocate path for signer %d's digest algorithm parsing path",
|
||||||
|
+ i);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ algo_oid_size = sizeof (algo_oid);
|
||||||
|
+ res = asn1_read_value (signed_part, si_da_path, algo_oid, &algo_oid_size);
|
||||||
|
+ if (res != ASN1_SUCCESS)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "error reading signer %d's digest algorithm: %s", i, asn1_strerror (res));
|
||||||
|
+ grub_free (si_da_path);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_free (si_da_path);
|
||||||
|
+
|
||||||
|
+ if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ if (sha512_in_da == false)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "signer %d claims a SHA-512 signature which was not "
|
||||||
|
+ "specified in the outer DigestAlgorithms", i);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ sha512_in_si = true;
|
||||||
|
+ msg->signers[i].hash = grub_crypto_lookup_md_by_name ("sha512");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ if (sha256_in_da == false)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "signer %d claims a SHA-256 signature which was not "
|
||||||
|
+ "specified in the outer DigestAlgorithms", i);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ sha256_in_si = true;
|
||||||
|
+ msg->signers[i].hash = grub_crypto_lookup_md_by_name ("sha256");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
+ "only SHA-256 and SHA-512 hashes are supported, found OID %s",
|
||||||
|
+ algo_oid);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (msg->signers[i].hash == NULL)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "Hash algorithm for signer %d (OID %s) not loaded", i, algo_oid);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ si_sig_path = grub_xasprintf ("signerInfos.?%d.signature", i + 1);
|
||||||
|
+ if (si_sig_path == NULL)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
+ "could not allocate path for signer %d's signature parsing path", i);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ result_buf = grub_asn1_allocate_and_read (signed_part, si_sig_path, "signature data", &result_size);
|
||||||
|
+ grub_free (si_sig_path);
|
||||||
|
+
|
||||||
|
+ if (result_buf == NULL)
|
||||||
|
+ {
|
||||||
|
+ err = grub_errno;
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ gcry_err = _gcry_mpi_scan (&(msg->signers[i].sig_mpi), GCRYMPI_FMT_USG,
|
||||||
|
+ result_buf, result_size, NULL);
|
||||||
|
+ grub_free (result_buf);
|
||||||
|
+
|
||||||
|
+ if (gcry_err != GPG_ERR_NO_ERROR)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "error loading signature %d into MPI structure: %d",
|
||||||
|
+ i, gcry_err);
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Use msg->signer_count to track fully populated signerInfos so we know
|
||||||
|
+ * how many we need to clean up.
|
||||||
|
+ */
|
||||||
|
+ msg->signer_count++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Final consistency check of signerInfo.*.digestAlgorithm vs digestAlgorithms
|
||||||
|
+ * .*.algorithm. An algorithm must be present in both digestAlgorithms and
|
||||||
|
+ * signerInfo or in neither. We have already checked for an algorithm in
|
||||||
|
+ * signerInfo that is not in digestAlgorithms, here we check for algorithms in
|
||||||
|
+ * digestAlgorithms but not in signerInfos.
|
||||||
|
+ */
|
||||||
|
+ if (sha512_in_da == true && sha512_in_si == false)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "SHA-512 specified in DigestAlgorithms but did not appear in SignerInfos");
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
-cleanup_result:
|
||||||
|
- grub_free (result_buf);
|
||||||
|
-cleanup_signed_part:
|
||||||
|
+ if (sha256_in_da == true && sha256_in_si == false)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "SHA-256 specified in DigestAlgorithms but did not appear in SignerInfos");
|
||||||
|
+ goto cleanup_signerInfos;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ asn1_delete_structure (&signed_part);
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+
|
||||||
|
+ cleanup_signerInfos:
|
||||||
|
+ for (i = 0; i < msg->signer_count; i++)
|
||||||
|
+ _gcry_mpi_release (msg->signers[i].sig_mpi);
|
||||||
|
+
|
||||||
|
+ grub_free (msg->signers);
|
||||||
|
+
|
||||||
|
+ cleanup_signed_part:
|
||||||
|
asn1_delete_structure (&signed_part);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
-parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size,
|
||||||
|
- struct pkcs7_signedData *msg)
|
||||||
|
+grub_pkcs7_data_parse (const void *sigbuf, grub_size_t data_size, grub_pkcs7_data_t *msg)
|
||||||
|
{
|
||||||
|
- int res;
|
||||||
|
+ grub_int32_t res;
|
||||||
|
asn1_node content_info;
|
||||||
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
|
- char content_oid[MAX_OID_LEN];
|
||||||
|
+ char content_oid[GRUB_MAX_OID_LEN];
|
||||||
|
grub_uint8_t *content;
|
||||||
|
- int content_size;
|
||||||
|
- int content_oid_size = sizeof (content_oid);
|
||||||
|
- int size;
|
||||||
|
+ grub_int32_t content_size;
|
||||||
|
+ grub_int32_t content_oid_size = sizeof (content_oid);
|
||||||
|
+ grub_int32_t size = (grub_int32_t) data_size;
|
||||||
|
|
||||||
|
- if (data_size > GRUB_INT_MAX)
|
||||||
|
+ if (data_size > GRUB_UINT_MAX)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
- "Cannot parse a PKCS#7 message where data size > INT_MAX");
|
||||||
|
- size = (int) data_size;
|
||||||
|
+ "cannot parse a PKCS#7 message where data size > GRUB_UINT_MAX");
|
||||||
|
|
||||||
|
- res = asn1_create_element (_gnutls_pkix_asn,
|
||||||
|
- "PKIX1.pkcs-7-ContentInfo", &content_info);
|
||||||
|
+ res = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.pkcs-7-ContentInfo", &content_info);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
- {
|
||||||
|
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
- "Could not create ASN.1 structure for PKCS#7 data: %s",
|
||||||
|
- asn1_strerror (res));
|
||||||
|
- }
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
|
+ "could not create ASN.1 structure for PKCS#7 data: %s",
|
||||||
|
+ asn1_strerror (res));
|
||||||
|
|
||||||
|
res = asn1_der_decoding2 (&content_info, sigbuf, &size,
|
||||||
|
- ASN1_DECODE_FLAG_STRICT_DER, asn1_error);
|
||||||
|
+ ASN1_DECODE_FLAG_STRICT_DER | ASN1_DECODE_FLAG_ALLOW_PADDING,
|
||||||
|
+ asn1_error);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error decoding PKCS#7 message DER: %s", asn1_error);
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "error decoding PKCS#7 message DER: %s", asn1_error);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -255,32 +404,24 @@ parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size,
|
||||||
|
*
|
||||||
|
* ContentType ::= OBJECT IDENTIFIER
|
||||||
|
*/
|
||||||
|
- res =
|
||||||
|
- asn1_read_value (content_info, "contentType", content_oid,
|
||||||
|
- &content_oid_size);
|
||||||
|
+ res = asn1_read_value (content_info, "contentType", content_oid, &content_oid_size);
|
||||||
|
if (res != ASN1_SUCCESS)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Error reading PKCS#7 content type: %s",
|
||||||
|
- asn1_strerror (res));
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error reading PKCS#7 content type: %s",
|
||||||
|
+ asn1_strerror (res));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* OID for SignedData defined in 5.1 */
|
||||||
|
+ /* OID for SignedData defined in 5.1. */
|
||||||
|
if (grub_strncmp (signedData_oid, content_oid, content_oid_size) != 0)
|
||||||
|
{
|
||||||
|
- err =
|
||||||
|
- grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
- "Unexpected content type in PKCS#7 message: OID %s",
|
||||||
|
- content_oid);
|
||||||
|
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "unexpected content type in PKCS#7 message: OID %s", content_oid);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
- content =
|
||||||
|
- grub_asn1_allocate_and_read (content_info, "content",
|
||||||
|
- "PKCS#7 message content", &content_size);
|
||||||
|
- if (!content)
|
||||||
|
+ content = grub_asn1_allocate_and_read (content_info, "content", "PKCS#7 message content", &content_size);
|
||||||
|
+ if (content == NULL)
|
||||||
|
{
|
||||||
|
err = grub_errno;
|
||||||
|
goto cleanup;
|
||||||
|
@@ -289,17 +430,23 @@ parse_pkcs7_signedData (void *sigbuf, grub_size_t data_size,
|
||||||
|
err = process_content (content, content_size, msg);
|
||||||
|
grub_free (content);
|
||||||
|
|
||||||
|
-cleanup:
|
||||||
|
+ cleanup:
|
||||||
|
asn1_delete_structure (&content_info);
|
||||||
|
+
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Release all the storage associated with the PKCS#7 message.
|
||||||
|
- * If the caller dynamically allocated the message, it must free it.
|
||||||
|
+ * 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)
|
||||||
|
+grub_pkcs7_data_release (grub_pkcs7_data_t *msg)
|
||||||
|
{
|
||||||
|
- gcry_mpi_release (msg->sig_mpi);
|
||||||
|
+ grub_int32_t i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < msg->signer_count; i++)
|
||||||
|
+ _gcry_mpi_release (msg->signers[i].sig_mpi);
|
||||||
|
+
|
||||||
|
+ grub_free (msg->signers);
|
||||||
|
}
|
||||||
1590
0394-appended-signatures-Parse-X.509-certificates.patch
Normal file
1590
0394-appended-signatures-Parse-X.509-certificates.patch
Normal file
File diff suppressed because it is too large
Load Diff
122
0395-powerpc-ieee1275-Enter-lockdown-based-on-ibm-secure-.patch
Normal file
122
0395-powerpc-ieee1275-Enter-lockdown-based-on-ibm-secure-.patch
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:54 +0530
|
||||||
|
Subject: [PATCH] powerpc/ieee1275: Enter lockdown based on /ibm, secure-boot
|
||||||
|
|
||||||
|
Read secure boot mode from 'ibm,secure-boot' property and if the secure boot
|
||||||
|
mode is set to 2 (enforce), enter lockdown. Else it is considered as disabled.
|
||||||
|
There are three secure boot modes. They are
|
||||||
|
|
||||||
|
0 - disabled
|
||||||
|
No signature verification is performed. This is the default.
|
||||||
|
1 - audit
|
||||||
|
Signature verification is performed and if signature verification fails,
|
||||||
|
display the errors and allow the boot to continue.
|
||||||
|
2 - enforce
|
||||||
|
Lockdown the GRUB. Signature verification is performed and if signature
|
||||||
|
verification fails, display the errors and stop the boot.
|
||||||
|
|
||||||
|
Now, only support disabled and enforce.
|
||||||
|
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/kern/ieee1275/init.c | 56 +++++++++++++++++++++++++++++++-----------
|
||||||
|
1 file changed, 42 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
|
||||||
|
index 482cad2..0c587d3 100644
|
||||||
|
--- a/grub-core/kern/ieee1275/init.c
|
||||||
|
+++ b/grub-core/kern/ieee1275/init.c
|
||||||
|
@@ -49,7 +49,14 @@
|
||||||
|
#if defined(__powerpc__) || defined(__i386__)
|
||||||
|
#include <grub/ieee1275/alloc.h>
|
||||||
|
#endif
|
||||||
|
+#if defined(__powerpc__)
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#ifdef __powerpc__
|
||||||
|
+#define GRUB_SB_DISABLED ((grub_uint32_t) 0)
|
||||||
|
+#define GRUB_SB_ENFORCE ((grub_uint32_t) 2)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* The maximum heap size we're going to claim. Not used by sparc. */
|
||||||
|
#ifdef __i386__
|
||||||
|
@@ -1009,30 +1016,49 @@ grub_parse_cmdline (void)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef __powerpc__
|
||||||
|
static void
|
||||||
|
-grub_get_ieee1275_secure_boot (void)
|
||||||
|
+grub_ieee1275_get_secure_boot (void)
|
||||||
|
{
|
||||||
|
grub_ieee1275_phandle_t root;
|
||||||
|
- int rc;
|
||||||
|
- grub_uint32_t is_sb;
|
||||||
|
+ grub_uint32_t sb_mode = GRUB_SB_DISABLED;
|
||||||
|
+ grub_int32_t rc;
|
||||||
|
|
||||||
|
- grub_ieee1275_finddevice ("/", &root);
|
||||||
|
+ rc = grub_ieee1275_finddevice ("/", &root);
|
||||||
|
+ if (rc != 0)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &is_sb,
|
||||||
|
- sizeof (is_sb), 0);
|
||||||
|
-
|
||||||
|
- /* ibm,secure-boot:
|
||||||
|
+ rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &sb_mode, sizeof (sb_mode), 0);
|
||||||
|
+ if (rc != 0)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /ibm,secure-boot property");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ /*
|
||||||
|
+ * Secure Boot Mode:
|
||||||
|
* 0 - disabled
|
||||||
|
+ * No signature verification is performed. This is the default.
|
||||||
|
* 1 - audit
|
||||||
|
+ * Signature verification is performed and if signature verification
|
||||||
|
+ * fails, display the errors and allow the boot to continue.
|
||||||
|
* 2 - enforce
|
||||||
|
- * 3 - enforce + OS-specific behaviour
|
||||||
|
+ * Lockdown the GRUB. Signature verification is performed and If
|
||||||
|
+ * signature verification fails, display the errors and stop the boot.
|
||||||
|
*
|
||||||
|
- * We only support enforce.
|
||||||
|
+ * Now, only support disabled and enforce.
|
||||||
|
*/
|
||||||
|
- if (rc >= 0 && is_sb >= 2)
|
||||||
|
- grub_lockdown ();
|
||||||
|
+ if (sb_mode == GRUB_SB_ENFORCE)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("ieee1275", "Secure Boot Enabled\n");
|
||||||
|
+ grub_lockdown ();
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ grub_dprintf ("ieee1275", "Secure Boot Disabled\n");
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+#endif /* __powerpc__ */
|
||||||
|
grub_addr_t grub_modbase;
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -1059,7 +1085,9 @@ grub_machine_init (void)
|
||||||
|
grub_install_get_time_ms (grub_rtc_get_time_ms);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- grub_get_ieee1275_secure_boot ();
|
||||||
|
+#ifdef __powerpc__
|
||||||
|
+ grub_ieee1275_get_secure_boot ();
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
1098
0396-appended-signatures-Support-verifying-appended-signa.patch
Normal file
1098
0396-appended-signatures-Support-verifying-appended-signa.patch
Normal file
File diff suppressed because it is too large
Load Diff
775
0397-powerpc-ieee1275-Read-the-db-and-dbx-secure-boot-var.patch
Normal file
775
0397-powerpc-ieee1275-Read-the-db-and-dbx-secure-boot-var.patch
Normal file
@ -0,0 +1,775 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:56 +0530
|
||||||
|
Subject: [PATCH] powerpc/ieee1275: Read the db and dbx secure boot variables
|
||||||
|
|
||||||
|
Enhancing the infrastructure to enable the Platform Keystore (PKS) feature,
|
||||||
|
which provides access to the SB_VERSION, db, and dbx secure boot variables
|
||||||
|
from PKS.
|
||||||
|
|
||||||
|
If PKS is enabled, it will read secure boot variables such as db and dbx
|
||||||
|
from PKS and extract EFI Signature List (ESL) from it. The ESLs would be
|
||||||
|
saved in the Platform Keystore buffer, and the appendedsig module would
|
||||||
|
read it later to extract the certificate's details from ESL.
|
||||||
|
|
||||||
|
In the following scenarios, static key management mode will be activated:
|
||||||
|
1. When Secure Boot is enabled with static key management mode
|
||||||
|
2. When SB_VERSION is unavailable but Secure Boot is enabled
|
||||||
|
3. When PKS support is unavailable but Secure Boot is enabled
|
||||||
|
|
||||||
|
Note:
|
||||||
|
|
||||||
|
SB_VERSION: Key Management Mode
|
||||||
|
1 - Enable dynamic key management mode. Read the db and dbx variables from PKS,
|
||||||
|
and use them for signature verification.
|
||||||
|
0 - Enable static key management mode. Read keys from the GRUB ELF Note and
|
||||||
|
use it for signature verification.
|
||||||
|
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/Makefile.am | 2 +
|
||||||
|
grub-core/Makefile.core.def | 2 +
|
||||||
|
grub-core/kern/ieee1275/ieee1275.c | 1 -
|
||||||
|
grub-core/kern/ieee1275/init.c | 4 +
|
||||||
|
grub-core/kern/powerpc/ieee1275/ieee1275.c | 137 +++++++++
|
||||||
|
.../kern/powerpc/ieee1275/platform_keystore.c | 333 +++++++++++++++++++++
|
||||||
|
include/grub/ieee1275/ieee1275.h | 3 +
|
||||||
|
include/grub/powerpc/ieee1275/ieee1275.h | 36 +++
|
||||||
|
include/grub/powerpc/ieee1275/platform_keystore.h | 123 ++++++++
|
||||||
|
9 files changed, 640 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c
|
||||||
|
create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||||
|
create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h
|
||||||
|
|
||||||
|
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
|
||||||
|
index aa17239..8dd7014 100644
|
||||||
|
--- a/grub-core/Makefile.am
|
||||||
|
+++ b/grub-core/Makefile.am
|
||||||
|
@@ -247,6 +247,8 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||||
|
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h
|
||||||
|
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||||
|
endif
|
||||||
|
|
||||||
|
if COND_sparc64_ieee1275
|
||||||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||||
|
index 15721c5..e16013a 100644
|
||||||
|
--- a/grub-core/Makefile.core.def
|
||||||
|
+++ b/grub-core/Makefile.core.def
|
||||||
|
@@ -338,6 +338,8 @@ kernel = {
|
||||||
|
powerpc_ieee1275 = kern/powerpc/dl.c;
|
||||||
|
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
|
||||||
|
powerpc_ieee1275 = kern/lockdown.c;
|
||||||
|
+ powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c;
|
||||||
|
+ powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c;
|
||||||
|
|
||||||
|
sparc64_ieee1275 = kern/sparc64/cache.S;
|
||||||
|
sparc64_ieee1275 = kern/sparc64/dl.c;
|
||||||
|
diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c
|
||||||
|
index 36ca2db..afa37a9 100644
|
||||||
|
--- a/grub-core/kern/ieee1275/ieee1275.c
|
||||||
|
+++ b/grub-core/kern/ieee1275/ieee1275.c
|
||||||
|
@@ -23,7 +23,6 @@
|
||||||
|
|
||||||
|
#define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1)
|
||||||
|
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
|
||||||
|
-#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
|
||||||
|
index 0c587d3..32ee281 100644
|
||||||
|
--- a/grub-core/kern/ieee1275/init.c
|
||||||
|
+++ b/grub-core/kern/ieee1275/init.c
|
||||||
|
@@ -51,6 +51,8 @@
|
||||||
|
#endif
|
||||||
|
#if defined(__powerpc__)
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
+#include <grub/powerpc/ieee1275/ieee1275.h>
|
||||||
|
+#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __powerpc__
|
||||||
|
@@ -1057,6 +1059,8 @@ grub_ieee1275_get_secure_boot (void)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_dprintf ("ieee1275", "Secure Boot Disabled\n");
|
||||||
|
+
|
||||||
|
+ grub_pks_keystore_init ();
|
||||||
|
}
|
||||||
|
#endif /* __powerpc__ */
|
||||||
|
grub_addr_t grub_modbase;
|
||||||
|
diff --git a/grub-core/kern/powerpc/ieee1275/ieee1275.c b/grub-core/kern/powerpc/ieee1275/ieee1275.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..20c49e3
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/kern/powerpc/ieee1275/ieee1275.c
|
||||||
|
@@ -0,0 +1,137 @@
|
||||||
|
+/* ieee1275.c - Access the Open Firmware client interface. */
|
||||||
|
+/*
|
||||||
|
+ * GRUB -- GRand Unified Bootloader
|
||||||
|
+ * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2020, 2021, 2022, 2023, 2024, 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/ieee1275/ieee1275.h>
|
||||||
|
+#include <grub/powerpc/ieee1275/ieee1275.h>
|
||||||
|
+#include <grub/misc.h>
|
||||||
|
+
|
||||||
|
+grub_int32_t
|
||||||
|
+grub_ieee1275_test (const char *interface_name)
|
||||||
|
+{
|
||||||
|
+ struct test_args
|
||||||
|
+ {
|
||||||
|
+ struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */
|
||||||
|
+ grub_ieee1275_cell_t name; /* The interface name. */
|
||||||
|
+ grub_ieee1275_cell_t missing;
|
||||||
|
+ } args;
|
||||||
|
+
|
||||||
|
+ INIT_IEEE1275_COMMON (&args.common, "test", 1, 1);
|
||||||
|
+ args.name = (grub_ieee1275_cell_t) interface_name;
|
||||||
|
+
|
||||||
|
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (args.missing == IEEE1275_CELL_INVALID)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+grub_int32_t
|
||||||
|
+grub_ieee1275_pks_max_object_size (grub_uint32_t *result)
|
||||||
|
+{
|
||||||
|
+ struct mos_args
|
||||||
|
+ {
|
||||||
|
+ struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */
|
||||||
|
+ grub_ieee1275_cell_t size; /* The maximum object size for a PKS object. */
|
||||||
|
+ } args;
|
||||||
|
+
|
||||||
|
+ INIT_IEEE1275_COMMON (&args.common, GRUB_PKS_MAX_OBJ_INTERFACE, 0, 1);
|
||||||
|
+
|
||||||
|
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (args.size == IEEE1275_CELL_INVALID || args.size == 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ *result = args.size;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+grub_int32_t
|
||||||
|
+grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label,
|
||||||
|
+ const grub_uint32_t label_len, const grub_uint32_t buffer_len,
|
||||||
|
+ grub_uint8_t *buffer, grub_uint32_t *data_len,
|
||||||
|
+ grub_uint32_t *policies)
|
||||||
|
+{
|
||||||
|
+ struct pks_read_args
|
||||||
|
+ {
|
||||||
|
+ struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */
|
||||||
|
+ grub_ieee1275_cell_t consumer; /* The object belonging to consumer with the label. */
|
||||||
|
+ grub_ieee1275_cell_t label; /* Object label buffer logical real address. */
|
||||||
|
+ grub_ieee1275_cell_t label_len; /* The byte length of the object label. */
|
||||||
|
+ grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */
|
||||||
|
+ grub_ieee1275_cell_t buffer_len; /* Length of the output buffer. */
|
||||||
|
+ grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */
|
||||||
|
+ grub_ieee1275_cell_t policies; /* The object policies. */
|
||||||
|
+ grub_int32_t rc; /* The return code. */
|
||||||
|
+ } args;
|
||||||
|
+
|
||||||
|
+ INIT_IEEE1275_COMMON (&args.common, GRUB_PKS_READ_OBJ_INTERFACE, 5, 3);
|
||||||
|
+ args.consumer = consumer;
|
||||||
|
+ args.label_len = label_len;
|
||||||
|
+ args.buffer_len = buffer_len;
|
||||||
|
+ args.label = (grub_ieee1275_cell_t) label;
|
||||||
|
+ args.buffer = (grub_ieee1275_cell_t) buffer;
|
||||||
|
+
|
||||||
|
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (args.data_len == IEEE1275_CELL_INVALID)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ *data_len = args.data_len;
|
||||||
|
+ *policies = args.policies;
|
||||||
|
+
|
||||||
|
+ return args.rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+grub_int32_t
|
||||||
|
+grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type,
|
||||||
|
+ const grub_uint32_t buffer_len, grub_uint8_t *buffer,
|
||||||
|
+ grub_size_t *data_len)
|
||||||
|
+{
|
||||||
|
+ struct pks_read_sbvar_args
|
||||||
|
+ {
|
||||||
|
+ struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */
|
||||||
|
+ grub_ieee1275_cell_t sbvar_flags; /* The sbvar operation flags. */
|
||||||
|
+ grub_ieee1275_cell_t sbvar_type; /* The sbvar being requested. */
|
||||||
|
+ grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */
|
||||||
|
+ grub_ieee1275_cell_t buffer_len; /* Length of the Output buffer. */
|
||||||
|
+ grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */
|
||||||
|
+ grub_int32_t rc; /* The return code. */
|
||||||
|
+ } args;
|
||||||
|
+
|
||||||
|
+ INIT_IEEE1275_COMMON (&args.common, GRUB_PKS_READ_SBVAR_INTERFACE, 4, 2);
|
||||||
|
+ args.sbvar_flags = sbvar_flags;
|
||||||
|
+ args.sbvar_type = sbvar_type;
|
||||||
|
+ args.buffer_len = buffer_len;
|
||||||
|
+ args.buffer = (grub_ieee1275_cell_t) buffer;
|
||||||
|
+
|
||||||
|
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (args.data_len == IEEE1275_CELL_INVALID)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ *data_len = args.data_len;
|
||||||
|
+
|
||||||
|
+ return args.rc;
|
||||||
|
+}
|
||||||
|
diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..cc2d493
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c
|
||||||
|
@@ -0,0 +1,333 @@
|
||||||
|
+/*
|
||||||
|
+ * GRUB -- GRand Unified Bootloader
|
||||||
|
+ * Copyright (C) 2024 Free Software Foundation, Inc.
|
||||||
|
+ * Copyright (C) 2022, 2023, 2024, 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/mm.h>
|
||||||
|
+#include <grub/types.h>
|
||||||
|
+#include <grub/misc.h>
|
||||||
|
+#include <grub/lockdown.h>
|
||||||
|
+#include <grub/ieee1275/ieee1275.h>
|
||||||
|
+#include <grub/powerpc/ieee1275/ieee1275.h>
|
||||||
|
+#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||||
|
+
|
||||||
|
+/* PKS object maximum size. */
|
||||||
|
+static grub_uint32_t pks_max_object_size = 0;
|
||||||
|
+
|
||||||
|
+/* Platform KeyStore db and dbx. */
|
||||||
|
+static grub_pks_t pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0,
|
||||||
|
+ .dbx_entries = 0, .db_exists = true};
|
||||||
|
+/*
|
||||||
|
+ * pks_use_keystore: Key Management Modes
|
||||||
|
+ * False: Static key management (use built-in Keys). This is default.
|
||||||
|
+ * True: Dynamic key management (use Platform KeySotre).
|
||||||
|
+ */
|
||||||
|
+static bool pks_use_keystore = false;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Reads the Globally Unique Identifier (GUID), EFI Signature Database (ESD),
|
||||||
|
+ * and its size from the Platform KeyStore EFI Signature List (ESL), then
|
||||||
|
+ * stores them into the PKS Signature Database (SD) (i.e., pks_sd buffer
|
||||||
|
+ * and pks_sd entries) in the GRUB.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+_esl_to_esd (const grub_uint8_t *esl_data, grub_size_t esl_size,
|
||||||
|
+ const grub_size_t signature_size, const grub_packed_guid_t *guid,
|
||||||
|
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
|
||||||
|
+{
|
||||||
|
+ grub_esd_t *esd;
|
||||||
|
+ grub_pks_sd_t *signature = *pks_sd;
|
||||||
|
+ grub_uint32_t entries = *pks_sd_entries;
|
||||||
|
+ grub_size_t data_size, offset = 0;
|
||||||
|
+
|
||||||
|
+ /* Reads the ESD from ESL. */
|
||||||
|
+ while (esl_size > 0)
|
||||||
|
+ {
|
||||||
|
+ esd = (grub_esd_t *) (esl_data + offset);
|
||||||
|
+ data_size = signature_size - sizeof (grub_esd_t);
|
||||||
|
+
|
||||||
|
+ signature = grub_realloc (signature, (entries + 1) * sizeof (grub_pks_sd_t));
|
||||||
|
+ if (signature == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ signature[entries].data = grub_malloc (data_size * sizeof (grub_uint8_t));
|
||||||
|
+ if (signature[entries].data == NULL)
|
||||||
|
+ {
|
||||||
|
+ /* Allocated memory will be freed by grub_pks_free_data(). */
|
||||||
|
+ *pks_sd = signature;
|
||||||
|
+ *pks_sd_entries = entries + 1;
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_memcpy (signature[entries].data, esd->signature_data, data_size);
|
||||||
|
+ signature[entries].data_size = data_size;
|
||||||
|
+ signature[entries].guid = *guid;
|
||||||
|
+ entries++;
|
||||||
|
+ esl_size -= signature_size;
|
||||||
|
+ offset += signature_size;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *pks_sd = signature;
|
||||||
|
+ *pks_sd_entries = entries;
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Extract the ESD after removing the ESL header from ESL. */
|
||||||
|
+static grub_err_t
|
||||||
|
+esl_to_esd (const grub_uint8_t *esl_data, grub_size_t *next_esl,
|
||||||
|
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
|
||||||
|
+{
|
||||||
|
+ grub_packed_guid_t guid;
|
||||||
|
+ grub_esl_t *esl;
|
||||||
|
+ grub_size_t offset, esl_size, signature_size, signature_header_size;
|
||||||
|
+
|
||||||
|
+ /* Convert the ESL data into the ESL. */
|
||||||
|
+ esl = (grub_esl_t *) esl_data;
|
||||||
|
+ if (*next_esl < sizeof (grub_esl_t) || esl == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_BUG, "invalid ESL");
|
||||||
|
+
|
||||||
|
+ esl_size = grub_le_to_cpu32 (esl->signature_list_size);
|
||||||
|
+ signature_header_size = grub_le_to_cpu32 (esl->signature_header_size);
|
||||||
|
+ signature_size = grub_le_to_cpu32 (esl->signature_size);
|
||||||
|
+ grub_memcpy (&guid, &esl->signature_type, sizeof (grub_packed_guid_t));
|
||||||
|
+
|
||||||
|
+ if (esl_size < sizeof (grub_esl_t) || esl_size > *next_esl)
|
||||||
|
+ return grub_error (GRUB_ERR_BUG, "invalid ESL size (%u)\n", esl_size);
|
||||||
|
+
|
||||||
|
+ *next_esl = esl_size;
|
||||||
|
+ offset = sizeof (grub_esl_t) + signature_header_size;
|
||||||
|
+ esl_size = esl_size - offset;
|
||||||
|
+
|
||||||
|
+ return _esl_to_esd (esl_data + offset, esl_size, signature_size, &guid,
|
||||||
|
+ pks_sd, pks_sd_entries);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Import the EFI Signature Database (ESD) and the number of ESD from the ESL
|
||||||
|
+ * into the pks_sd buffer and pks_sd entries.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+pks_sd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
|
||||||
|
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_size_t next_esl = esl_size;
|
||||||
|
+
|
||||||
|
+ do
|
||||||
|
+ {
|
||||||
|
+ rc = esl_to_esd (esl_data, &next_esl, pks_sd, pks_sd_entries);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ esl_data += next_esl;
|
||||||
|
+ esl_size -= next_esl;
|
||||||
|
+ next_esl = esl_size;
|
||||||
|
+ }
|
||||||
|
+ while (esl_size > 0);
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Read the secure boot version from PKS as an object. Caller must free result. */
|
||||||
|
+static grub_err_t
|
||||||
|
+read_sbversion_from_pks (grub_uint8_t **out)
|
||||||
|
+{
|
||||||
|
+ grub_int32_t rc;
|
||||||
|
+ grub_uint32_t outlen = 0, policy = 0;
|
||||||
|
+
|
||||||
|
+ *out = grub_malloc (pks_max_object_size);
|
||||||
|
+ if (*out == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ rc = grub_ieee1275_pks_read_object (GRUB_PKS_CONSUMER_FW, GRUB_SB_VERSION_KEY_NAME,
|
||||||
|
+ GRUB_SB_VERSION_KEY_LEN, pks_max_object_size, *out,
|
||||||
|
+ &outlen, &policy);
|
||||||
|
+ if (rc < 0)
|
||||||
|
+ {
|
||||||
|
+ grub_free (*out);
|
||||||
|
+ return grub_error (GRUB_ERR_READ_ERROR, "SB version read failed (%d)\n", rc);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (outlen != 1 || (**out >= 2))
|
||||||
|
+ {
|
||||||
|
+ grub_free (*out);
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_NUMBER, "found unexpected SB version: %u\n", **out);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Reads the secure boot variable from PKS, unpacks it, read the ESD from ESL,
|
||||||
|
+ * and store the information in the pks_sd buffer.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+read_sbvar_from_pks (const grub_uint32_t sbvarflags, const grub_uint32_t sbvartype,
|
||||||
|
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
|
||||||
|
+{
|
||||||
|
+ grub_int32_t rc;
|
||||||
|
+ grub_err_t err = GRUB_ERR_NONE;
|
||||||
|
+ grub_uint8_t *esl_data = NULL;
|
||||||
|
+ grub_size_t esl_data_size = 0;
|
||||||
|
+
|
||||||
|
+ esl_data = grub_malloc (pks_max_object_size);
|
||||||
|
+ if (esl_data == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ rc = grub_ieee1275_pks_read_sbvar (sbvarflags, sbvartype, pks_max_object_size,
|
||||||
|
+ esl_data, &esl_data_size);
|
||||||
|
+ if (rc == IEEE1275_CELL_NOT_FOUND)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "secure boot variable %s not found (%d)",
|
||||||
|
+ (sbvartype == GRUB_PKS_SBVAR_DB) ? "db" : "dbx", rc);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ else if (rc < 0)
|
||||||
|
+ {
|
||||||
|
+ err = grub_error (GRUB_ERR_READ_ERROR, "secure boot variable %s reading (%d)",
|
||||||
|
+ (sbvartype == GRUB_PKS_SBVAR_DB) ? "db" : "dbx", rc);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (esl_data_size > 0)
|
||||||
|
+ err = pks_sd_from_esl (esl_data, esl_data_size, pks_sd, pks_sd_entries);
|
||||||
|
+ else
|
||||||
|
+ err = GRUB_ERR_BAD_NUMBER;
|
||||||
|
+
|
||||||
|
+ fail:
|
||||||
|
+ grub_free (esl_data);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Test the availability of PKS support. If PKS support is avaialble and objects
|
||||||
|
+ * present, it reads the secure boot version (SB_VERSION) from PKS.
|
||||||
|
+ *
|
||||||
|
+ * SB_VERSION: Key Management Mode
|
||||||
|
+ * 1 - Enable dynamic key management mode. Read the db and dbx variables from PKS,
|
||||||
|
+ * and use them for signature verification.
|
||||||
|
+ * 0 - Enable static key management mode. Read keys from the GRUB ELF Note and use
|
||||||
|
+ * it for signature verification.
|
||||||
|
+ */
|
||||||
|
+static bool
|
||||||
|
+is_pks_present (void)
|
||||||
|
+{
|
||||||
|
+ grub_err_t err;
|
||||||
|
+ grub_int32_t rc;
|
||||||
|
+ grub_uint8_t *data = NULL;
|
||||||
|
+ bool ret = false;
|
||||||
|
+
|
||||||
|
+ rc = grub_ieee1275_test (GRUB_PKS_MAX_OBJ_INTERFACE);
|
||||||
|
+ if (rc < 0)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_FIRMWARE, "firmware doesn't have PKS support\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size);
|
||||||
|
+ if (rc < 0)
|
||||||
|
+ {
|
||||||
|
+ grub_error (GRUB_ERR_BAD_NUMBER, "PKS support is there but it has zero objects\n");
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ err = read_sbversion_from_pks (&data);
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If *data == 1, use dynamic key management and read the keys from the PKS.
|
||||||
|
+ * Else, use static key management and read the keys from the GRUB ELF Note.
|
||||||
|
+ */
|
||||||
|
+ ret = ((*data == 1) ? true : false);
|
||||||
|
+
|
||||||
|
+ grub_free (data);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Free allocated memory. */
|
||||||
|
+void
|
||||||
|
+grub_pks_free_data (void)
|
||||||
|
+{
|
||||||
|
+ grub_size_t i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < pks_keystore.db_entries; i++)
|
||||||
|
+ grub_free (pks_keystore.db[i].data);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < pks_keystore.dbx_entries; i++)
|
||||||
|
+ grub_free (pks_keystore.dbx[i].data);
|
||||||
|
+
|
||||||
|
+ grub_free (pks_keystore.db);
|
||||||
|
+ grub_free (pks_keystore.dbx);
|
||||||
|
+ grub_memset (&pks_keystore, 0, sizeof (grub_pks_t));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+grub_pks_t *
|
||||||
|
+grub_pks_get_keystore (void)
|
||||||
|
+{
|
||||||
|
+ return (pks_use_keystore == true) ? &pks_keystore : NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Initialization of the Platform KeyStore. */
|
||||||
|
+void
|
||||||
|
+grub_pks_keystore_init (void)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc_db, rc_dbx;
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("ieee1275", "trying to load Platform KeyStore\n");
|
||||||
|
+
|
||||||
|
+ if (is_pks_present () == false)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("ieee1275", "Platform PKS is not available\n");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * When read db from PKS, there are three scenarios
|
||||||
|
+ * 1. db fully loaded from PKS
|
||||||
|
+ * 2. db partially loaded from PKS
|
||||||
|
+ * 3. no keys are loaded from db (if db does not exist in PKS), default to
|
||||||
|
+ * built-in keys (static keys)
|
||||||
|
+ * each of these scenarios, the db keys are checked against dbx.
|
||||||
|
+ */
|
||||||
|
+ rc_db = read_sbvar_from_pks (0, GRUB_PKS_SBVAR_DB, &pks_keystore.db, &pks_keystore.db_entries);
|
||||||
|
+ if (rc_db == GRUB_ERR_FILE_NOT_FOUND)
|
||||||
|
+ pks_keystore.db_exists = false;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Read dbx from PKS. If dbx is not completely loaded from PKS, then this
|
||||||
|
+ * could lead to the loading of vulnerable GRUB modules and kernel binaries.
|
||||||
|
+ * So, this should be prevented by freeing up loaded dbx and db.
|
||||||
|
+ */
|
||||||
|
+ rc_dbx = read_sbvar_from_pks (0, GRUB_PKS_SBVAR_DBX, &pks_keystore.dbx, &pks_keystore.dbx_entries);
|
||||||
|
+ if (rc_dbx == GRUB_ERR_FILE_NOT_FOUND || rc_dbx == GRUB_ERR_BAD_NUMBER)
|
||||||
|
+ rc_dbx = GRUB_ERR_NONE;
|
||||||
|
+
|
||||||
|
+ if (rc_dbx != GRUB_ERR_NONE)
|
||||||
|
+ grub_pks_free_data ();
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * At this point, it's evident that PKS infrastructure exists, so the PKS
|
||||||
|
+ * keystore must be used for validating appended signatures.
|
||||||
|
+ */
|
||||||
|
+ pks_use_keystore = true;
|
||||||
|
+}
|
||||||
|
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
|
||||||
|
index db0ec5f..17aecf2 100644
|
||||||
|
--- a/include/grub/ieee1275/ieee1275.h
|
||||||
|
+++ b/include/grub/ieee1275/ieee1275.h
|
||||||
|
@@ -24,6 +24,9 @@
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/machine/ieee1275.h>
|
||||||
|
|
||||||
|
+#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1)
|
||||||
|
+#define IEEE1275_CELL_NOT_FOUND ((grub_int32_t) -7)
|
||||||
|
+
|
||||||
|
#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0)
|
||||||
|
#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1)
|
||||||
|
|
||||||
|
diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h
|
||||||
|
index 4eb2070..4b9966d 100644
|
||||||
|
--- a/include/grub/powerpc/ieee1275/ieee1275.h
|
||||||
|
+++ b/include/grub/powerpc/ieee1275/ieee1275.h
|
||||||
|
@@ -28,4 +28,40 @@ typedef grub_uint32_t grub_ieee1275_cell_t;
|
||||||
|
#define PRIxGRUB_IEEE1275_CELL_T PRIxGRUB_UINT32_T
|
||||||
|
#define PRIuGRUB_IEEE1275_CELL_T PRIuGRUB_UINT32_T
|
||||||
|
|
||||||
|
+#ifdef __powerpc__
|
||||||
|
+/* The maximum object size interface name for a PKS object. */
|
||||||
|
+#define GRUB_PKS_MAX_OBJ_INTERFACE "pks-max-object-size"
|
||||||
|
+
|
||||||
|
+/* PKS read object and read sbvar interface name. */
|
||||||
|
+#define GRUB_PKS_READ_OBJ_INTERFACE "pks-read-object"
|
||||||
|
+#define GRUB_PKS_READ_SBVAR_INTERFACE "pks-read-sbvar"
|
||||||
|
+
|
||||||
|
+/* PKS read object label for secure boot version. */
|
||||||
|
+#define GRUB_SB_VERSION_KEY_NAME "SB_VERSION"
|
||||||
|
+#define GRUB_SB_VERSION_KEY_LEN (sizeof (GRUB_SB_VERSION_KEY_NAME) - 1)
|
||||||
|
+
|
||||||
|
+/* PKS consumer type for firmware. */
|
||||||
|
+#define GRUB_PKS_CONSUMER_FW ((grub_uint32_t) 1)
|
||||||
|
+
|
||||||
|
+/* PKS read secure boot variable request type for db and dbx. */
|
||||||
|
+#define GRUB_PKS_SBVAR_DB ((grub_uint32_t) 1)
|
||||||
|
+#define GRUB_PKS_SBVAR_DBX ((grub_uint32_t) 2)
|
||||||
|
+
|
||||||
|
+extern grub_int32_t
|
||||||
|
+grub_ieee1275_test (const char *interface_name);
|
||||||
|
+
|
||||||
|
+extern grub_int32_t
|
||||||
|
+grub_ieee1275_pks_max_object_size (grub_uint32_t *result);
|
||||||
|
+
|
||||||
|
+extern grub_int32_t
|
||||||
|
+grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label,
|
||||||
|
+ const grub_uint32_t label_len, const grub_uint32_t buffer_len,
|
||||||
|
+ grub_uint8_t *buffer, grub_uint32_t *data_len,
|
||||||
|
+ grub_uint32_t *policies);
|
||||||
|
+
|
||||||
|
+extern grub_int32_t
|
||||||
|
+grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type,
|
||||||
|
+ const grub_uint32_t buffer_len, grub_uint8_t *buffer,
|
||||||
|
+ grub_size_t *data_len);
|
||||||
|
+#endif /* __powerpc__ */
|
||||||
|
#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
|
||||||
|
diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h b/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..931ada2
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/grub/powerpc/ieee1275/platform_keystore.h
|
||||||
|
@@ -0,0 +1,123 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This
|
||||||
|
+ * program and the accompanying materials are licensed and made available
|
||||||
|
+ * under the terms and conditions of the 2-Clause BSD License which
|
||||||
|
+ * accompanies this distribution.
|
||||||
|
+ *
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions are met:
|
||||||
|
+ *
|
||||||
|
+ * 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
+ * this list of conditions and the following disclaimer.
|
||||||
|
+ *
|
||||||
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
+ * notice, this list of conditions and the following disclaimer in the
|
||||||
|
+ * documentation and/or other materials provided with the distribution.
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
+ *
|
||||||
|
+ * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore),
|
||||||
|
+ * the ImageAuthentication.h file under it, and here's the copyright and license.
|
||||||
|
+ *
|
||||||
|
+ * MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2022, 2023, 2024, 2025 IBM Corp.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef PLATFORM_KEYSTORE_HEADER
|
||||||
|
+#define PLATFORM_KEYSTORE_HEADER 1
|
||||||
|
+
|
||||||
|
+#include <grub/symbol.h>
|
||||||
|
+#include <grub/mm.h>
|
||||||
|
+#include <grub/types.h>
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_SIGNATURE_DATA
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ *
|
||||||
|
+ * The structure of an EFI Signature Database (ESD). */
|
||||||
|
+struct grub_esd
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * An identifier which identifies the agent which added the signature to
|
||||||
|
+ * the list.
|
||||||
|
+ */
|
||||||
|
+ grub_packed_guid_t signature_owner;
|
||||||
|
+ /* The format of the signature is defined by the SignatureType. */
|
||||||
|
+ grub_uint8_t signature_data[];
|
||||||
|
+} GRUB_PACKED;
|
||||||
|
+typedef struct grub_esd grub_esd_t;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_SIGNATURE_LIST
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ *
|
||||||
|
+ * The structure of an EFI Signature List (ESL). */
|
||||||
|
+struct grub_esl
|
||||||
|
+{
|
||||||
|
+ /* Type of the signature. GUID signature types are defined in below. */
|
||||||
|
+ grub_packed_guid_t signature_type;
|
||||||
|
+ /* Total size of the signature list, including this header. */
|
||||||
|
+ grub_uint32_t signature_list_size;
|
||||||
|
+ /* Size of the signature header which precedes the array of signatures. */
|
||||||
|
+ grub_uint32_t signature_header_size;
|
||||||
|
+ /* Size of each signature.*/
|
||||||
|
+ grub_uint32_t signature_size;
|
||||||
|
+} GRUB_PACKED;
|
||||||
|
+typedef struct grub_esl grub_esl_t;
|
||||||
|
+
|
||||||
|
+/* The structure of a PKS Signature Database (SD). */
|
||||||
|
+struct grub_pks_sd
|
||||||
|
+{
|
||||||
|
+ grub_packed_guid_t guid; /* Signature type. */
|
||||||
|
+ grub_uint8_t *data; /* Signature data. */
|
||||||
|
+ grub_size_t data_size; /* Size of signature data. */
|
||||||
|
+} GRUB_PACKED;
|
||||||
|
+typedef struct grub_pks_sd grub_pks_sd_t;
|
||||||
|
+
|
||||||
|
+/* The structure of a Platform KeyStore (PKS). */
|
||||||
|
+struct grub_pks
|
||||||
|
+{
|
||||||
|
+ grub_pks_sd_t *db; /* Signature database. */
|
||||||
|
+ grub_pks_sd_t *dbx; /* Forbidden signature database. */
|
||||||
|
+ grub_uint32_t db_entries; /* Size of signature database. */
|
||||||
|
+ grub_uint32_t dbx_entries;/* Size of forbidden signature database. */
|
||||||
|
+ bool db_exists; /* Flag to indicate if the db exists or not in PKS. */
|
||||||
|
+};
|
||||||
|
+typedef struct grub_pks grub_pks_t;
|
||||||
|
+
|
||||||
|
+#if defined(__powerpc__)
|
||||||
|
+/* Initialization of the Platform Keystore. */
|
||||||
|
+extern void
|
||||||
|
+grub_pks_keystore_init (void);
|
||||||
|
+
|
||||||
|
+/* Platform KeyStore db and dbx. */
|
||||||
|
+extern grub_pks_t *
|
||||||
|
+EXPORT_FUNC (grub_pks_get_keystore) (void);
|
||||||
|
+
|
||||||
|
+/* Free allocated memory. */
|
||||||
|
+extern void
|
||||||
|
+EXPORT_FUNC (grub_pks_free_data) (void);
|
||||||
|
+#else
|
||||||
|
+static inline grub_pks_t *
|
||||||
|
+grub_pks_get_keystore (void)
|
||||||
|
+{
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline void
|
||||||
|
+grub_pks_free_data (void)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+#endif /* __powerpc__ */
|
||||||
|
+#endif
|
||||||
144
0398-appended-signatures-Introducing-key-management-envir.patch
Normal file
144
0398-appended-signatures-Introducing-key-management-envir.patch
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:57 +0530
|
||||||
|
Subject: [PATCH] appended signatures: Introducing key management environment
|
||||||
|
variable
|
||||||
|
|
||||||
|
Introducing the appended signature key management environment variable. It is
|
||||||
|
automatically set to either "static" or "dynamic" based on the Platform KeyStore.
|
||||||
|
|
||||||
|
"static": Enforce static key management signature verification. This is the
|
||||||
|
default. When the GRUB is locked down, user cannot change the value
|
||||||
|
by setting the appendedsig_key_mgmt variable back to "dynamic".
|
||||||
|
|
||||||
|
"dynamic": Enforce dynamic key management signature verification. When the GRUB
|
||||||
|
is locked down, user cannot change the value by setting the
|
||||||
|
appendedsig_key_mgmt variable back to "static".
|
||||||
|
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.c | 75 ++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 75 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
index e53efd2..ca54c90 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
#include <libtasn1.h>
|
||||||
|
#include <grub/env.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
+#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||||
|
|
||||||
|
#include "appendedsig.h"
|
||||||
|
|
||||||
|
@@ -94,6 +95,16 @@ static sb_database_t db = {.certs = NULL, .cert_entries = 0};
|
||||||
|
*/
|
||||||
|
static bool check_sigs = false;
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * append_key_mgmt: Key Management Modes
|
||||||
|
+ * False: Static key management (use built-in Keys). This is default.
|
||||||
|
+ * True: Dynamic key management (use Platform KeySotre).
|
||||||
|
+ */
|
||||||
|
+static bool append_key_mgmt = false;
|
||||||
|
+
|
||||||
|
+/* Platform KeyStore db and dbx. */
|
||||||
|
+static grub_pks_t *pks_keystore;
|
||||||
|
+
|
||||||
|
static grub_ssize_t
|
||||||
|
pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
|
||||||
|
{
|
||||||
|
@@ -469,6 +480,46 @@ grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), const cha
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static const char *
|
||||||
|
+grub_env_read_key_mgmt (struct grub_env_var *var __attribute__ ((unused)),
|
||||||
|
+ const char *val __attribute__ ((unused)))
|
||||||
|
+{
|
||||||
|
+ if (append_key_mgmt == true)
|
||||||
|
+ return "dynamic";
|
||||||
|
+
|
||||||
|
+ return "static";
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+grub_env_write_key_mgmt (struct grub_env_var *var __attribute__ ((unused)), const char *val)
|
||||||
|
+{
|
||||||
|
+ char *ret;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Do not allow the value to be changed if signature verification is enabled
|
||||||
|
+ * (check_sigs is set to true) and GRUB is locked down.
|
||||||
|
+ */
|
||||||
|
+ if (check_sigs == true && grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
|
||||||
|
+ {
|
||||||
|
+ ret = grub_strdup (grub_env_read_key_mgmt (NULL, NULL));
|
||||||
|
+ if (ret == NULL)
|
||||||
|
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (grub_strcmp (val, "dynamic") == 0)
|
||||||
|
+ append_key_mgmt = true;
|
||||||
|
+ else if (grub_strcmp (val, "static") == 0)
|
||||||
|
+ append_key_mgmt = false;
|
||||||
|
+
|
||||||
|
+ ret = grub_strdup (grub_env_read_key_mgmt (NULL, NULL));
|
||||||
|
+ if (ret == NULL)
|
||||||
|
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static grub_err_t
|
||||||
|
appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type type,
|
||||||
|
void **context __attribute__ ((unused)), enum grub_verify_flags *flags)
|
||||||
|
@@ -540,6 +591,11 @@ GRUB_MOD_INIT (appendedsig)
|
||||||
|
if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
|
||||||
|
check_sigs = true;
|
||||||
|
|
||||||
|
+ /* If PKS keystore is available, use dynamic key management. */
|
||||||
|
+ pks_keystore = grub_pks_get_keystore ();
|
||||||
|
+ if (pks_keystore != NULL)
|
||||||
|
+ append_key_mgmt = true;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* This is appended signature verification environment variable. It is
|
||||||
|
* automatically set to either "no" or "yes" based on the ’ibm,secure-boot’
|
||||||
|
@@ -554,6 +610,23 @@ GRUB_MOD_INIT (appendedsig)
|
||||||
|
grub_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec);
|
||||||
|
grub_env_export ("check_appended_signatures");
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * This is appended signature key management environment variable. It is
|
||||||
|
+ * automatically set to either "static" or "dynamic" based on the
|
||||||
|
+ * Platform KeyStore.
|
||||||
|
+ *
|
||||||
|
+ * "static": Enforce static key management signature verification. This is
|
||||||
|
+ * the default. When the GRUB is locked down, user cannot change
|
||||||
|
+ * the value by setting the appendedsig_key_mgmt variable back to
|
||||||
|
+ * "dynamic".
|
||||||
|
+ *
|
||||||
|
+ * "dynamic": Enforce dynamic key management signature verification. When the
|
||||||
|
+ * GRUB is locked down, user cannot change the value by setting the
|
||||||
|
+ * appendedsig_key_mgmt variable back to "static".
|
||||||
|
+ */
|
||||||
|
+ grub_register_variable_hook ("appendedsig_key_mgmt", grub_env_read_key_mgmt, grub_env_write_key_mgmt);
|
||||||
|
+ grub_env_export ("appendedsig_key_mgmt");
|
||||||
|
+
|
||||||
|
rc = grub_asn1_init ();
|
||||||
|
if (rc != ASN1_SUCCESS)
|
||||||
|
grub_fatal ("error initing ASN.1 data structures: %d: %s\n", rc, asn1_strerror (rc));
|
||||||
|
@@ -577,5 +650,7 @@ GRUB_MOD_FINI (appendedsig)
|
||||||
|
free_db_list ();
|
||||||
|
grub_register_variable_hook ("check_appended_signatures", NULL, NULL);
|
||||||
|
grub_env_unset ("check_appended_signatures");
|
||||||
|
+ grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL);
|
||||||
|
+ grub_env_unset ("appendedsig_key_mgmt");
|
||||||
|
grub_verifier_unregister (&grub_appendedsig_verifier);
|
||||||
|
}
|
||||||
689
0399-appended-signatures-Create-db-and-dbx-lists.patch
Normal file
689
0399-appended-signatures-Create-db-and-dbx-lists.patch
Normal file
@ -0,0 +1,689 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:58 +0530
|
||||||
|
Subject: [PATCH] appended signatures: Create db and dbx lists
|
||||||
|
|
||||||
|
If secure boot is enabled with static key management mode, the trusted
|
||||||
|
certificates will be extracted from the GRUB ELF Note and added to db list.
|
||||||
|
|
||||||
|
If secure boot is enabled with dynamic key management mode, the trusted
|
||||||
|
certificates and certificate/binary hash will be extracted from the PKS
|
||||||
|
and added to db list. The distrusted certificates, certificate/binary hash
|
||||||
|
are read from the PKS and added to dbx list. Both dbx and db lists usage is
|
||||||
|
added by a subsequent patch.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
- If db does not exist in the PKS storage, then read the static keys as a db
|
||||||
|
default keys from the GRUB ELF Note and add them into the db list.
|
||||||
|
- If the certificate or the certificate hash exists in the dbx list, then do not
|
||||||
|
add that certificate/certificate hash to the db list.
|
||||||
|
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.c | 407 +++++++++++++++++++++++++--
|
||||||
|
include/grub/efi/pks.h | 112 ++++++++
|
||||||
|
include/grub/types.h | 4 +
|
||||||
|
3 files changed, 506 insertions(+), 17 deletions(-)
|
||||||
|
create mode 100644 include/grub/efi/pks.h
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
index ca54c90..0c4c788 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
#include <grub/env.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||||
|
+#include <grub/efi/pks.h>
|
||||||
|
|
||||||
|
#include "appendedsig.h"
|
||||||
|
|
||||||
|
@@ -46,6 +47,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
#define SIG_MAGIC "~Module signature appended~\n"
|
||||||
|
#define SIG_MAGIC_SIZE ((sizeof(SIG_MAGIC) - 1))
|
||||||
|
|
||||||
|
+/* SHA256, SHA384 and SHA512 hash sizes. */
|
||||||
|
+#define SHA256_HASH_SIZE 32
|
||||||
|
+#define SHA384_HASH_SIZE 48
|
||||||
|
+#define SHA512_HASH_SIZE 64
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* This structure is extracted from scripts/sign-file.c in the linux kernel
|
||||||
|
* source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible.
|
||||||
|
@@ -79,11 +85,23 @@ struct sb_database
|
||||||
|
{
|
||||||
|
grub_x509_cert_t *certs; /* Certificates. */
|
||||||
|
grub_uint32_t cert_entries; /* Number of certificates. */
|
||||||
|
+ grub_uint8_t **hashes; /* Certificate/binary hashes. */
|
||||||
|
+ grub_size_t *hash_sizes; /* Sizes of certificate/binary hashes. */
|
||||||
|
+ grub_uint32_t hash_entries; /* Number of certificate/binary hashes. */
|
||||||
|
+ bool is_db; /* Flag to indicate the db/dbx list. */
|
||||||
|
};
|
||||||
|
typedef struct sb_database sb_database_t;
|
||||||
|
|
||||||
|
/* The db list is used to validate appended signatures. */
|
||||||
|
-static sb_database_t db = {.certs = NULL, .cert_entries = 0};
|
||||||
|
+static sb_database_t db = {.certs = NULL, .cert_entries = 0, .hashes = NULL,
|
||||||
|
+ .hash_sizes = NULL, .hash_entries = 0, .is_db = true};
|
||||||
|
+/*
|
||||||
|
+ * The dbx list is used to ensure that the distrusted certificates or GRUB
|
||||||
|
+ * modules/kernel binaries are rejected during appended signatures/hashes
|
||||||
|
+ * validation.
|
||||||
|
+ */
|
||||||
|
+static sb_database_t dbx = {.certs = NULL, .cert_entries = 0, .hashes = NULL,
|
||||||
|
+ .hash_sizes = NULL, .hash_entries = 0, .is_db = false};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signature verification flag (check_sigs).
|
||||||
|
@@ -118,6 +136,169 @@ static struct grub_fs pseudo_fs = {
|
||||||
|
.fs_read = pseudo_read
|
||||||
|
};
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * GUID can be used to determine the hashing function and generate the hash using
|
||||||
|
+ * determined hashing function.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+get_hash (const grub_packed_guid_t *guid, const grub_uint8_t *data, const grub_size_t data_size,
|
||||||
|
+ grub_uint8_t *hash, grub_size_t *hash_size)
|
||||||
|
+{
|
||||||
|
+ gcry_md_spec_t *hash_func = NULL;
|
||||||
|
+
|
||||||
|
+ if (guid == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "GUID is not available");
|
||||||
|
+
|
||||||
|
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0)
|
||||||
|
+ hash_func = &_gcry_digest_spec_sha256;
|
||||||
|
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0)
|
||||||
|
+ hash_func = &_gcry_digest_spec_sha384;
|
||||||
|
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0)
|
||||||
|
+ hash_func = &_gcry_digest_spec_sha512;
|
||||||
|
+ else
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "unsupported GUID hash");
|
||||||
|
+
|
||||||
|
+ grub_crypto_hash (hash_func, hash, data, data_size);
|
||||||
|
+ *hash_size = hash_func->mdlen;
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_err_t
|
||||||
|
+generate_cert_hash (const grub_size_t cert_hash_size, const grub_uint8_t *data,
|
||||||
|
+ const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size)
|
||||||
|
+{
|
||||||
|
+ grub_packed_guid_t guid = { 0 };
|
||||||
|
+
|
||||||
|
+ /* support SHA256, SHA384 and SHA512 for certificate hash */
|
||||||
|
+ if (cert_hash_size == SHA256_HASH_SIZE)
|
||||||
|
+ grub_memcpy (&guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_PACKED_GUID_SIZE);
|
||||||
|
+ else if (cert_hash_size == SHA384_HASH_SIZE)
|
||||||
|
+ grub_memcpy (&guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_PACKED_GUID_SIZE);
|
||||||
|
+ else if (cert_hash_size == SHA512_HASH_SIZE)
|
||||||
|
+ grub_memcpy (&guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_PACKED_GUID_SIZE);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and "
|
||||||
|
+ "skipped\n", cert_hash_size);
|
||||||
|
+ return GRUB_ERR_UNKNOWN_COMMAND;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return get_hash (&guid, data, data_size, hash, hash_size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Check the hash presence in the db/dbx list. */
|
||||||
|
+static bool
|
||||||
|
+check_hash_presence (grub_uint8_t *const hash, const grub_size_t hash_size,
|
||||||
|
+ const sb_database_t *sb_database)
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < sb_database->hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (sb_database->hashes[i] == NULL)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (hash_size == sb_database->hash_sizes[i] &&
|
||||||
|
+ grub_memcmp (sb_database->hashes[i], hash, hash_size) == 0)
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Add the certificate/binary hash into the db/dbx list. */
|
||||||
|
+static grub_err_t
|
||||||
|
+add_hash (grub_uint8_t *const data, const grub_size_t data_size, sb_database_t *sb_database)
|
||||||
|
+{
|
||||||
|
+ grub_uint8_t **hashes;
|
||||||
|
+ grub_size_t *hash_sizes;
|
||||||
|
+
|
||||||
|
+ if (data == NULL || data_size == 0)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary-hash data or size is not available");
|
||||||
|
+
|
||||||
|
+ if (sb_database->is_db == true)
|
||||||
|
+ {
|
||||||
|
+ if (check_hash_presence (data, data_size, &dbx) == true)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "cannot add a hash (%02x%02x%02x%02x), as it is present in the dbx list\n",
|
||||||
|
+ data[0], data[1], data[2], data[3]);
|
||||||
|
+ return GRUB_ERR_ACCESS_DENIED;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (check_hash_presence (data, data_size, sb_database) == true)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "cannot add a hash (%02x%02x%02x%02x), as it is present in the %s list\n",
|
||||||
|
+ data[0], data[1], data[2], data[3], ((sb_database->is_db == true) ? "db" : "dbx"));
|
||||||
|
+ return GRUB_ERR_EXISTS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hashes = grub_realloc (sb_database->hashes, sizeof (grub_uint8_t *) * (sb_database->hash_entries + 1));
|
||||||
|
+ if (hashes == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ hash_sizes = grub_realloc (sb_database->hash_sizes, sizeof (grub_size_t) * (sb_database->hash_entries + 1));
|
||||||
|
+ if (hash_sizes == NULL)
|
||||||
|
+ {
|
||||||
|
+ /* Allocated memory will be freed by free_db_list()/free_dbx_list(). */
|
||||||
|
+ hashes[sb_database->hash_entries] = NULL;
|
||||||
|
+ sb_database->hashes = hashes;
|
||||||
|
+ sb_database->hash_entries++;
|
||||||
|
+
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ hashes[sb_database->hash_entries] = grub_malloc (data_size);
|
||||||
|
+ if (hashes[sb_database->hash_entries] == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "added the hash %02x%02x%02x%02x... with size of %" PRIuGRUB_SIZE " to the %s list\n",
|
||||||
|
+ data[0], data[1], data[2], data[3], data_size,
|
||||||
|
+ ((sb_database->is_db == true) ? "db" : "dbx"));
|
||||||
|
+
|
||||||
|
+ grub_memcpy (hashes[sb_database->hash_entries], data, data_size);
|
||||||
|
+ hash_sizes[sb_database->hash_entries] = data_size;
|
||||||
|
+ sb_database->hash_sizes = hash_sizes;
|
||||||
|
+ sb_database->hashes = hashes;
|
||||||
|
+ sb_database->hash_entries++;
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+is_hash (const grub_packed_guid_t *guid)
|
||||||
|
+{
|
||||||
|
+ /* GUID type of the binary hash. */
|
||||||
|
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ /* GUID type of the certificate hash. */
|
||||||
|
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0 ||
|
||||||
|
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+is_x509 (const grub_packed_guid_t *guid)
|
||||||
|
+{
|
||||||
|
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_PACKED_GUID_SIZE) == 0)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static bool
|
||||||
|
is_cert_match (const grub_x509_cert_t *cert1, const grub_x509_cert_t *cert2)
|
||||||
|
{
|
||||||
|
@@ -136,7 +317,33 @@ is_cert_match (const grub_x509_cert_t *cert1, const grub_x509_cert_t *cert2)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Check the certificate presence in the db list. */
|
||||||
|
+/* Check the certificate hash presence in the dbx list. */
|
||||||
|
+static bool
|
||||||
|
+is_cert_hash_present_in_dbx (const grub_uint8_t *data, const grub_size_t data_size)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+ grub_size_t cert_hash_size = 0;
|
||||||
|
+ grub_uint8_t cert_hash[GRUB_MAX_HASH_LEN] = { 0 };
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < dbx.hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (dbx.hashes[i] == NULL)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ rc = generate_cert_hash (dbx.hash_sizes[i], data, data_size, cert_hash, &cert_hash_size);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (cert_hash_size == dbx.hash_sizes[i] &&
|
||||||
|
+ grub_memcmp (dbx.hashes[i], cert_hash, cert_hash_size) == 0)
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Check the certificate presence in the db/dbx list. */
|
||||||
|
static bool
|
||||||
|
check_cert_presence (const grub_x509_cert_t *cert_in, const sb_database_t *sb_database)
|
||||||
|
{
|
||||||
|
@@ -149,7 +356,11 @@ check_cert_presence (const grub_x509_cert_t *cert_in, const sb_database_t *sb_da
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Add the certificate into the db list */
|
||||||
|
+/*
|
||||||
|
+ * Add the certificate into the db list if it is not present in the dbx and db
|
||||||
|
+ * list when is_db is true. Add the certificate into the dbx list when is_db is
|
||||||
|
+ * false.
|
||||||
|
+ */
|
||||||
|
static grub_err_t
|
||||||
|
add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
|
||||||
|
sb_database_t *sb_database)
|
||||||
|
@@ -167,30 +378,54 @@ add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
|
||||||
|
rc = grub_x509_cert_parse (data, data_size, cert);
|
||||||
|
if (rc != GRUB_ERR_NONE)
|
||||||
|
{
|
||||||
|
- grub_dprintf ("appendedsig", "cannot add a certificate CN='%s' to the db list\n",
|
||||||
|
- cert->subject);
|
||||||
|
+ grub_dprintf ("appendedsig", "cannot add a certificate CN='%s' to the %s list\n",
|
||||||
|
+ cert->subject, (sb_database->is_db == true) ? "db" : "dbx");
|
||||||
|
grub_free (cert);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Only checks the certificate against dbx if is_db is true when dynamic key
|
||||||
|
+ * management is enabled.
|
||||||
|
+ */
|
||||||
|
+ if (append_key_mgmt == true)
|
||||||
|
+ {
|
||||||
|
+ if (sb_database->is_db == true)
|
||||||
|
+ {
|
||||||
|
+ if (is_cert_hash_present_in_dbx (data, data_size) == true ||
|
||||||
|
+ check_cert_presence (cert, &dbx) == true)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "cannot add a certificate CN='%s', as it is present in the dbx list",
|
||||||
|
+ cert->subject);
|
||||||
|
+ rc = GRUB_ERR_ACCESS_DENIED;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (check_cert_presence (cert, sb_database) == true)
|
||||||
|
{
|
||||||
|
grub_dprintf ("appendedsig",
|
||||||
|
- "cannot add a certificate CN='%s', as it is present in the db list",
|
||||||
|
- cert->subject);
|
||||||
|
- grub_x509_cert_release (cert);
|
||||||
|
- grub_free (cert);
|
||||||
|
-
|
||||||
|
- return GRUB_ERR_EXISTS;
|
||||||
|
+ "cannot add a certificate CN='%s', as it is present in the %s list",
|
||||||
|
+ cert->subject, ((sb_database->is_db == true) ? "db" : "dbx"));
|
||||||
|
+ rc = GRUB_ERR_EXISTS;
|
||||||
|
+ goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
- grub_dprintf ("appendedsig", "added a certificate CN='%s' to the db list\n",
|
||||||
|
- cert->subject);
|
||||||
|
+ grub_dprintf ("appendedsig", "added a certificate CN='%s' to the %s list\n",
|
||||||
|
+ cert->subject, ((sb_database->is_db == true) ? "db" : "dbx"));
|
||||||
|
|
||||||
|
cert->next = sb_database->certs;
|
||||||
|
sb_database->certs = cert;
|
||||||
|
sb_database->cert_entries++;
|
||||||
|
|
||||||
|
+ return rc;
|
||||||
|
+
|
||||||
|
+ fail:
|
||||||
|
+ grub_x509_cert_release (cert);
|
||||||
|
+ grub_free (cert);
|
||||||
|
+
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -382,6 +617,68 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Add the X.509 certificates/binary hash to the db list from PKS. */
|
||||||
|
+static grub_err_t
|
||||||
|
+load_pks2db (void)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < pks_keystore->db_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (is_hash (&pks_keystore->db[i].guid) == true)
|
||||||
|
+ {
|
||||||
|
+ rc = add_hash (pks_keystore->db[i].data,
|
||||||
|
+ pks_keystore->db[i].data_size, &db);
|
||||||
|
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+ else if (is_x509 (&pks_keystore->db[i].guid) == true)
|
||||||
|
+ {
|
||||||
|
+ rc = add_certificate (pks_keystore->db[i].data,
|
||||||
|
+ pks_keystore->db[i].data_size, &db);
|
||||||
|
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ grub_dprintf ("appendedsig", "unsupported signature data type and "
|
||||||
|
+ "skipped (%u)\n", i + 1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Add the certificates and certificate/binary hash to the dbx list from PKS. */
|
||||||
|
+static grub_err_t
|
||||||
|
+load_pks2dbx (void)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < pks_keystore->dbx_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (is_x509 (&pks_keystore->dbx[i].guid) == true)
|
||||||
|
+ {
|
||||||
|
+ rc = add_certificate (pks_keystore->dbx[i].data,
|
||||||
|
+ pks_keystore->dbx[i].data_size, &dbx);
|
||||||
|
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+ else if (is_hash (&pks_keystore->dbx[i].guid) == true)
|
||||||
|
+ {
|
||||||
|
+ rc = add_hash (pks_keystore->dbx[i].data,
|
||||||
|
+ pks_keystore->dbx[i].data_size, &dbx);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ grub_dprintf ("appendedsig", "unsupported signature data type and "
|
||||||
|
+ "skipped (%u)\n", i + 1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Extract the X.509 certificates from the ELF Note header, parse it, and add
|
||||||
|
* it to the db list.
|
||||||
|
@@ -422,11 +719,45 @@ load_elf2db (void)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Extract trusted and distrusted keys from PKS and store them in the db and
|
||||||
|
+ * dbx list.
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+create_dbs_from_pks (void)
|
||||||
|
+{
|
||||||
|
+ grub_err_t err;
|
||||||
|
+
|
||||||
|
+ err = load_pks2dbx ();
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ grub_printf ("warning: dbx list might not be fully populated\n");
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If db does not exist in the PKS storage, then read the static keys as a db
|
||||||
|
+ * default keys from the GRUB ELF Note and add them into the db list.
|
||||||
|
+ */
|
||||||
|
+ if (pks_keystore->db_exists == false)
|
||||||
|
+ load_elf2db ();
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ err = load_pks2db ();
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ grub_printf ("warning: db list might not be fully populated\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_pks_free_data ();
|
||||||
|
+ grub_dprintf ("appendedsig", "the db list now has %u keys\n"
|
||||||
|
+ "the dbx list now has %u keys\n",
|
||||||
|
+ db.hash_entries + db.cert_entries,
|
||||||
|
+ dbx.hash_entries + dbx.cert_entries);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Free db list memory */
|
||||||
|
static void
|
||||||
|
free_db_list (void)
|
||||||
|
{
|
||||||
|
grub_x509_cert_t *cert;
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
|
||||||
|
while (db.certs != NULL)
|
||||||
|
{
|
||||||
|
@@ -436,9 +767,37 @@ free_db_list (void)
|
||||||
|
grub_free (cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ for (i = 0; i < db.hash_entries; i++)
|
||||||
|
+ grub_free (db.hashes[i]);
|
||||||
|
+
|
||||||
|
+ grub_free (db.hashes);
|
||||||
|
+ grub_free (db.hash_sizes);
|
||||||
|
grub_memset (&db, 0, sizeof (sb_database_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Free dbx list memory */
|
||||||
|
+static void
|
||||||
|
+free_dbx_list (void)
|
||||||
|
+{
|
||||||
|
+ grub_x509_cert_t *cert;
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+
|
||||||
|
+ while (dbx.certs != NULL)
|
||||||
|
+ {
|
||||||
|
+ cert = dbx.certs;
|
||||||
|
+ dbx.certs = dbx.certs->next;
|
||||||
|
+ grub_x509_cert_release (cert);
|
||||||
|
+ grub_free (cert);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < dbx.hash_entries; i++)
|
||||||
|
+ grub_free (dbx.hashes[i]);
|
||||||
|
+
|
||||||
|
+ grub_free (dbx.hashes);
|
||||||
|
+ grub_free (dbx.hash_sizes);
|
||||||
|
+ grub_memset (&dbx, 0, sizeof (sb_database_t));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const char *
|
||||||
|
grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)),
|
||||||
|
const char *val __attribute__ ((unused)))
|
||||||
|
@@ -631,10 +990,23 @@ GRUB_MOD_INIT (appendedsig)
|
||||||
|
if (rc != ASN1_SUCCESS)
|
||||||
|
grub_fatal ("error initing ASN.1 data structures: %d: %s\n", rc, asn1_strerror (rc));
|
||||||
|
|
||||||
|
- /* Extract trusted keys from ELF Note and store them in the db. */
|
||||||
|
- load_elf2db ();
|
||||||
|
- grub_dprintf ("appendedsig", "the db list now has %u static keys\n",
|
||||||
|
- db.cert_entries);
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled with the dynamic key management,
|
||||||
|
+ * extract trusted and distrusted keys from PKS and store them in the db
|
||||||
|
+ * and dbx list.
|
||||||
|
+ */
|
||||||
|
+ if (append_key_mgmt == true)
|
||||||
|
+ create_dbs_from_pks ();
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled with the static key management,
|
||||||
|
+ * extract trusted keys from ELF Note and store them in the db list.
|
||||||
|
+ */
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ load_elf2db ();
|
||||||
|
+ grub_dprintf ("appendedsig", "the db list now has %u static keys\n",
|
||||||
|
+ db.cert_entries);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
grub_verifier_register (&grub_appendedsig_verifier);
|
||||||
|
grub_dl_set_persistent (mod);
|
||||||
|
@@ -648,6 +1020,7 @@ GRUB_MOD_FINI (appendedsig)
|
||||||
|
*/
|
||||||
|
|
||||||
|
free_db_list ();
|
||||||
|
+ free_dbx_list ();
|
||||||
|
grub_register_variable_hook ("check_appended_signatures", NULL, NULL);
|
||||||
|
grub_env_unset ("check_appended_signatures");
|
||||||
|
grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL);
|
||||||
|
diff --git a/include/grub/efi/pks.h b/include/grub/efi/pks.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..ff306f5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/grub/efi/pks.h
|
||||||
|
@@ -0,0 +1,112 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This
|
||||||
|
+ * program and the accompanying materials are licensed and made available
|
||||||
|
+ * under the terms and conditions of the 2-Clause BSD License which
|
||||||
|
+ * accompanies this distribution.
|
||||||
|
+ *
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions are met:
|
||||||
|
+ *
|
||||||
|
+ * 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
+ * this list of conditions and the following disclaimer.
|
||||||
|
+ *
|
||||||
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
+ * notice, this list of conditions and the following disclaimer in the
|
||||||
|
+ * documentation and/or other materials provided with the distribution.
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
+ * POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
+ *
|
||||||
|
+ * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore),
|
||||||
|
+ * the ImageAuthentication.h file under it, and here's the copyright and license.
|
||||||
|
+ *
|
||||||
|
+ * MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ *
|
||||||
|
+ * Copyright 2022, 2023, 2024, 2025 IBM Corp.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef PKS_HEADER
|
||||||
|
+#define PKS_HEADER 1
|
||||||
|
+
|
||||||
|
+#include <grub/types.h>
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_X509_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_X509_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0xa159c0a5, 0xe494, 0xa74a, \
|
||||||
|
+ { 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_SHA256_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_SHA256_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0x2616c4c1, 0x4c50, 0x9240, \
|
||||||
|
+ { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_SHA384_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_SHA384_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0x07533eff, 0xd09f, 0xc948, \
|
||||||
|
+ { 0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1 } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_SHA512_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_SHA512_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0xae0f3e09, 0xc4a6, 0x504f, \
|
||||||
|
+ { 0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_X509_SHA256_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_X509_SHA256_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0x92a4d23b, 0xc096, 0x7940, \
|
||||||
|
+ { 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_X509_SHA384_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_X509_SHA384_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0x6e877670, 0xc280, 0xe64e, \
|
||||||
|
+ { 0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * It is derived from EFI_CERT_X509_SHA512_GUID.
|
||||||
|
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
|
||||||
|
+ */
|
||||||
|
+#define GRUB_PKS_CERT_X509_SHA512_GUID \
|
||||||
|
+ (grub_guid_t) \
|
||||||
|
+ { 0x63bf6d44, 0x0225, 0xda4c, \
|
||||||
|
+ { 0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d } \
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/include/grub/types.h b/include/grub/types.h
|
||||||
|
index 59e0302..5f37adb 100644
|
||||||
|
--- a/include/grub/types.h
|
||||||
|
+++ b/include/grub/types.h
|
||||||
|
@@ -380,6 +380,8 @@ struct grub_guid
|
||||||
|
} __attribute__ ((aligned(4)));
|
||||||
|
typedef struct grub_guid grub_guid_t;
|
||||||
|
|
||||||
|
+#define GRUB_GUID_SIZE (sizeof (grub_guid_t))
|
||||||
|
+
|
||||||
|
struct grub_packed_guid
|
||||||
|
{
|
||||||
|
grub_uint32_t data1;
|
||||||
|
@@ -389,4 +391,6 @@ struct grub_packed_guid
|
||||||
|
} GRUB_PACKED;
|
||||||
|
typedef struct grub_packed_guid grub_packed_guid_t;
|
||||||
|
|
||||||
|
+#define GRUB_PACKED_GUID_SIZE (sizeof (grub_packed_guid_t))
|
||||||
|
+
|
||||||
|
#endif /* ! GRUB_TYPES_HEADER */
|
||||||
136
0400-appended-signatures-Using-db-and-dbx-lists-for-signa.patch
Normal file
136
0400-appended-signatures-Using-db-and-dbx-lists-for-signa.patch
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:59 +0530
|
||||||
|
Subject: [PATCH] appended signatures: Using db and dbx lists for signature
|
||||||
|
verification
|
||||||
|
|
||||||
|
Signature verification: verify the kernel against lists of hashes that are
|
||||||
|
either in dbx or db list. If it is not in the dbx list then the trusted keys
|
||||||
|
from the db list are used to verify the signature.
|
||||||
|
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.c | 94 +++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 93 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
index 0c4c788..9cfa1be 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
@@ -521,6 +521,83 @@ extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
|
||||||
|
return grub_pkcs7_data_parse (signed_data, appendedsig_pkcs7_size, &sig->pkcs7);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static grub_err_t
|
||||||
|
+get_binary_hash (const grub_size_t binary_hash_size, const grub_uint8_t *data,
|
||||||
|
+ const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size)
|
||||||
|
+{
|
||||||
|
+ grub_packed_guid_t guid = { 0 };
|
||||||
|
+
|
||||||
|
+ /* support SHA256, SHA384 and SHA512 for binary hash */
|
||||||
|
+ if (binary_hash_size == SHA256_HASH_SIZE)
|
||||||
|
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_PACKED_GUID_SIZE);
|
||||||
|
+ else if (binary_hash_size == SHA384_HASH_SIZE)
|
||||||
|
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_PACKED_GUID_SIZE);
|
||||||
|
+ else if (binary_hash_size == SHA512_HASH_SIZE)
|
||||||
|
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_PACKED_GUID_SIZE);
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and "
|
||||||
|
+ "skipped\n", binary_hash_size);
|
||||||
|
+ return GRUB_ERR_UNKNOWN_COMMAND;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return get_hash (&guid, data, data_size, hash, hash_size);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Verify binary hash against the db and dbx list.
|
||||||
|
+ * The following errors can occur:
|
||||||
|
+ * - GRUB_ERR_BAD_SIGNATURE: indicates that the hash is in dbx list.
|
||||||
|
+ * - GRUB_ERR_EOF: the hash could not be found in the db and dbx list.
|
||||||
|
+ * - GRUB_ERR_NONE: the hash is found in db list.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc = GRUB_ERR_NONE;
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+ grub_size_t hash_size = 0;
|
||||||
|
+ grub_uint8_t hash[GRUB_MAX_HASH_LEN] = { 0 };
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < dbx.hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (dbx.hashes[i] == NULL)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ rc = get_binary_hash (dbx.hash_sizes[i], data, data_size, hash, &hash_size);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (hash_size == dbx.hash_sizes[i] &&
|
||||||
|
+ grub_memcmp (dbx.hashes[i], hash, hash_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "the hash (%02x%02x%02x%02x) is present in the dbx list\n",
|
||||||
|
+ hash[0], hash[1], hash[2], hash[3]);
|
||||||
|
+ return GRUB_ERR_BAD_SIGNATURE;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < db.hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (db.hashes[i] == NULL)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ rc = get_binary_hash (db.hash_sizes[i], data, data_size, hash, &hash_size);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (hash_size == db.hash_sizes[i] &&
|
||||||
|
+ grub_memcmp (db.hashes[i], hash, hash_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "verified with a trusted hash (%02x%02x%02x%02x)\n",
|
||||||
|
+ hash[0], hash[1], hash[2], hash[3]);
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_EOF;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Given a hash value 'hval', of hash specification 'hash', prepare the
|
||||||
|
* S-expressions (sexp) and perform the signature verification.
|
||||||
|
@@ -565,7 +642,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||||
|
grub_pkcs7_signer_t *si;
|
||||||
|
grub_int32_t i;
|
||||||
|
|
||||||
|
- if (!db.cert_entries)
|
||||||
|
+ if (!db.cert_entries && !db.hash_entries)
|
||||||
|
return grub_error (GRUB_ERR_BAD_SIGNATURE, "no trusted keys to verify against");
|
||||||
|
|
||||||
|
err = extract_appended_signature (buf, bufsize, &sig);
|
||||||
|
@@ -574,6 +651,21 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||||
|
|
||||||
|
datasize = bufsize - sig.signature_len;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled with dynamic key management mode,
|
||||||
|
+ * Verify binary hash against the db and dbx list.
|
||||||
|
+ */
|
||||||
|
+ if (append_key_mgmt == true)
|
||||||
|
+ {
|
||||||
|
+ err = verify_binary_hash (buf, datasize);
|
||||||
|
+ if (err == GRUB_ERR_BAD_SIGNATURE)
|
||||||
|
+ {
|
||||||
|
+ grub_pkcs7_data_release (&sig.pkcs7);
|
||||||
|
+ return grub_error (err,
|
||||||
|
+ "failed to verify the binary hash against a trusted binary hash");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Verify signature using trusted keys from db list. */
|
||||||
|
for (i = 0; i < sig.pkcs7.signer_count; i++)
|
||||||
|
{
|
||||||
406
0401-appended-signatures-GRUB-commands-to-manage-the-cert.patch
Normal file
406
0401-appended-signatures-GRUB-commands-to-manage-the-cert.patch
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:55:00 +0530
|
||||||
|
Subject: [PATCH] appended signatures: GRUB commands to manage the certificates
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Introducing the following GRUB commands to manage the certificates.
|
||||||
|
|
||||||
|
1. append_list_db:
|
||||||
|
Show the list of trusted certificates from the db list
|
||||||
|
2. append_add_db_cert:
|
||||||
|
Add the trusted certificate to the db list
|
||||||
|
3. append_add_dbx_cert:
|
||||||
|
Add the distrusted certificate to the dbx list
|
||||||
|
4. append_verify:
|
||||||
|
Verify the signed file using db list
|
||||||
|
|
||||||
|
Note that if signature verification (check_appended_signatures) is set to yes,
|
||||||
|
the append_add_db_cert and append_add_dbx_cert commands only accept the file
|
||||||
|
‘X509_certificate’ that is signed with an appended signature.
|
||||||
|
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Tested-by: Sridhar Markonda <sridharm@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.c | 316 +++++++++++++++++++++++++++
|
||||||
|
1 file changed, 316 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
index 9cfa1be..614ebee 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
@@ -123,6 +123,9 @@ static bool append_key_mgmt = false;
|
||||||
|
/* Platform KeyStore db and dbx. */
|
||||||
|
static grub_pks_t *pks_keystore;
|
||||||
|
|
||||||
|
+/* Appended signature size. */
|
||||||
|
+static grub_size_t append_sig_len = 0;
|
||||||
|
+
|
||||||
|
static grub_ssize_t
|
||||||
|
pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
|
||||||
|
{
|
||||||
|
@@ -136,6 +139,65 @@ static struct grub_fs pseudo_fs = {
|
||||||
|
.fs_read = pseudo_read
|
||||||
|
};
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * We cannot use hexdump() to display hash data because it is typically displayed
|
||||||
|
+ * in hexadecimal format, along with an ASCII representation of the same data.
|
||||||
|
+ *
|
||||||
|
+ * Example: sha256 hash data
|
||||||
|
+ * 00000000 52 b5 90 49 64 de 22 d7 4e 5f 4f b4 1b 51 9c 34 |R..Id.".N_O..Q.4|
|
||||||
|
+ * 00000010 b1 96 21 7c 91 78 a5 0d 20 8c e9 5c 22 54 53 f7 |..!|.x.. ..\"TS.|
|
||||||
|
+ *
|
||||||
|
+ * An appended signature only required to display the hexadecimal of the hash data
|
||||||
|
+ * by separating each byte with ":". So, we introduced a new method hexdump_colon
|
||||||
|
+ * to display it.
|
||||||
|
+ *
|
||||||
|
+ * Example: Sha256 hash data
|
||||||
|
+ * 52:b5:90:49:64:de:22:d7:4e:5f:4f:b4:1b:51:9c:34:
|
||||||
|
+ * b1:96:21:7c:91:78:a5:0d:20:8c:e9:5c:22:54:53:f7
|
||||||
|
+ */
|
||||||
|
+static void
|
||||||
|
+hexdump_colon (const grub_uint8_t *data, const grub_size_t length)
|
||||||
|
+{
|
||||||
|
+ grub_size_t i, count = 0;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < length - 1; i++)
|
||||||
|
+ {
|
||||||
|
+ grub_printf ("%02x:", data[i]);
|
||||||
|
+ count++;
|
||||||
|
+ if (count == 16)
|
||||||
|
+ {
|
||||||
|
+ grub_printf ("\n ");
|
||||||
|
+ count = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_printf ("%02x\n", data[i]);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+print_certificate (const grub_x509_cert_t *cert, const grub_uint32_t cert_num)
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+
|
||||||
|
+ grub_printf ("\nCertificate: %u\n", cert_num);
|
||||||
|
+ grub_printf (" Data:\n");
|
||||||
|
+ grub_printf (" Version: %u (0x%u)\n", cert->version + 1, cert->version);
|
||||||
|
+ grub_printf (" Serial Number:\n ");
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < cert->serial_len - 1; i++)
|
||||||
|
+ grub_printf ("%02x:", cert->serial[i]);
|
||||||
|
+
|
||||||
|
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
|
||||||
|
+ grub_printf (" Issuer: %s\n", cert->issuer);
|
||||||
|
+ grub_printf (" Subject: %s\n", cert->subject);
|
||||||
|
+ grub_printf (" Subject Public Key Info:\n");
|
||||||
|
+ grub_printf (" Public Key Algorithm: rsaEncryption\n");
|
||||||
|
+ grub_printf (" RSA Public-Key: (%d bit)\n", cert->modulus_size);
|
||||||
|
+ grub_printf (" Fingerprint: sha256\n ");
|
||||||
|
+ hexdump_colon (&cert->fingerprint[GRUB_FINGERPRINT_SHA256][0],
|
||||||
|
+ grub_strlen ((char *) cert->fingerprint[GRUB_FINGERPRINT_SHA256]));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* GUID can be used to determine the hashing function and generate the hash using
|
||||||
|
* determined hashing function.
|
||||||
|
@@ -429,6 +491,61 @@ add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+_remove_cert_from_db (const grub_x509_cert_t *cert)
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t i = 1;
|
||||||
|
+ grub_x509_cert_t *curr_cert, *prev_cert;
|
||||||
|
+
|
||||||
|
+ for (curr_cert = prev_cert = db.certs; curr_cert != NULL; curr_cert = curr_cert->next, i++)
|
||||||
|
+ {
|
||||||
|
+ if (is_cert_match (curr_cert, cert) == true)
|
||||||
|
+ {
|
||||||
|
+ if (i == 1) /* Match with first certificate in the db list. */
|
||||||
|
+ db.certs = curr_cert->next;
|
||||||
|
+ else
|
||||||
|
+ prev_cert->next = curr_cert->next;
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "removed distrusted certificate with CN: %s from the db list\n",
|
||||||
|
+ curr_cert->subject);
|
||||||
|
+ curr_cert->next = NULL;
|
||||||
|
+ grub_x509_cert_release (curr_cert);
|
||||||
|
+ grub_free (curr_cert);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ prev_cert = curr_cert;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_err_t
|
||||||
|
+remove_cert_from_db (const grub_uint8_t *data, const grub_size_t data_size)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_x509_cert_t *cert;
|
||||||
|
+
|
||||||
|
+ if (data == NULL || data_size == 0)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data or size is not available");
|
||||||
|
+
|
||||||
|
+ cert = grub_zalloc (sizeof (grub_x509_cert_t));
|
||||||
|
+ if (cert == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
|
||||||
|
+
|
||||||
|
+ rc = grub_x509_cert_parse (data, data_size, cert);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "cannot remove an invalid certificate from the db list\n");
|
||||||
|
+ grub_free (cert);
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Remove certificate from the db list. */
|
||||||
|
+ _remove_cert_from_db (cert);
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static grub_err_t
|
||||||
|
file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
|
||||||
|
{
|
||||||
|
@@ -649,6 +766,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||||
|
if (err != GRUB_ERR_NONE)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
+ append_sig_len = sig.signature_len;
|
||||||
|
datasize = bufsize - sig.signature_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -709,6 +827,189 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_verify_signature (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||||
|
+{
|
||||||
|
+ grub_file_t signed_file;
|
||||||
|
+ grub_err_t err;
|
||||||
|
+ grub_uint8_t *signed_data = NULL;
|
||||||
|
+ grub_size_t signed_data_size = 0;
|
||||||
|
+
|
||||||
|
+ if (argc != 1)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
+ "a signed file is expected\nExample:\n\tappend_verify <SIGNED FILE>\n");
|
||||||
|
+
|
||||||
|
+ if (!grub_strlen (args[0]))
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILENAME, "missing signed file");
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("appendedsig", "verifying %s\n", args[0]);
|
||||||
|
+
|
||||||
|
+ signed_file = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
|
||||||
|
+ if (signed_file == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "could not open %s file", args[0]);
|
||||||
|
+
|
||||||
|
+ err = file_read_whole (signed_file, &signed_data, &signed_data_size);
|
||||||
|
+ if (err == GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ err = grub_verify_appended_signature (signed_data, signed_data_size);
|
||||||
|
+ grub_free (signed_data);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ grub_file_close (signed_file);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Checks the trusted certificate against dbx list if dynamic key management is
|
||||||
|
+ * enabled. And add it to the db list if it is not already present.
|
||||||
|
+ *
|
||||||
|
+ * Note: When signature verification is enabled, this command only accepts the
|
||||||
|
+ * trusted certificate that is signed with an appended signature.
|
||||||
|
+ * The signature is verified by the appendedsig module. If verification succeeds,
|
||||||
|
+ * the certificate is added to the db list. Otherwise, an error is posted and
|
||||||
|
+ * the certificate is not added.
|
||||||
|
+ * When signature verification is disabled, it accepts the trusted certificate
|
||||||
|
+ * without an appended signature and add it to the db list.
|
||||||
|
+ *
|
||||||
|
+ * Also, note that the adding of the trusted certificate using this command does
|
||||||
|
+ * not persist across reboots.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_db_cert (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||||
|
+{
|
||||||
|
+ grub_err_t err;
|
||||||
|
+ grub_file_t cert_file;
|
||||||
|
+ grub_uint8_t *cert_data = NULL;
|
||||||
|
+ grub_size_t cert_data_size = 0;
|
||||||
|
+
|
||||||
|
+ if (argc != 1)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
+ "a trusted X.509 certificate file is expected in DER format\n"
|
||||||
|
+ "Example:\n\tappend_add_db_cert <X509_CERTIFICATE>\n");
|
||||||
|
+
|
||||||
|
+ if (!grub_strlen (args[0]))
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILENAME, "missing trusted X.509 certificate file");
|
||||||
|
+
|
||||||
|
+ cert_file = grub_file_open (args[0],
|
||||||
|
+ GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||||
|
+ if (cert_file == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "could not open %s file", args[0]);
|
||||||
|
+
|
||||||
|
+ err = file_read_whole (cert_file, &cert_data, &cert_data_size);
|
||||||
|
+ grub_file_close (cert_file);
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled (check_sigs is set to true), obtain
|
||||||
|
+ * the actual certificate size by subtracting the appended signature size from
|
||||||
|
+ * the certificate size because the certificate has an appended signature, and
|
||||||
|
+ * this actual certificate size is used to get the X.509 certificate.
|
||||||
|
+ */
|
||||||
|
+ if (check_sigs == true)
|
||||||
|
+ cert_data_size -= append_sig_len;
|
||||||
|
+
|
||||||
|
+ err = add_certificate (cert_data, cert_data_size, &db);
|
||||||
|
+ grub_free (cert_data);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Remove the distrusted certificate from the db list if it is already present.
|
||||||
|
+ * And add it to the dbx list if not present when dynamic key management is
|
||||||
|
+ * enabled.
|
||||||
|
+ *
|
||||||
|
+ * Note: When signature verification is enabled, this command only accepts the
|
||||||
|
+ * distrusted certificate that is signed with an appended signature.
|
||||||
|
+ * The signature is verified by the appended sig module. If verification
|
||||||
|
+ * succeeds, the certificate is removed from the db list. Otherwise, an error
|
||||||
|
+ * is posted and the certificate is not removed.
|
||||||
|
+ * When signature verification is disabled, it accepts the distrusted certificate
|
||||||
|
+ * without an appended signature and removes it from the db list.
|
||||||
|
+ *
|
||||||
|
+ * Also, note that the removal of the distrusted certificate using this command
|
||||||
|
+ * does not persist across reboots.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_dbx_cert (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
|
||||||
|
+{
|
||||||
|
+ grub_err_t err;
|
||||||
|
+ grub_file_t cert_file;
|
||||||
|
+ grub_uint8_t *cert_data = NULL;
|
||||||
|
+ grub_size_t cert_data_size = 0;
|
||||||
|
+
|
||||||
|
+ if (argc != 1)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
+ "a distrusted X.509 certificate file is expected in DER format\n"
|
||||||
|
+ "Example:\n\tappend_add_dbx_cert <X509_CERTIFICATE>\n");
|
||||||
|
+
|
||||||
|
+ if (!grub_strlen (args[0]))
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILENAME, "missing distrusted X.509 certificate file");
|
||||||
|
+
|
||||||
|
+ cert_file = grub_file_open (args[0],
|
||||||
|
+ GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||||
|
+ if (cert_file == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "could not open %s file", args[0]);
|
||||||
|
+
|
||||||
|
+ err = file_read_whole (cert_file, &cert_data, &cert_data_size);
|
||||||
|
+ grub_file_close (cert_file);
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled (check_sigs is set to true), obtain
|
||||||
|
+ * the actual certificate size by subtracting the appended signature size from
|
||||||
|
+ * the certificate size because the certificate has an appended signature, and
|
||||||
|
+ * this actual certificate size is used to get the X.509 certificate.
|
||||||
|
+ */
|
||||||
|
+ if (check_sigs == true)
|
||||||
|
+ cert_data_size -= append_sig_len;
|
||||||
|
+
|
||||||
|
+ /* Remove distrusted certificate from the db list if present. */
|
||||||
|
+ err = remove_cert_from_db (cert_data, cert_data_size);
|
||||||
|
+ if (err != GRUB_ERR_NONE)
|
||||||
|
+ {
|
||||||
|
+ grub_free (cert_data);
|
||||||
|
+ return err;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Only add the certificate to the dbx list if dynamic key management is enabled. */
|
||||||
|
+ if (append_key_mgmt == true)
|
||||||
|
+ err = add_certificate (cert_data, cert_data_size, &dbx);
|
||||||
|
+
|
||||||
|
+ grub_free (cert_data);
|
||||||
|
+
|
||||||
|
+ return err;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_list_db (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)),
|
||||||
|
+ char **args __attribute__ ((unused)))
|
||||||
|
+{
|
||||||
|
+ struct x509_certificate *cert;
|
||||||
|
+ grub_uint32_t i, cert_num = 1;
|
||||||
|
+
|
||||||
|
+ for (cert = db.certs; cert != NULL; cert = cert->next, cert_num++)
|
||||||
|
+ print_certificate (cert, cert_num);
|
||||||
|
+
|
||||||
|
+ if (append_key_mgmt == false)
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < db.hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (db.hashes[i] != NULL)
|
||||||
|
+ {
|
||||||
|
+ grub_printf ("\nBinary hash: %u\n", i + 1);
|
||||||
|
+ grub_printf (" Hash: sha%" PRIuGRUB_SIZE "\n ", db.hash_sizes[i] * 8);
|
||||||
|
+ hexdump_colon (db.hashes[i], db.hash_sizes[i]);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Add the X.509 certificates/binary hash to the db list from PKS. */
|
||||||
|
static grub_err_t
|
||||||
|
load_pks2db (void)
|
||||||
|
@@ -1031,6 +1332,8 @@ struct grub_file_verifier grub_appendedsig_verifier = {
|
||||||
|
.write = appendedsig_write,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static grub_command_t cmd_verify, cmd_list_db, cmd_dbx_cert, cmd_db_cert;
|
||||||
|
+
|
||||||
|
GRUB_MOD_INIT (appendedsig)
|
||||||
|
{
|
||||||
|
grub_int32_t rc;
|
||||||
|
@@ -1100,6 +1403,15 @@ GRUB_MOD_INIT (appendedsig)
|
||||||
|
db.cert_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ cmd_verify = grub_register_command ("append_verify", grub_cmd_verify_signature, N_("<SIGNED_FILE>"),
|
||||||
|
+ N_("Verify SIGNED_FILE against the trusted X.509 certificates in the db list"));
|
||||||
|
+ cmd_list_db = grub_register_command ("append_list_db", grub_cmd_list_db, 0,
|
||||||
|
+ N_("Show the list of trusted X.509 certificates from the db list"));
|
||||||
|
+ cmd_db_cert = grub_register_command ("append_add_db_cert", grub_cmd_db_cert, N_("<X509_CERTIFICATE>"),
|
||||||
|
+ N_("Add trusted X509_CERTIFICATE to the db list"));
|
||||||
|
+ cmd_dbx_cert = grub_register_command ("append_add_dbx_cert", grub_cmd_dbx_cert, N_("<X509_CERTIFICATE>"),
|
||||||
|
+ N_("Add distrusted X509_CERTIFICATE to the dbx list"));
|
||||||
|
+
|
||||||
|
grub_verifier_register (&grub_appendedsig_verifier);
|
||||||
|
grub_dl_set_persistent (mod);
|
||||||
|
}
|
||||||
|
@@ -1118,4 +1430,8 @@ GRUB_MOD_FINI (appendedsig)
|
||||||
|
grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL);
|
||||||
|
grub_env_unset ("appendedsig_key_mgmt");
|
||||||
|
grub_verifier_unregister (&grub_appendedsig_verifier);
|
||||||
|
+ grub_unregister_command (cmd_verify);
|
||||||
|
+ grub_unregister_command (cmd_list_db);
|
||||||
|
+ grub_unregister_command (cmd_db_cert);
|
||||||
|
+ grub_unregister_command (cmd_dbx_cert);
|
||||||
|
}
|
||||||
382
0402-appended-signatures-GRUB-commands-to-manage-the-hash.patch
Normal file
382
0402-appended-signatures-GRUB-commands-to-manage-the-hash.patch
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:55:01 +0530
|
||||||
|
Subject: [PATCH] appended signatures: GRUB commands to manage the hashes
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Introducing the following GRUB commands to manage certificate/binary
|
||||||
|
hashes.
|
||||||
|
|
||||||
|
1. append_list_dbx:
|
||||||
|
Show the list of distrusted certificates and binary/certificate
|
||||||
|
hashes from the dbx list.
|
||||||
|
2. append_add_db_hash:
|
||||||
|
Add the trusted binary hash to the db list.
|
||||||
|
3. append_add_dbx_hash:
|
||||||
|
Add the distrusted certificate/binary hash to the dbx list.
|
||||||
|
|
||||||
|
Note that if signature verification (check_appended_signatures) is set to yes,
|
||||||
|
the append_add_db_hash and append_add_dbx_hash commands only accept the file
|
||||||
|
‘hash_file’ that is signed with an appended signature.
|
||||||
|
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Tested-by: Sridhar Markonda <sridharm@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.c | 279 +++++++++++++++++++++++++++
|
||||||
|
include/grub/file.h | 2 +
|
||||||
|
2 files changed, 281 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
index 614ebee..5c53f63 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
@@ -52,6 +52,9 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
#define SHA384_HASH_SIZE 48
|
||||||
|
#define SHA512_HASH_SIZE 64
|
||||||
|
|
||||||
|
+#define OPTION_BINARY_HASH 0
|
||||||
|
+#define OPTION_CERT_HASH 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.
|
||||||
|
@@ -126,6 +129,13 @@ static grub_pks_t *pks_keystore;
|
||||||
|
/* Appended signature size. */
|
||||||
|
static grub_size_t append_sig_len = 0;
|
||||||
|
|
||||||
|
+static const struct grub_arg_option options[] =
|
||||||
|
+{
|
||||||
|
+ {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_PATHNAME},
|
||||||
|
+ {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_PATHNAME},
|
||||||
|
+ {0, 0, 0, 0, 0, 0}
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static grub_ssize_t
|
||||||
|
pseudo_read (struct grub_file *file, char *buf, grub_size_t len)
|
||||||
|
{
|
||||||
|
@@ -546,6 +556,69 @@ remove_cert_from_db (const grub_uint8_t *data, const grub_size_t data_size)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool
|
||||||
|
+cert_fingerprint_match (const grub_uint8_t *hash_data, const grub_size_t hash_data_size,
|
||||||
|
+ const grub_x509_cert_t *cert)
|
||||||
|
+{
|
||||||
|
+ grub_int32_t type;
|
||||||
|
+
|
||||||
|
+ if (hash_data_size == SHA256_HASH_SIZE)
|
||||||
|
+ type = GRUB_FINGERPRINT_SHA256;
|
||||||
|
+ else if (hash_data_size == SHA384_HASH_SIZE)
|
||||||
|
+ type = GRUB_FINGERPRINT_SHA384;
|
||||||
|
+ else if (hash_data_size == SHA512_HASH_SIZE)
|
||||||
|
+ type = GRUB_FINGERPRINT_SHA512;
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "unsupported fingerprint hash type "
|
||||||
|
+ "(%" PRIuGRUB_SIZE ") \n", hash_data_size);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (grub_memcmp (cert->fingerprint[type], hash_data, hash_data_size) == 0)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+remove_hash_from_db (const grub_uint8_t *hash_data, const grub_size_t hash_data_size,
|
||||||
|
+ const bool bin_hash)
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t i;
|
||||||
|
+ grub_x509_cert_t *cert;
|
||||||
|
+
|
||||||
|
+ if (bin_hash == true)
|
||||||
|
+ {
|
||||||
|
+ for (i = 0; i < db.hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (db.hashes[i] == NULL)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (grub_memcmp (db.hashes[i], hash_data, hash_data_size) == 0)
|
||||||
|
+ {
|
||||||
|
+ grub_dprintf ("appendedsig", "removed distrusted hash %02x%02x%02x%02x.. from the db list\n",
|
||||||
|
+ db.hashes[i][0], db.hashes[i][1], db.hashes[i][2], db.hashes[i][3]);
|
||||||
|
+ grub_free (db.hashes[i]);
|
||||||
|
+ db.hashes[i] = NULL;
|
||||||
|
+ db.hash_sizes[i] = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ for (cert = db.certs; cert != NULL; cert = cert->next)
|
||||||
|
+ {
|
||||||
|
+ if (cert_fingerprint_match (hash_data, hash_data_size, cert) == true)
|
||||||
|
+ {
|
||||||
|
+ _remove_cert_from_db (cert);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static grub_err_t
|
||||||
|
file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
|
||||||
|
{
|
||||||
|
@@ -1010,6 +1083,192 @@ grub_cmd_list_db (grub_command_t cmd __attribute__ ((unused)), int argc __attrib
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_list_dbx (grub_command_t cmd __attribute__((unused)),
|
||||||
|
+ int argc __attribute__((unused)), char **args __attribute__((unused)))
|
||||||
|
+{
|
||||||
|
+ struct x509_certificate *cert;
|
||||||
|
+ grub_uint32_t i, cert_num = 1;
|
||||||
|
+
|
||||||
|
+ if (append_key_mgmt == false)
|
||||||
|
+ return grub_error (GRUB_ERR_ACCESS_DENIED,
|
||||||
|
+ "append_list_dbx command is unsupported in static key mode");
|
||||||
|
+
|
||||||
|
+ for (cert = dbx.certs; cert != NULL; cert = cert->next, cert_num++)
|
||||||
|
+ print_certificate (cert, cert_num);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < dbx.hash_entries; i++)
|
||||||
|
+ {
|
||||||
|
+ if (dbx.hashes[i] != NULL)
|
||||||
|
+ {
|
||||||
|
+ grub_printf ("\nCertificate/Binary hash: %u\n", i + 1);
|
||||||
|
+ grub_printf (" Hash: sha%" PRIuGRUB_SIZE "\n ", dbx.hash_sizes[i] * 8);
|
||||||
|
+ hexdump_colon (dbx.hashes[i], dbx.hash_sizes[i]);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return GRUB_ERR_NONE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Remove the trusted binary hash from the dbx list if present. And add them to
|
||||||
|
+ * the db list if it is not already present.
|
||||||
|
+ *
|
||||||
|
+ * Note: When signature verification is enabled, this command only accepts the
|
||||||
|
+ * binary hash file that is signed with an appended signature. The signature is
|
||||||
|
+ * verified by the appendedsig module. If verification succeeds, the binary hash
|
||||||
|
+ * is added to the db list. Otherwise, an error is posted and the binary hash is
|
||||||
|
+ * not added.
|
||||||
|
+ * When signature verification is disabled, it accepts the binary hash file
|
||||||
|
+ * without an appended signature and adds it to the db list.
|
||||||
|
+ *
|
||||||
|
+ * Also, note that the adding of the trusted binary hash using this command does
|
||||||
|
+ * not persist across reboots.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_add_db_hash (grub_command_t cmd __attribute__((unused)), int argc, char**args)
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_file_t hash_file;
|
||||||
|
+ grub_uint8_t *hash_data = NULL;
|
||||||
|
+ grub_size_t hash_data_size = 0;
|
||||||
|
+
|
||||||
|
+ if (append_key_mgmt == false)
|
||||||
|
+ return grub_error (GRUB_ERR_ACCESS_DENIED,
|
||||||
|
+ "append_add_db_hash command is unsupported in static key mode");
|
||||||
|
+
|
||||||
|
+ if (argc != 1)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
+ "a trusted binary hash file is expected in binary format\n"
|
||||||
|
+ "Example:\n\tappend_add_db_hash <BINARY HASH FILE>\n");
|
||||||
|
+
|
||||||
|
+ if (!grub_strlen (args[0]))
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILENAME, "missing trusted binary hash file");
|
||||||
|
+
|
||||||
|
+ hash_file = grub_file_open (args[0], GRUB_FILE_TYPE_HASH_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||||
|
+ if (hash_file == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "unable to open %s file", args[0]);
|
||||||
|
+
|
||||||
|
+ rc = file_read_whole (hash_file, &hash_data, &hash_data_size);
|
||||||
|
+ grub_file_close (hash_file);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ return rc;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled (check_sigs is set to true), obtain
|
||||||
|
+ * the actual hash data size by subtracting the appended signature size from
|
||||||
|
+ * the hash data size because the hash has an appended signature, and this
|
||||||
|
+ * actual hash data size is used to get the hash data.
|
||||||
|
+ */
|
||||||
|
+ if (check_sigs == true)
|
||||||
|
+ hash_data_size -= append_sig_len;
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "adding a trusted binary hash %02x%02x%02x%02x... with size of %" PRIuGRUB_SIZE "\n",
|
||||||
|
+ hash_data[0], hash_data[1], hash_data[2], hash_data[3], hash_data_size);
|
||||||
|
+
|
||||||
|
+ /* Only accept SHA256, SHA384 and SHA512 binary hash */
|
||||||
|
+ if (hash_data_size != SHA256_HASH_SIZE && hash_data_size != SHA384_HASH_SIZE &&
|
||||||
|
+ hash_data_size != SHA512_HASH_SIZE)
|
||||||
|
+ {
|
||||||
|
+ grub_free (hash_data);
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, "unacceptable trusted binary hash type");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rc = add_hash (hash_data, hash_data_size, &db);
|
||||||
|
+ grub_free (hash_data);
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Remove the distrusted binary/certificate hash from the db list if present.
|
||||||
|
+ * And add them to the dbx list if it is not already present.
|
||||||
|
+ *
|
||||||
|
+ * Note: When signature verification is enabled, this command only accepts the
|
||||||
|
+ * binary/certificate hash file that is signed with an appended signature. The
|
||||||
|
+ * signature is verified by the appendedsig module. If verification succeeds,
|
||||||
|
+ * the binary/certificate hash is added to the dbx list. Otherwise, an error is
|
||||||
|
+ * posted and the binary/certificate hash is not added.
|
||||||
|
+ * When signature verification is disabled, it accepts the binary/certificate
|
||||||
|
+ * hash file without an appended signature and adds it to the dbx list.
|
||||||
|
+ *
|
||||||
|
+ * Also, note that the adding of the distrusted binary/certificate hash using
|
||||||
|
+ * this command does not persist across reboots.
|
||||||
|
+ */
|
||||||
|
+static grub_err_t
|
||||||
|
+grub_cmd_add_dbx_hash (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
|
||||||
|
+ char **args __attribute__ ((unused)))
|
||||||
|
+{
|
||||||
|
+ grub_err_t rc;
|
||||||
|
+ grub_file_t hash_file;
|
||||||
|
+ grub_uint8_t *hash_data = NULL;
|
||||||
|
+ grub_size_t hash_data_size = 0;
|
||||||
|
+ char *file_path;
|
||||||
|
+
|
||||||
|
+ if (append_key_mgmt == false)
|
||||||
|
+ return grub_error (GRUB_ERR_ACCESS_DENIED,
|
||||||
|
+ "append_add_dbx_hash command is unsupported in static key mode");
|
||||||
|
+
|
||||||
|
+ if (!ctxt->state[OPTION_BINARY_HASH].set && !ctxt->state[OPTION_CERT_HASH].set)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
|
+ "a distrusted certificate/binary hash file is expected in binary format\n"
|
||||||
|
+ "Example:\n\tappend_add_dbx_hash [option] <FILE>\n"
|
||||||
|
+ "option:\n[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
|
||||||
|
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]\n");
|
||||||
|
+
|
||||||
|
+ if (ctxt->state[OPTION_BINARY_HASH].arg == NULL && ctxt->state[OPTION_CERT_HASH].arg == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_FILENAME, "missing distrusted certificate/binary hash file");
|
||||||
|
+
|
||||||
|
+ if (ctxt->state[OPTION_BINARY_HASH].arg != NULL)
|
||||||
|
+ file_path = ctxt->state[OPTION_BINARY_HASH].arg;
|
||||||
|
+ else
|
||||||
|
+ file_path = ctxt->state[OPTION_CERT_HASH].arg;
|
||||||
|
+
|
||||||
|
+ hash_file = grub_file_open (file_path, GRUB_FILE_TYPE_HASH_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS);
|
||||||
|
+ if (hash_file == NULL)
|
||||||
|
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "unable to open %s file", file_path);
|
||||||
|
+
|
||||||
|
+ rc = file_read_whole (hash_file, &hash_data, &hash_data_size);
|
||||||
|
+ grub_file_close (hash_file);
|
||||||
|
+ if (rc != GRUB_ERR_NONE)
|
||||||
|
+ return rc;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If signature verification is enabled (check_sigs is set to true), obtain
|
||||||
|
+ * the actual hash data size by subtracting the appended signature size from
|
||||||
|
+ * the hash data size because the hash has an appended signature, and this
|
||||||
|
+ * actual hash data size is used to get the hash data.
|
||||||
|
+ */
|
||||||
|
+ if (check_sigs == true)
|
||||||
|
+ hash_data_size -= append_sig_len;
|
||||||
|
+
|
||||||
|
+ grub_dprintf ("appendedsig",
|
||||||
|
+ "adding a distrusted certificate/binary hash %02x%02x%02x%02x..."
|
||||||
|
+ " with size of %" PRIuGRUB_SIZE "\n", hash_data[0], hash_data[1],
|
||||||
|
+ hash_data[2], hash_data[3], hash_data_size);
|
||||||
|
+
|
||||||
|
+ if (ctxt->state[OPTION_BINARY_HASH].set || ctxt->state[OPTION_CERT_HASH].set)
|
||||||
|
+ {
|
||||||
|
+ /* Only accept SHA256, SHA384 and SHA512 certificate/binary hash */
|
||||||
|
+ if (hash_data_size != SHA256_HASH_SIZE && hash_data_size != SHA384_HASH_SIZE &&
|
||||||
|
+ hash_data_size != SHA512_HASH_SIZE)
|
||||||
|
+ {
|
||||||
|
+ grub_free (hash_data);
|
||||||
|
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
|
||||||
|
+ "unacceptable distrusted certificate/binary hash type");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Remove distrusted binary hash/certificate from the db list if present. */
|
||||||
|
+ remove_hash_from_db (hash_data, hash_data_size,
|
||||||
|
+ (ctxt->state[OPTION_BINARY_HASH].set) ? true : false);
|
||||||
|
+ rc = add_hash (hash_data, hash_data_size, &dbx);
|
||||||
|
+ grub_free (hash_data);
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Add the X.509 certificates/binary hash to the db list from PKS. */
|
||||||
|
static grub_err_t
|
||||||
|
load_pks2db (void)
|
||||||
|
@@ -1292,6 +1551,11 @@ appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type t
|
||||||
|
* verifier, but we lack the hubris required to take this on. Instead,
|
||||||
|
* require that it have an appended signature.
|
||||||
|
*/
|
||||||
|
+ case GRUB_FILE_TYPE_HASH_TRUST:
|
||||||
|
+ /*
|
||||||
|
+ * This is a certificate/binary hash to add to db/dbx. This needs to be
|
||||||
|
+ * verified or blocked.
|
||||||
|
+ */
|
||||||
|
case GRUB_FILE_TYPE_LINUX_KERNEL:
|
||||||
|
case GRUB_FILE_TYPE_GRUB_MODULE:
|
||||||
|
/*
|
||||||
|
@@ -1333,6 +1597,8 @@ struct grub_file_verifier grub_appendedsig_verifier = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static grub_command_t cmd_verify, cmd_list_db, cmd_dbx_cert, cmd_db_cert;
|
||||||
|
+static grub_command_t cmd_list_dbx, cmd_db_hash;
|
||||||
|
+static grub_extcmd_t cmd_dbx_hash;
|
||||||
|
|
||||||
|
GRUB_MOD_INIT (appendedsig)
|
||||||
|
{
|
||||||
|
@@ -1412,6 +1678,16 @@ GRUB_MOD_INIT (appendedsig)
|
||||||
|
cmd_dbx_cert = grub_register_command ("append_add_dbx_cert", grub_cmd_dbx_cert, N_("<X509_CERTIFICATE>"),
|
||||||
|
N_("Add distrusted X509_CERTIFICATE to the dbx list"));
|
||||||
|
|
||||||
|
+ cmd_list_dbx = grub_register_command ("append_list_dbx", grub_cmd_list_dbx, 0,
|
||||||
|
+ N_("Show the list of distrusted certificates and"
|
||||||
|
+ " certificate/binary hashes from the dbx list"));
|
||||||
|
+ cmd_db_hash = grub_register_command ("append_add_db_hash", grub_cmd_add_db_hash, N_("BINARY HASH FILE"),
|
||||||
|
+ N_("Add trusted BINARY HASH to the db list."));
|
||||||
|
+ cmd_dbx_hash = grub_register_extcmd ("append_add_dbx_hash", grub_cmd_add_dbx_hash, 0,
|
||||||
|
+ N_("[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
|
||||||
|
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]"),
|
||||||
|
+ N_("Add distrusted CERTFICATE/BINARY HASH to the dbx list."), options);
|
||||||
|
+
|
||||||
|
grub_verifier_register (&grub_appendedsig_verifier);
|
||||||
|
grub_dl_set_persistent (mod);
|
||||||
|
}
|
||||||
|
@@ -1434,4 +1710,7 @@ GRUB_MOD_FINI (appendedsig)
|
||||||
|
grub_unregister_command (cmd_list_db);
|
||||||
|
grub_unregister_command (cmd_db_cert);
|
||||||
|
grub_unregister_command (cmd_dbx_cert);
|
||||||
|
+ grub_unregister_command (cmd_list_dbx);
|
||||||
|
+ grub_unregister_command (cmd_db_hash);
|
||||||
|
+ grub_unregister_extcmd (cmd_dbx_hash);
|
||||||
|
}
|
||||||
|
diff --git a/include/grub/file.h b/include/grub/file.h
|
||||||
|
index d678de0..16a4b7d 100644
|
||||||
|
--- a/include/grub/file.h
|
||||||
|
+++ b/include/grub/file.h
|
||||||
|
@@ -115,6 +115,8 @@ enum grub_file_type
|
||||||
|
GRUB_FILE_TYPE_HASHLIST,
|
||||||
|
/* File hashed by hashsum. */
|
||||||
|
GRUB_FILE_TYPE_TO_HASH,
|
||||||
|
+ /* File holding certificiate/binary hash to add to db/dbx. */
|
||||||
|
+ GRUB_FILE_TYPE_HASH_TRUST,
|
||||||
|
/* Keyboard layout. */
|
||||||
|
GRUB_FILE_TYPE_KEYBOARD_LAYOUT,
|
||||||
|
/* Picture file. */
|
||||||
1270
0403-appended-signatures-Verification-tests.patch
Normal file
1270
0403-appended-signatures-Verification-tests.patch
Normal file
File diff suppressed because it is too large
Load Diff
44
0404-docs-grub-Document-signing-GRUB-under-UEFI.patch
Normal file
44
0404-docs-grub-Document-signing-GRUB-under-UEFI.patch
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Axtens <dja@axtens.net>
|
||||||
|
Date: Mon, 6 Oct 2025 12:55:03 +0530
|
||||||
|
Subject: [PATCH] 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 <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
docs/grub.texi | 15 +++++++++++++++
|
||||||
|
1 file changed, 15 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||||
|
index 2d6d73a..e08aaf5 100644
|
||||||
|
--- a/docs/grub.texi
|
||||||
|
+++ b/docs/grub.texi
|
||||||
|
@@ -6912,6 +6912,21 @@ which increases the risk of password leakage during the process. Moreover, the
|
||||||
|
superuser list must be well maintained, and the password used cannot be
|
||||||
|
synchronized with LUKS key rotation.
|
||||||
|
|
||||||
|
+@node Signing GRUB itself
|
||||||
|
+@section Signing GRUB itself
|
||||||
|
+To ensure a complete secure-boot chain, there must be a way for the code that
|
||||||
|
+loads GRUB to verify the integrity of the core image.
|
||||||
|
+This is ultimately platform-specific and individual platforms can define their
|
||||||
|
+own mechanisms. However, there are general-purpose mechanisms that can be used
|
||||||
|
+with GRUB.
|
||||||
|
+@section Signing GRUB for UEFI secure boot
|
||||||
|
+On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed
|
||||||
|
+with a tool such as @command{pesign} or @command{sbsign}. Refer to the
|
||||||
|
+suggestions in @pxref{UEFI secure boot and shim} to ensure that the final
|
||||||
|
+image works under UEFI secure boot and can maintain the secure-boot chain. It
|
||||||
|
+will also be necessary to enroll the public key used into a relevant firmware
|
||||||
|
+key database.
|
||||||
|
+
|
||||||
|
@node Platform limitations
|
||||||
|
@chapter Platform limitations
|
||||||
|
|
||||||
124
0405-docs-grub-Document-signing-GRUB-with-an-appended-sig.patch
Normal file
124
0405-docs-grub-Document-signing-GRUB-with-an-appended-sig.patch
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:55:04 +0530
|
||||||
|
Subject: [PATCH] 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 <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
docs/grub.texi | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 95 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||||
|
index e08aaf5..0b1c9d1 100644
|
||||||
|
--- a/docs/grub.texi
|
||||||
|
+++ b/docs/grub.texi
|
||||||
|
@@ -6927,6 +6927,101 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It
|
||||||
|
will also be necessary to enroll the public key used into a relevant firmware
|
||||||
|
key database.
|
||||||
|
|
||||||
|
+@section Signing GRUB with an appended signature
|
||||||
|
+The @file{core.elf} itself can be signed with a Linux kernel module-style
|
||||||
|
+appended signature (@pxref{Using appended signatures}).
|
||||||
|
+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.elf}
|
||||||
|
+can specify the size and location of the appended signature with an ELF
|
||||||
|
+Note added by @command{grub-install} or @command{grub-mkimage}.
|
||||||
|
+An image can be signed this way using the @command{sign-file} command from
|
||||||
|
+the Linux kernel:
|
||||||
|
+
|
||||||
|
+@itemize
|
||||||
|
+@item Signing a GRUB image using a single signer key. The grub.key is your
|
||||||
|
+private key used for GRUB signing, grub.der is a corresponding public key
|
||||||
|
+(certificate) used for GRUB signature verification, and the kernel.der is
|
||||||
|
+your public key (certificate) used for kernel signature verification.
|
||||||
|
+@example
|
||||||
|
+@group
|
||||||
|
+# Determine the size of the appended signature. It depends on the
|
||||||
|
+# signing key and the hash algorithm.
|
||||||
|
+#
|
||||||
|
+# Signing /dev/null with an appended signature.
|
||||||
|
+
|
||||||
|
+sign-file SHA256 grub.key grub.der /dev/null ./empty.sig
|
||||||
|
+
|
||||||
|
+# Build a GRUB image for the signature.
|
||||||
|
+
|
||||||
|
+grub-mkimage -O powerpc-ieee1275 -o core.elf.unsigned -x kernel.der \
|
||||||
|
+ -p /grub --appended-signature-size $(stat -c '%s' ./empty.sig) \
|
||||||
|
+ --modules="appendedsig ..." ...
|
||||||
|
+
|
||||||
|
+# Remove the signature file.
|
||||||
|
+
|
||||||
|
+rm ./empty.sig
|
||||||
|
+
|
||||||
|
+# Signing a GRUB image with an appended signature.
|
||||||
|
+
|
||||||
|
+sign-file SHA256 grub.key grub.der core.elf.unsigned core.elf.signed
|
||||||
|
+
|
||||||
|
+@end group
|
||||||
|
+@end example
|
||||||
|
+@item Signing a GRUB image using more than one signer key. The grub1.key and
|
||||||
|
+grub2.key are private keys used for GRUB signing, grub1.der and grub2.der
|
||||||
|
+are corresponding public keys (certificates) used for GRUB signature verification.
|
||||||
|
+The kernel1.der and kernel2.der are your public keys (certificates) used for
|
||||||
|
+kernel signature verification.
|
||||||
|
+@example
|
||||||
|
+@group
|
||||||
|
+# Generate a signature by signing /dev/null.
|
||||||
|
+
|
||||||
|
+openssl cms -sign -binary -nocerts -in /dev/null -signer \
|
||||||
|
+ grub1.der -inkey grub1.key -signer grub2.der -inkey grub2.key \
|
||||||
|
+ -out ./empty.p7s -outform DER -noattr -md sha256
|
||||||
|
+
|
||||||
|
+# To be able to determine the size of an appended signature, sign an
|
||||||
|
+# empty file (/dev/null) to which a signature will be appended to.
|
||||||
|
+
|
||||||
|
+sign-file -s ./empty.p7s sha256 /dev/null /dev/null ./empty.sig
|
||||||
|
+
|
||||||
|
+# Build a GRUB image for the signature.
|
||||||
|
+
|
||||||
|
+grub-mkimage -O powerpc-ieee1275 -o core.elf.unsigned -x kernel1.der \
|
||||||
|
+ kernel2.der -p /grub --appended-signature-size $(stat -c '%s' ./empty.sig) \
|
||||||
|
+ --modules="appendedsig ..." ...
|
||||||
|
+
|
||||||
|
+# Remove the signature files.
|
||||||
|
+
|
||||||
|
+rm ./empty.sig ./empty.p7s
|
||||||
|
+
|
||||||
|
+# Generate a raw signature for GRUB image signing using OpenSSL.
|
||||||
|
+
|
||||||
|
+openssl cms -sign -binary -nocerts -in core.elf.unsigned -signer \
|
||||||
|
+ grub1.der -inkey grub1.key -signer grub2.der -inkey grub2.key \
|
||||||
|
+ -out core.p7s -outform DER -noattr -md sha256
|
||||||
|
+
|
||||||
|
+# Sign a GRUB image to get an image file with an appended signature.
|
||||||
|
+
|
||||||
|
+sign-file -s core.p7s sha256 /dev/null core.elf.unsigned core.elf.signed
|
||||||
|
+
|
||||||
|
+@end group
|
||||||
|
+@end example
|
||||||
|
+@item Don't forget to install the signed image as required
|
||||||
|
+(e.g. on powerpc-ieee1275, to the PReP partition).
|
||||||
|
+@example
|
||||||
|
+@group
|
||||||
|
+# Install signed GRUB image to the PReP partition on powerpc-ieee1275
|
||||||
|
+
|
||||||
|
+dd if=core.elf.signed of=/dev/sda1
|
||||||
|
+
|
||||||
|
+@end group
|
||||||
|
+@end example
|
||||||
|
+@end itemize
|
||||||
|
+
|
||||||
|
+As with UEFI secure boot, it is necessary to build-in the required modules,
|
||||||
|
+or sign them if they are not part of the GRUB image.
|
||||||
|
+
|
||||||
|
@node Platform limitations
|
||||||
|
@chapter Platform limitations
|
||||||
|
|
||||||
465
0406-docs-grub-Document-appended-signature.patch
Normal file
465
0406-docs-grub-Document-appended-signature.patch
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:55:05 +0530
|
||||||
|
Subject: [PATCH] docs/grub: Document appended signature
|
||||||
|
|
||||||
|
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 <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
docs/grub.texi | 355 +++++++++++++++++++++++++++++++++++++++++++++++----------
|
||||||
|
1 file changed, 293 insertions(+), 62 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||||
|
index 0b1c9d1..e4f36df 100644
|
||||||
|
--- a/docs/grub.texi
|
||||||
|
+++ b/docs/grub.texi
|
||||||
|
@@ -3274,6 +3274,7 @@ GRUB. Others may be used freely in GRUB configuration files.
|
||||||
|
These variables have special meaning to GRUB.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
+* appendedsig_key_mgmt::
|
||||||
|
* biosnum::
|
||||||
|
* check_appended_signatures::
|
||||||
|
* check_signatures::
|
||||||
|
@@ -3327,6 +3328,19 @@ These variables have special meaning to GRUB.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
+@node appendedsig_key_mgmt
|
||||||
|
+@subsection appendedsig_key_mgmt
|
||||||
|
+
|
||||||
|
+This variable controls whether GRUB enforces appended signature validation
|
||||||
|
+using either @code{static} or @code{dynamic} key management. It is automatically
|
||||||
|
+set by GRUB to either @code{static} or @code{dynamic} based on the
|
||||||
|
+@strong{'ibm,secure-boot'} device tree property and Platform KeyStore (PKS).
|
||||||
|
+Also, it can be explicitly set to either @code{static} or @code{dynamic} by
|
||||||
|
+setting the @code{appendedsig_key_mgmt} variable from the GRUB console
|
||||||
|
+when the GRUB is not locked down.
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+
|
||||||
|
@node biosnum
|
||||||
|
@subsection biosnum
|
||||||
|
|
||||||
|
@@ -3339,13 +3353,17 @@ this.
|
||||||
|
For an alternative approach which also changes BIOS drive mappings for the
|
||||||
|
chain-loaded system, @pxref{drivemap}.
|
||||||
|
|
||||||
|
-
|
||||||
|
@node check_appended_signatures
|
||||||
|
@subsection check_appended_signatures
|
||||||
|
|
||||||
|
This variable controls whether GRUB enforces appended signature validation on
|
||||||
|
-certain loaded files. @xref{Using appended signatures}.
|
||||||
|
+loaded kernel and GRUB module files. It is automatically set by GRUB
|
||||||
|
+to either @code{no} or @code{yes} based on the @strong{'ibm,secure-boot'} device
|
||||||
|
+tree property. Also, it can be explicitly set to either @code{no} or @code{yes} by
|
||||||
|
+setting the @code{check_appended_signatures} variable from the GRUB console
|
||||||
|
+when the GRUB is not locked down.
|
||||||
|
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
|
||||||
|
@node check_signatures
|
||||||
|
@subsection check_signatures
|
||||||
|
@@ -4350,6 +4368,13 @@ you forget a command, you can run the command @command{help}
|
||||||
|
@menu
|
||||||
|
* [:: Check file types and compare values
|
||||||
|
* acpi:: Load ACPI tables
|
||||||
|
+* append_add_db_cert:: Add trusted certificate to the db list
|
||||||
|
+* append_add_db_hash:: Add trusted certificate/binary hash to the db list
|
||||||
|
+* append_add_dbx_cert:: Add distrusted certificate to the dbx list
|
||||||
|
+* append_add_dbx_hash:: Add distrusted certificate/binary hash to the dbx list
|
||||||
|
+* append_list_db:: List all trusted certificates from the db list
|
||||||
|
+* append_list_dbx:: List all distrusted certificates and binary/certificate hashes from the dbx list
|
||||||
|
+* append_verify:: Verify appended digital signature using db and dbx lists
|
||||||
|
* authenticate:: Check whether user is in user list
|
||||||
|
* background_color:: Set background color for active terminal
|
||||||
|
* background_image:: Load background image for active terminal
|
||||||
|
@@ -4469,6 +4494,140 @@ Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}).
|
||||||
|
unsigned code.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
+@node append_add_db_cert
|
||||||
|
+@subsection append_add_db_cert
|
||||||
|
+
|
||||||
|
+@deffn Command append_add_db_cert <X509_certificate>
|
||||||
|
+Read an X.509 certificate from the file @var{X509_certificate}
|
||||||
|
+and add it to GRUB's internal db list of trusted certificates.
|
||||||
|
+These certificates are used to validate appended signatures when the
|
||||||
|
+environment variable @code{check_appended_signatures} (@pxref{check_appended_signatures})
|
||||||
|
+is set to @code{yes} or the @command{append_verify} (@pxref{append_verify})
|
||||||
|
+command is executed from the GRUB console.
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
+@node append_add_db_hash
|
||||||
|
+@subsection append_add_db_hash
|
||||||
|
+
|
||||||
|
+@deffn Command append_add_db_hash <hash_file>
|
||||||
|
+Read a binary hash from the file @var{hash_file}
|
||||||
|
+and add it to GRUB's internal db list of trusted binary hashes. These
|
||||||
|
+hashes are used to validate the Linux kernel/GRUB module binary hashes when the
|
||||||
|
+environment variable @code{check_appended_signatures}
|
||||||
|
+(@pxref{check_appended_signatures}) is set to @code{yes} or the
|
||||||
|
+@command{append_verify} (@pxref{append_verify}) command is executed
|
||||||
|
+from the GRUB console.
|
||||||
|
+
|
||||||
|
+Here is an example for how to generate a SHA-256 hash for a file. The hash
|
||||||
|
+will be in binary format:
|
||||||
|
+
|
||||||
|
+@example
|
||||||
|
+
|
||||||
|
+# The vmlinux (kernel image) file is your binary file, and
|
||||||
|
+# it should be unsigned.
|
||||||
|
+#
|
||||||
|
+# Generate the binary_hash.bin file from the vmlinux file
|
||||||
|
+# using OpenSSL command
|
||||||
|
+
|
||||||
|
+openssl dgst -binary -sha256 -out binary_hash.bin vmlinux
|
||||||
|
+
|
||||||
|
+@end example
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
+@node append_add_dbx_cert
|
||||||
|
+@subsection append_add_dbx_cert
|
||||||
|
+
|
||||||
|
+@deffn Command append_add_dbx_cert <X509_certificate>
|
||||||
|
+Read an X.509 certificate from the file @var{X509_certificate}
|
||||||
|
+and add it to GRUB's internal dbx list of distrusted certificates.
|
||||||
|
+These certificates are used to ensure that the distrusted certificates
|
||||||
|
+are rejected during appended signatures validation when the environment
|
||||||
|
+variable @code{check_appended_signatures} is set to @code{yes}
|
||||||
|
+(@pxref{check_appended_signatures}) or the @command{append_verify}
|
||||||
|
+(@pxref{append_verify}) command is executed from the GRUB console.
|
||||||
|
+Also, these certificates are used to prevent distrusted certificates from
|
||||||
|
+being added to the db list later on.
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
+@node append_add_dbx_hash
|
||||||
|
+@subsection append_add_dbx_hash
|
||||||
|
+
|
||||||
|
+@deffn Command append_add_dbx_hash [@option{-b}|@option{-c}] <hash_file>
|
||||||
|
+Read a binary/certificate hash from the file @var{hash_file}
|
||||||
|
+and add it to GRUB's internal dbx list of distrusted binary/certificate hashes.
|
||||||
|
+When the environment variable @code{check_appended_signatures} (@pxref{check_appended_signatures})
|
||||||
|
+is set to @code{yes} or the @command{append_verify} (@pxref{append_verify}) command
|
||||||
|
+is executed from the GRUB console, then matching distrusted binary hashes or the signature
|
||||||
|
+validation with distrusted certificates may lead to the rejection of the Linux kernel or GRUB modules.
|
||||||
|
+Also, these hashes are used to prevent distrusted certificates and binary hashes from being
|
||||||
|
+added to the db list later on.
|
||||||
|
+
|
||||||
|
+The @option{-b} (@option{--binary-hash}) can be used to specify a binary hash file and
|
||||||
|
+@option{-c} (@option{--cert-hash}) can be used to specify a certificate hash file.
|
||||||
|
+
|
||||||
|
+Here is an example for how to generate a SHA-256 hash for a binary and a
|
||||||
|
+certificate file. The hash will be in binary format:
|
||||||
|
+
|
||||||
|
+@example
|
||||||
|
+
|
||||||
|
+# The vmlinux (kernel image) file is your binary file, and
|
||||||
|
+# it should be unsigned. The kernel.der is your certificate file.
|
||||||
|
+#
|
||||||
|
+# Generate the cert_hash.bin file from the kernel.der file
|
||||||
|
+
|
||||||
|
+openssl dgst -binary -sha256 -out cert_hash.bin kernel.der
|
||||||
|
+
|
||||||
|
+# Generate the binary_hash.bin file from the vmlinux file
|
||||||
|
+
|
||||||
|
+openssl dgst -binary -sha256 -out binary_hash.bin vmlinux
|
||||||
|
+
|
||||||
|
+@end example
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
+@node append_list_db
|
||||||
|
+@subsection append_list_db
|
||||||
|
+
|
||||||
|
+@deffn Command append_list_db
|
||||||
|
+List all X.509 certificates and binary hashes trusted by GRUB for validating
|
||||||
|
+appended signatures. The output is a numbered list of certificates and binary hashes,
|
||||||
|
+showing the certificate's version, serial number, issuer, subject,
|
||||||
|
+public key algorithm, RSA public key size, and certificate fingerprint.
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
+@node append_list_dbx
|
||||||
|
+@subsection append_list_dbx
|
||||||
|
+
|
||||||
|
+@deffn Command append_list_dbx
|
||||||
|
+List all the distrusted X.509 certificates and binary/certificate hashes.
|
||||||
|
+The output is a numbered list of certificates and binary/certificate hashes,
|
||||||
|
+showing the certificate's version, serial number, issuer, subject,
|
||||||
|
+public key algorithm, RSA public key size, and certificate fingerprint.
|
||||||
|
+
|
||||||
|
+@xref{Using appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
+
|
||||||
|
+@node append_verify
|
||||||
|
+@subsection append_verify
|
||||||
|
+
|
||||||
|
+@deffn Command append_verify <signed_file>
|
||||||
|
+Verifies an appended signature on @var{signed_file} against the trusted X.509 certificates
|
||||||
|
+and hashes known to GRUB (@pxref{append_list_db},@pxref{append_list_dbx}, @pxref{append_add_db_cert},
|
||||||
|
+@pxref{append_add_db_hash}, @pxref{append_add_dbx_hash} and @pxref{append_add_dbx_cert}).
|
||||||
|
+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 appended signatures} for more information.
|
||||||
|
+@end deffn
|
||||||
|
|
||||||
|
@node authenticate
|
||||||
|
@subsection authenticate
|
||||||
|
@@ -5139,10 +5298,12 @@ configurations, and to enable ``one-shot'' boot attempts and
|
||||||
|
``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} if GRUB is
|
||||||
|
-not in @pxref{Lockdown} mode.
|
||||||
|
+If the environment variable @code{check_appended_signatures} value is set to
|
||||||
|
+@code{yes} and GRUB is in lockeddown mode, the user is not allowed to set
|
||||||
|
+@code{check_appended_signatures} to @code{no} and @code{appendedsig_key_mgmt}
|
||||||
|
+to @code{static} or @code{dynamic} either directly using @command{load_env}
|
||||||
|
+command or via environment block file. @xref{Using appended signatures}, for
|
||||||
|
+more information.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@@ -6488,6 +6649,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 certificate and hash files:: Certificate and hash file signing
|
||||||
|
* Signing GRUB itself:: Ensuring the integrity of the GRUB core image
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
@@ -6661,8 +6823,8 @@ 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
|
||||||
|
+GRUB supports verifying Linux-style 'appended signatures' for Linux on Power LPAR
|
||||||
|
+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:
|
||||||
|
|
||||||
|
@@ -6670,73 +6832,114 @@ with an appended signature ends with the magic string:
|
||||||
|
~Module signature appended~\n
|
||||||
|
@end example
|
||||||
|
|
||||||
|
-where @code{\n} represents the line-feed character, @code{0x0a}.
|
||||||
|
+where @code{\n} represents the line feed character, @code{0x0a}.
|
||||||
|
|
||||||
|
-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}.
|
||||||
|
+Linux on Power LPAR secure boot is controlled by @strong{'ibm,secure-boot'}
|
||||||
|
+device tree property and if this property is set to @code{2} (@samp{enforce}),
|
||||||
|
+GRUB enters lockdown mode. There are three secure boot modes. They are
|
||||||
|
|
||||||
|
-A file can be explictly verified using the @pxref{verify_appended} command.
|
||||||
|
+@itemize
|
||||||
|
+@item @samp{0 - disabled}: Secure boot is disabled. This is the default.
|
||||||
|
+@item @samp{1 - audit}: Enforce signature verification by setting
|
||||||
|
+ @code{check_appended_signatures} (@pxref{check_appended_signatures}) to
|
||||||
|
+ @code{yes} and do not enter lockdown mode. Signature verification
|
||||||
|
+ is performed and if signature verification fails, display the errors and
|
||||||
|
+ allow the boot to continue.
|
||||||
|
+@item @samp{2 - enforce}: Enter lockdown mode and enforce signature verification by setting
|
||||||
|
+ @code{check_appended_signatures} (@pxref{check_appended_signatures}) to @code{yes}.
|
||||||
|
+@end itemize
|
||||||
|
|
||||||
|
-Only signatures made with the SHA-256 or SHA-512 hash algorithm are supported,
|
||||||
|
-and only RSA signatures are supported.
|
||||||
|
+Note that Linux on Power LPAR only supports @samp{0 - disabled} and @samp{2 - enforce},
|
||||||
|
+and @samp{1 - audit} is considered as secure boot being disabled.
|
||||||
|
+
|
||||||
|
+Enforcement of signature verification is controlled by the environment variable
|
||||||
|
+@code{check_appended_signatures} (@pxref{check_appended_signatures}).
|
||||||
|
+
|
||||||
|
+@itemize
|
||||||
|
+@item @samp{no}: No verification is performed. This is the default.
|
||||||
|
+@item @samp{yes}: Signature verification is performed and if signature verification fails,
|
||||||
|
+ display the errors and stop the boot. Signature verification cannot be disabled by setting
|
||||||
|
+ the @code{check_appended_signatures} variable back to @samp{no}.
|
||||||
|
+@end itemize
|
||||||
|
+
|
||||||
|
+To enable appended signature verification, load the appendedsig module and an
|
||||||
|
+X.509 certificate for verification. It is recommended to build the appendedsig module
|
||||||
|
+into the core GRUB image.
|
||||||
|
+
|
||||||
|
+Key management is controlled by the environment variable @code{appendedsig_key_mgmt}
|
||||||
|
+(@pxref{appendedsig_key_mgmt}).
|
||||||
|
+
|
||||||
|
+@itemize
|
||||||
|
+@item @samp{static}: Enforce static key management signature verification. This is the default.
|
||||||
|
+ When GRUB is in lockdown mode, then the user cannot change the value of the
|
||||||
|
+ @code{appendedsig_key_mgmt}.
|
||||||
|
+@item @samp{dynamic}: Enforce dynamic key management signature verification. When GRUB is in
|
||||||
|
+ lockdown mode, then the user cannot change the value of the @code{appendedsig_key_mgmt}.
|
||||||
|
+@end itemize
|
||||||
|
+
|
||||||
|
+In static key management mode, certificates will be built into the core image using
|
||||||
|
+the @code{--x509} parameter to @command{grub-mkimage}. The list of trusted certificates
|
||||||
|
+available at boot time can be shown using @command{append_list_db} (@pxref{append_list_db}).
|
||||||
|
+Distrusted certificates can be explicitly removed from the db using @command{append_add_dbx_cert}
|
||||||
|
+(@pxref{append_add_dbx_cert}). Also, trusted certificates can be explicitly added to the db using
|
||||||
|
+@command{append_add_db_cert} (@pxref{append_add_db_cert}).
|
||||||
|
+
|
||||||
|
+In dynamic key management mode, db and dbx are read from the Platform KeyStore (PKS). If
|
||||||
|
+db does not exist in PKS, static keys (built-in keys) are used as the default keys.
|
||||||
|
+The list of trusted certificates and binary hashes available at boot time can be shown using
|
||||||
|
+@command{append_list_db} (@pxref{append_list_db}) and the list of distrusted certificates and
|
||||||
|
+binary/certificate hashes available at boot time can be shown using @command{append_list_dbx}
|
||||||
|
+(@pxref{append_list_dbx}). The trusted certificates and binary hashes can be explicitly added
|
||||||
|
+to the db using @command{append_add_db_cert} (@pxref{append_add_db_cert}) and
|
||||||
|
+@command{append_add_db_hash} (@pxref{append_add_db_hash}). Distrusted certificates can be explicitly
|
||||||
|
+added to the dbx using @command{append_add_dbx_cert} (@pxref{append_add_dbx_cert}) and distrusted
|
||||||
|
+certificate/binary hashes can be explicitly added to the dbx using @command{append_add_dbx_hash}
|
||||||
|
+(@pxref{append_add_dbx_hash}).
|
||||||
|
+
|
||||||
|
+A file can be explicitly verified using @command{append_verify} (@pxref{append_verify}).
|
||||||
|
+
|
||||||
|
+Note that when the environment variable @code{check_appended_signatures} is set to @code{yes},
|
||||||
|
+the @command{append_add_db_cert} and @command{append_add_dbx_cert} commands only accept
|
||||||
|
+the file @samp{@var{X509_certificate}} that is signed with an appended signature
|
||||||
|
+(@pxref{Signing certificate and hash files}), and the @command{append_add_db_hash} and
|
||||||
|
+@command{append_add_dbx_hash} commands only accept the file @samp{@var{hash_file}} that is
|
||||||
|
+signed with an appended signature (@pxref{Signing certificate and hash files}).
|
||||||
|
+The signature is verified by the appendedsig module.
|
||||||
|
+When the environment variable @code{check_appended_signatures} is set to @code{no},
|
||||||
|
+these commands accept files without an appended signature.
|
||||||
|
+
|
||||||
|
+Also, note that @samp{@var{X509_certificate}} should be in DER-format and @samp{@var{hash_file}}
|
||||||
|
+should be in binary format. Only SHA-256, SHA-384, or SHA-512 hashes of binary/certificate are allowed.
|
||||||
|
+Certificates/hashes of certificates/binaries added through @command{append_add_db_cert},
|
||||||
|
+@command{append_add_dbx_cert}, @command{append_add_db_hash}, and @command{append_add_dbx_hash}
|
||||||
|
+will not be persisted across boots.
|
||||||
|
+
|
||||||
|
+Only signatures created using SHA-256 or SHA-512 hash algorithm along with RSA keys of size 2048,
|
||||||
|
+3072, or 4096 bits 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:
|
||||||
|
+key and @code{certificate.der} as the X.509 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.
|
||||||
|
+Once signature verification is turned on, the following file types must carry
|
||||||
|
+appended signatures:
|
||||||
|
|
||||||
|
-@itemize
|
||||||
|
-@item @samp{no}: no verification is performed. This is the default when GRUB
|
||||||
|
- is not in @pxref{Lockdown} mode.
|
||||||
|
-@item @samp{enforce}: verification is performed. Verification can be disabled
|
||||||
|
- by setting the variable back to @samp{no}.
|
||||||
|
-@item @samp{forced}: verification is performed and cannot be disabled. This is
|
||||||
|
- set when GRUB is in Lockdown when the appendedsig module is loaded.
|
||||||
|
-@end itemize
|
||||||
|
-
|
||||||
|
-Unlike GPG-style signatures, not all files loaded by GRUB are required to be
|
||||||
|
-signed. Once verification is turned on, the following file types will have
|
||||||
|
-appended signatures verified:
|
||||||
|
-
|
||||||
|
-@itemize
|
||||||
|
+@enumerate
|
||||||
|
@item Linux kernels
|
||||||
|
-@item GRUB modules, except those built into the core image
|
||||||
|
-@item Any new certificate files to be trusted
|
||||||
|
-@end itemize
|
||||||
|
-
|
||||||
|
-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.
|
||||||
|
-
|
||||||
|
-Unless lockdown mode is enabled, 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, unless lockdown mode is enabled:
|
||||||
|
-
|
||||||
|
-@itemize
|
||||||
|
-@item Special care must be taken around the @command{loadenv} command, which
|
||||||
|
- can be used to turn off @code{check_appended_signature}.
|
||||||
|
-
|
||||||
|
-@item If the grub configuration file is loaded from the disk, anyone who can
|
||||||
|
- modify the file on disk can turn off @code{check_appended_signature}.
|
||||||
|
- Consider embedding the configuration into the core grub image.
|
||||||
|
-@end itemize
|
||||||
|
+@item GRUB modules, except those built in to the core image
|
||||||
|
+@item Any new certificate or binary hash files to be trusted
|
||||||
|
+@item Any new certificate/binary hash files to be distrusted
|
||||||
|
+@end enumerate
|
||||||
|
+
|
||||||
|
+When GRUB is in lockdown mode (when secure boot mode is set to @code{enforce}),
|
||||||
|
+signature verification cannot be @strong{disabled} by setting the
|
||||||
|
+@code{check_appended_signatures} (@pxref{check_appended_signatures}) variable
|
||||||
|
+to @code{no} or using the @command{load_env} (@pxref{load_env}) command from
|
||||||
|
+the GRUB console.
|
||||||
|
|
||||||
|
@node UEFI secure boot and shim
|
||||||
|
@section UEFI secure boot and shim support
|
||||||
|
@@ -6912,6 +7115,34 @@ which increases the risk of password leakage during the process. Moreover, the
|
||||||
|
superuser list must be well maintained, and the password used cannot be
|
||||||
|
synchronized with LUKS key rotation.
|
||||||
|
|
||||||
|
+@node Signing certificate and hash files
|
||||||
|
+@section Signing certificate and hash files
|
||||||
|
+X.509 certificate (public key) files and hash files (binary/certificate hash files)
|
||||||
|
+can be signed with a Linux kernel module-style appended signature.
|
||||||
|
+
|
||||||
|
+The signer.key is a private key used for signing and signer.der is the corresponding
|
||||||
|
+public key (certificate) used for appended signature verification. Note that the
|
||||||
|
+signer.der (certificate) should exist in the db (@pxref{Using appended signatures}).
|
||||||
|
+
|
||||||
|
+@itemize
|
||||||
|
+@item Signing the X.509 certificate file using @file{sign-file}.
|
||||||
|
+The kernel.der is an X.509 certificate file.
|
||||||
|
+@example
|
||||||
|
+
|
||||||
|
+sign-file SHA256 signer.key signer.der kernel.der \
|
||||||
|
+ kernel.der.signed
|
||||||
|
+
|
||||||
|
+@end example
|
||||||
|
+@item Signing the hash file using @file{sign-file}.
|
||||||
|
+The binary_hash.bin is a binary hash file.
|
||||||
|
+@example
|
||||||
|
+
|
||||||
|
+sign-file SHA256 signer.key signer.der binary_hash.bin \
|
||||||
|
+ binary_hash.signed
|
||||||
|
+
|
||||||
|
+@end example
|
||||||
|
+@end itemize
|
||||||
|
+
|
||||||
|
@node Signing GRUB itself
|
||||||
|
@section Signing GRUB itself
|
||||||
|
To ensure a complete secure-boot chain, there must be a way for the code that
|
||||||
89
0407-libtasn1-Fix-include-path-for-grub.patch
Normal file
89
0407-libtasn1-Fix-include-path-for-grub.patch
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicolas Frayer <nfrayer@redhat.com>
|
||||||
|
Date: Wed, 19 Nov 2025 13:33:12 +0100
|
||||||
|
Subject: [PATCH] libtasn1: Fix include path for grub
|
||||||
|
|
||||||
|
Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
|
||||||
|
---
|
||||||
|
grub-core/commands/appendedsig/appendedsig.c | 2 +-
|
||||||
|
grub-core/commands/appendedsig/appendedsig.h | 2 +-
|
||||||
|
grub-core/commands/appendedsig/asn1util.c | 2 +-
|
||||||
|
grub-core/commands/appendedsig/gnutls_asn1_tab.c | 2 +-
|
||||||
|
grub-core/commands/appendedsig/pkix_asn1_tab.c | 2 +-
|
||||||
|
grub-core/commands/appendedsig/x509.c | 2 +-
|
||||||
|
6 files changed, 6 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
index 5c53f63..1c74554 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.c
|
||||||
|
@@ -30,7 +30,7 @@
|
||||||
|
#include <grub/kernel.h>
|
||||||
|
#include <grub/extcmd.h>
|
||||||
|
#include <grub/verify.h>
|
||||||
|
-#include <libtasn1.h>
|
||||||
|
+#include <grub/libtasn1.h>
|
||||||
|
#include <grub/env.h>
|
||||||
|
#include <grub/lockdown.h>
|
||||||
|
#include <grub/powerpc/ieee1275/platform_keystore.h>
|
||||||
|
diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
index c874654..cb0fe19 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
+++ b/grub-core/commands/appendedsig/appendedsig.h
|
||||||
|
@@ -18,7 +18,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <grub/crypto.h>
|
||||||
|
-#include <libtasn1.h>
|
||||||
|
+#include <grub/libtasn1.h>
|
||||||
|
|
||||||
|
extern asn1_node grub_gnutls_gnutls_asn;
|
||||||
|
extern asn1_node grub_gnutls_pkix_asn;
|
||||||
|
diff --git a/grub-core/commands/appendedsig/asn1util.c b/grub-core/commands/appendedsig/asn1util.c
|
||||||
|
index 9dd7898..1f50a74 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/asn1util.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/asn1util.c
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-#include <libtasn1.h>
|
||||||
|
+#include <grub/libtasn1.h>
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
|
diff --git a/grub-core/commands/appendedsig/gnutls_asn1_tab.c b/grub-core/commands/appendedsig/gnutls_asn1_tab.c
|
||||||
|
index efc0c14..16998f2 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/gnutls_asn1_tab.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/gnutls_asn1_tab.c
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
#include <grub/mm.h>
|
||||||
|
-#include <libtasn1.h>
|
||||||
|
+#include <grub/libtasn1.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Imported from gnutls.asn.
|
||||||
|
diff --git a/grub-core/commands/appendedsig/pkix_asn1_tab.c b/grub-core/commands/appendedsig/pkix_asn1_tab.c
|
||||||
|
index ec5f87b..fdc989a 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/pkix_asn1_tab.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/pkix_asn1_tab.c
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
#include <grub/mm.h>
|
||||||
|
-#include <libtasn1.h>
|
||||||
|
+#include <grub/libtasn1.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Imported from pkix.asn.
|
||||||
|
diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c
|
||||||
|
index bc15266..08846aa 100644
|
||||||
|
--- a/grub-core/commands/appendedsig/x509.c
|
||||||
|
+++ b/grub-core/commands/appendedsig/x509.c
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-#include <libtasn1.h>
|
||||||
|
+#include <grub/libtasn1.h>
|
||||||
|
#include <grub/types.h>
|
||||||
|
#include <grub/err.h>
|
||||||
|
#include <grub/mm.h>
|
||||||
81
0408-docs-fix-duplicated-entries.patch
Normal file
81
0408-docs-fix-duplicated-entries.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicolas Frayer <nfrayer@redhat.com>
|
||||||
|
Date: Wed, 19 Nov 2025 14:17:51 +0100
|
||||||
|
Subject: [PATCH] docs: fix duplicated entries
|
||||||
|
|
||||||
|
Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
|
||||||
|
---
|
||||||
|
docs/grub.texi | 60 ----------------------------------------------------------
|
||||||
|
1 file changed, 60 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
||||||
|
index e4f36df..9f5eb68 100644
|
||||||
|
--- a/docs/grub.texi
|
||||||
|
+++ b/docs/grub.texi
|
||||||
|
@@ -7025,66 +7025,6 @@ 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.
|
||||||
|
|
||||||
|
-@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.
|
||||||
|
-
|
||||||
|
-@section Signing GRUB with an appended signature
|
||||||
|
-
|
||||||
|
-The @file{core.elf} 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.elf}
|
||||||
|
-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.
|
||||||
|
-
|
||||||
|
@subsection Command line and menuentry editor protection
|
||||||
|
|
||||||
|
The TPM key protector provides full disk encryption support on servers or
|
||||||
345
0409-powerpc-ieee1275-Add-support-for-signing-GRUB-with-a.patch
Normal file
345
0409-powerpc-ieee1275-Add-support-for-signing-GRUB-with-a.patch
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Date: Mon, 6 Oct 2025 12:54:46 +0530
|
||||||
|
Subject: [PATCH] powerpc/ieee1275: Add support 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: Rashmica Gupta <rashmica.g@gmail.com>
|
||||||
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||||
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||||
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
---
|
||||||
|
include/grub/util/install.h | 2 +-
|
||||||
|
include/grub/util/mkimage.h | 4 +--
|
||||||
|
util/grub-install-common.c | 28 ++++++++++-----------
|
||||||
|
util/grub-mkimage.c | 19 +++++++-------
|
||||||
|
util/grub-mkimagexx.c | 61 +++++++++++++++++++++++----------------------
|
||||||
|
util/mkimage.c | 20 ++++++++-------
|
||||||
|
6 files changed, 68 insertions(+), 66 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
|
||||||
|
index 93c1f0e..14f4489 100644
|
||||||
|
--- a/include/grub/util/install.h
|
||||||
|
+++ b/include/grub/util/install.h
|
||||||
|
@@ -70,7 +70,7 @@
|
||||||
|
{ "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
|
||||||
|
N_("disabled command line interface access"), 0 }, \
|
||||||
|
{ "x509key", 'x', N_("FILE"), 0, \
|
||||||
|
- N_("embed FILE as an x509 certificate for appended signature checking"), 0}, \
|
||||||
|
+ N_("embed FILE as an x509 certificate for appended signature checking"), 0}, \
|
||||||
|
{ "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE, \
|
||||||
|
"SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 1}, \
|
||||||
|
{ "verbose", 'v', 0, 0, \
|
||||||
|
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
|
||||||
|
index 881e303..244e39d 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, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
||||||
|
+ int note, char *sbat, size_t appsig_size, char **core_img, size_t *core_size,
|
||||||
|
Elf32_Addr target_addr,
|
||||||
|
struct grub_mkimage_layout *layout);
|
||||||
|
void
|
||||||
|
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
|
||||||
|
- int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
||||||
|
+ int note, char *sbat, size_t appsig_size, char **core_img, size_t *core_size,
|
||||||
|
Elf64_Addr target_addr,
|
||||||
|
struct grub_mkimage_layout *layout);
|
||||||
|
|
||||||
|
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
|
||||||
|
index 41251ce..c4b5cb3 100644
|
||||||
|
--- a/util/grub-install-common.c
|
||||||
|
+++ b/util/grub-install-common.c
|
||||||
|
@@ -475,6 +475,7 @@ int
|
||||||
|
grub_install_parse (int key, char *arg)
|
||||||
|
{
|
||||||
|
const char *end;
|
||||||
|
+
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS:
|
||||||
|
@@ -580,10 +581,11 @@ grub_install_parse (int key, char *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;
|
||||||
|
+ appsig_size = grub_strtoul (arg, &end, 10);
|
||||||
|
+ if (*arg == '\0' || *end != '\0')
|
||||||
|
+ grub_util_error (_("non-numeric or invalid appended signature size `%s'"), arg);
|
||||||
|
+ else if (appsig_size == 0)
|
||||||
|
+ grub_util_error (_("appended signature size `%s', and it should not be zero"), arg);
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
@@ -709,14 +711,12 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
|
||||||
|
|
||||||
|
grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'"
|
||||||
|
" --format '%s' --compression '%s'"
|
||||||
|
- " --appended-signture-size %zu %s%s%s\n",
|
||||||
|
- " --format '%s' --compression '%s'%s%s%s%s\n",
|
||||||
|
- dir, prefix, outname,
|
||||||
|
- mkimage_target, compnames[compression],
|
||||||
|
- appsig_size,
|
||||||
|
- note ? " --note" : "",
|
||||||
|
- disable_shim_lock ? " --disable-shim-lock" : "",
|
||||||
|
- disable_cli ? " --disable-cli" : "", s);
|
||||||
|
+ " --appended-signature-size %zu %s %s %s %s\n",
|
||||||
|
+ dir, prefix, outname,
|
||||||
|
+ mkimage_target, compnames[compression], appsig_size,
|
||||||
|
+ note ? " --note" : "",
|
||||||
|
+ disable_shim_lock ? " --disable-shim-lock" : "",
|
||||||
|
+ disable_cli ? " --disable-cli" : "", s);
|
||||||
|
free (s);
|
||||||
|
|
||||||
|
tgt = grub_install_get_image_target (mkimage_target);
|
||||||
|
@@ -725,9 +725,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,
|
||||||
|
- x509keys, nx509keys,
|
||||||
|
- config_path, tgt,
|
||||||
|
+ pubkeys, npubkeys, x509keys, nx509keys, config_path, tgt,
|
||||||
|
note, appsig_size, compression, dtb, sbat,
|
||||||
|
disable_shim_lock, disable_cli);
|
||||||
|
while (dc--)
|
||||||
|
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
|
||||||
|
index 89ca81c..e3511b0 100644
|
||||||
|
--- a/util/grub-mkimage.c
|
||||||
|
+++ b/util/grub-mkimage.c
|
||||||
|
@@ -85,8 +85,8 @@ 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},
|
||||||
|
{"disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, N_("disable command line interface access"), 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},
|
||||||
|
+ {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
|
||||||
|
{ 0, 0, 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -133,8 +133,8 @@ struct arguments
|
||||||
|
char *sbat;
|
||||||
|
int note;
|
||||||
|
int disable_shim_lock;
|
||||||
|
- size_t appsig_size;
|
||||||
|
int disable_cli;
|
||||||
|
+ size_t appsig_size;
|
||||||
|
const struct grub_install_image_target_desc *image_target;
|
||||||
|
grub_compression_t comp;
|
||||||
|
};
|
||||||
|
@@ -179,10 +179,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
- grub_errno = 0;
|
||||||
|
- arguments->appsig_size = grub_strtol(arg, &end, 10);
|
||||||
|
- if (grub_errno)
|
||||||
|
- return 0;
|
||||||
|
+ arguments->appsig_size = grub_strtoul (arg, &end, 10);
|
||||||
|
+ if (*arg == '\0' || *end != '\0')
|
||||||
|
+ grub_util_error (_("non-numeric or invalid appended signature size `%s'"), arg);
|
||||||
|
+ else if (arguments->appsig_size == 0)
|
||||||
|
+ grub_util_error (_("appended signature size `%s', and it should not be zero"), arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
@@ -351,9 +352,9 @@ main (int argc, char *argv[])
|
||||||
|
arguments.npubkeys, arguments.x509keys,
|
||||||
|
arguments.nx509keys, arguments.config,
|
||||||
|
arguments.image_target, arguments.note,
|
||||||
|
- arguments.appsig_size, arguments.comp,
|
||||||
|
- arguments.dtb, arguments.sbat,
|
||||||
|
- arguments.disable_shim_lock,
|
||||||
|
+ arguments.appsig_size,
|
||||||
|
+ arguments.comp, arguments.dtb,
|
||||||
|
+ arguments.sbat, arguments.disable_shim_lock,
|
||||||
|
arguments.disable_cli);
|
||||||
|
|
||||||
|
if (grub_util_file_sync (fp) < 0)
|
||||||
|
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
|
||||||
|
index b993054..d185246 100644
|
||||||
|
--- a/util/grub-mkimagexx.c
|
||||||
|
+++ b/util/grub-mkimagexx.c
|
||||||
|
@@ -85,15 +85,6 @@ 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
|
||||||
|
@@ -124,6 +115,14 @@ struct grub_sbat_note {
|
||||||
|
char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
|
||||||
|
};
|
||||||
|
|
||||||
|
+#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)];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
is_relocatable (const struct grub_install_image_target_desc *image_target)
|
||||||
|
{
|
||||||
|
@@ -225,7 +224,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, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
||||||
|
+ int note, char *sbat, size_t appsig_size, char **core_img, size_t *core_size,
|
||||||
|
Elf_Addr target_addr,
|
||||||
|
struct grub_mkimage_layout *layout)
|
||||||
|
{
|
||||||
|
@@ -249,7 +248,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||||
|
if (appsig_size)
|
||||||
|
{
|
||||||
|
phnum++;
|
||||||
|
- footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
|
||||||
|
+ footer_size += ALIGN_UP (sizeof (struct grub_appended_signature_note), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image_target->id != IMAGE_LOONGSON_ELF)
|
||||||
|
@@ -542,29 +541,31 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
||||||
|
phdr->p_filesz = grub_host_to_target32 (note_size);
|
||||||
|
phdr->p_memsz = 0;
|
||||||
|
phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
|
||||||
|
+ footer += note_size;
|
||||||
|
+ footer_offset += note_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));
|
||||||
|
+ 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 *) footer;
|
||||||
|
|
||||||
|
- 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);
|
||||||
|
+ 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));
|
||||||
|
- }
|
||||||
|
+ 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 + footer_offset);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
{
|
||||||
|
char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
|
||||||
|
diff --git a/util/mkimage.c b/util/mkimage.c
|
||||||
|
index cc4c79d..15cfd4b 100644
|
||||||
|
--- a/util/mkimage.c
|
||||||
|
+++ b/util/mkimage.c
|
||||||
|
@@ -883,12 +883,11 @@ 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 **x509key_paths,
|
||||||
|
- size_t nx509keys, char *config_path,
|
||||||
|
+ 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,
|
||||||
|
- int disable_shim_lock, int disable_cli)
|
||||||
|
+ int note, size_t appsig_size, grub_compression_t comp, const char *dtb_path,
|
||||||
|
+ const char *sbat_path, int disable_shim_lock,
|
||||||
|
+ int disable_cli)
|
||||||
|
{
|
||||||
|
char *kernel_img, *core_img;
|
||||||
|
size_t total_module_size, core_size;
|
||||||
|
@@ -978,6 +977,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
||||||
|
if (sbat_path != NULL && (image_target->id != IMAGE_EFI && image_target->id != IMAGE_PPC))
|
||||||
|
grub_util_error (_("SBAT data can be added only to EFI or powerpc-ieee1275 images"));
|
||||||
|
|
||||||
|
+ if (appsig_size != 0 && image_target->id != IMAGE_PPC)
|
||||||
|
+ grub_util_error (_("appended signature can be support only to powerpc-ieee1275 images"));
|
||||||
|
+
|
||||||
|
if (disable_shim_lock)
|
||||||
|
total_module_size += sizeof (struct grub_module_header);
|
||||||
|
|
||||||
|
@@ -1884,11 +1886,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, appsig_size, sbat, &core_img,
|
||||||
|
- &core_size, target_addr, &layout);
|
||||||
|
+ grub_mkimage_generate_elf32 (image_target, note, sbat, appsig_size, &core_img, &core_size,
|
||||||
|
+ target_addr, &layout);
|
||||||
|
else
|
||||||
|
- grub_mkimage_generate_elf64 (image_target, note, appsig_size, sbat, &core_img,
|
||||||
|
- &core_size, target_addr, &layout);
|
||||||
|
+ grub_mkimage_generate_elf64 (image_target, note, sbat, appsig_size, &core_img, &core_size,
|
||||||
|
+ target_addr, &layout);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
@ -476,7 +476,6 @@ fi \
|
|||||||
--appended-signature-size ${APPENDED_SIG_SIZE} \\\
|
--appended-signature-size ${APPENDED_SIG_SIZE} \\\
|
||||||
${GRUB_MODULES} \
|
${GRUB_MODULES} \
|
||||||
if [ -x /usr/bin/rpm-sign ]; then \
|
if [ -x /usr/bin/rpm-sign ]; then \
|
||||||
truncate -s -${APPENDED_SIG_SIZE} %{2}.orig \
|
|
||||||
rpm-sign --key %{4} \\\
|
rpm-sign --key %{4} \\\
|
||||||
--lkmsign %{2}.orig \\\
|
--lkmsign %{2}.orig \\\
|
||||||
--output %{2} \
|
--output %{2} \
|
||||||
|
|||||||
38
grub.patches
38
grub.patches
@ -369,4 +369,40 @@ Patch0369: 0369-blscfg-check-if-variable-is-escaped-before-consideri.patch
|
|||||||
Patch0370: 0370-Set-correctly-the-memory-attributes-for-the-kernel-P.patch
|
Patch0370: 0370-Set-correctly-the-memory-attributes-for-the-kernel-P.patch
|
||||||
Patch0371: 0371-script-execute-Don-t-let-trailing-blank-lines-determ.patch
|
Patch0371: 0371-script-execute-Don-t-let-trailing-blank-lines-determ.patch
|
||||||
Patch0372: 0372-normal-menu-Check-return-code-of-the-script-when-exe.patch
|
Patch0372: 0372-normal-menu-Check-return-code-of-the-script-when-exe.patch
|
||||||
Patch0373: 0373-Include-license-into-grub-set-password-util.patch
|
Patch0373: 0373-Include-license-into-grub-set-password-util.patch
|
||||||
|
Patch0374: 0374-libgcrypt-Import-libgcrypt-1.11.patch
|
||||||
|
Patch0375: 0375-b64dec-Import-b64dec-from-gpg-error.patch
|
||||||
|
Patch0376: 0376-b64dec-Add-harness-for-compilation-in-GRUB-environme.patch
|
||||||
|
Patch0377: 0377-libgcrypt-Adjust-import-script-definitions-and-API-u.patch
|
||||||
|
Patch0378: 0378-tests-Add-DSA-and-RSA-SEXP-tests.patch
|
||||||
|
Patch0379: 0379-keccak-Disable-acceleration-with-SSE-asm.patch
|
||||||
|
Patch0380: 0380-libgcrypt-Fix-Coverity-warnings.patch
|
||||||
|
Patch0381: 0381-libgcrypt-Remove-now-unneeded-compilation-flag.patch
|
||||||
|
Patch0382: 0382-libgcrypt-Ignore-sign-compare-warnings.patch
|
||||||
|
Patch0383: 0383-libgcrypt-Import-blake-family-of-hashes.patch
|
||||||
|
Patch0384: 0384-util-import_gcry-Make-compatible-with-Python-3.4.patch
|
||||||
|
Patch0385: 0385-util-import_gcry-Fix-pylint-warnings.patch
|
||||||
|
Patch0386: 0386-libgcrypt-Don-t-use-64-bit-division-on-platforms-whe.patch
|
||||||
|
Patch0387: 0387-libgcrypt-Fix-a-memory-leak.patch
|
||||||
|
Patch0388: 0388-docs-Write-how-to-import-new-libgcrypt.patch
|
||||||
|
Patch0389: 0389-pgp-Rename-OBJ_TYPE_PUBKEY-to-OBJ_TYPE_GPG_PUBKEY.patch
|
||||||
|
Patch0390: 0390-grub-install-Support-embedding-x509-certificates.patch
|
||||||
|
Patch0391: 0391-appended-signatures-Import-GNUTLS-s-ASN.1-descriptio.patch
|
||||||
|
Patch0392: 0392-appended-signatures-Parse-ASN1-node.patch
|
||||||
|
Patch0393: 0393-appended-signatures-Parse-PKCS-7-signed-data.patch
|
||||||
|
Patch0394: 0394-appended-signatures-Parse-X.509-certificates.patch
|
||||||
|
Patch0395: 0395-powerpc-ieee1275-Enter-lockdown-based-on-ibm-secure-.patch
|
||||||
|
Patch0396: 0396-appended-signatures-Support-verifying-appended-signa.patch
|
||||||
|
Patch0397: 0397-powerpc-ieee1275-Read-the-db-and-dbx-secure-boot-var.patch
|
||||||
|
Patch0398: 0398-appended-signatures-Introducing-key-management-envir.patch
|
||||||
|
Patch0399: 0399-appended-signatures-Create-db-and-dbx-lists.patch
|
||||||
|
Patch0400: 0400-appended-signatures-Using-db-and-dbx-lists-for-signa.patch
|
||||||
|
Patch0401: 0401-appended-signatures-GRUB-commands-to-manage-the-cert.patch
|
||||||
|
Patch0402: 0402-appended-signatures-GRUB-commands-to-manage-the-hash.patch
|
||||||
|
Patch0403: 0403-appended-signatures-Verification-tests.patch
|
||||||
|
Patch0404: 0404-docs-grub-Document-signing-GRUB-under-UEFI.patch
|
||||||
|
Patch0405: 0405-docs-grub-Document-signing-GRUB-with-an-appended-sig.patch
|
||||||
|
Patch0406: 0406-docs-grub-Document-appended-signature.patch
|
||||||
|
Patch0407: 0407-libtasn1-Fix-include-path-for-grub.patch
|
||||||
|
Patch0408: 0408-docs-fix-duplicated-entries.patch
|
||||||
|
Patch0409: 0409-powerpc-ieee1275-Add-support-for-signing-GRUB-with-a.patch
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
Name: grub2
|
Name: grub2
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
Version: 2.12
|
Version: 2.12
|
||||||
Release: 33%{?dist}
|
Release: 34%{?dist}
|
||||||
Summary: Bootloader with support for Linux, Multiboot and more
|
Summary: Bootloader with support for Linux, Multiboot and more
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
URL: http://www.gnu.org/software/grub/
|
URL: http://www.gnu.org/software/grub/
|
||||||
@ -574,6 +574,10 @@ fi
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Nov 21 2025 Nicolas Frayer <nfrayer@redhat.com> 2.12-34
|
||||||
|
- powerpc: Add appended signature feature
|
||||||
|
- Resolves: #RHEL-24510
|
||||||
|
|
||||||
* Thu Nov 06 2025 Leo Sandoval <lsandova@redhat.com> 2.12-33
|
* Thu Nov 06 2025 Leo Sandoval <lsandova@redhat.com> 2.12-33
|
||||||
- Include license into grub-set-password util
|
- Include license into grub-set-password util
|
||||||
- Resolves: #RHEL-120704
|
- Resolves: #RHEL-120704
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user