-
Notifications
You must be signed in to change notification settings - Fork 493
/
0045-mkimage-pgp-move-single-public-key-into-its-own-sect.patch
261 lines (234 loc) · 8.72 KB
/
0045-mkimage-pgp-move-single-public-key-into-its-own-sect.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
From eaa371d26be8f76f9d7ce7e9c4b5d30684a48f11 Mon Sep 17 00:00:00 2001
From: Markus Boehme <markubo@amazon.com>
Date: Mon, 24 Oct 2022 15:20:23 +0000
Subject: [PATCH] mkimage, pgp: move single public key into its own section of
EFI image
If mkimage is asked to embed a single public key for signature checking
into an EFI image, move that key into a new .pubkey section of the PE
file. Moving the key into its dedicated section allows for easily
swapping the public key, e.g. using objcopy, without having to rebuild
the image.
If more than one key is to be embedded, no new section is created and
all keys are embedded as modules just as before. The PGP signature
verification will check both of these sources for valid keys.
Signed-off-by: Markus Boehme <markubo@amazon.com>
---
grub-core/commands/pgp.c | 28 ++++++++++++++
include/grub/efi/efi.h | 2 +-
util/mkimage.c | 84 +++++++++++++++++++++++++++-------------
3 files changed, 87 insertions(+), 27 deletions(-)
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
index b81ac0a..5fa1e8e 100644
--- a/grub-core/commands/pgp.c
+++ b/grub-core/commands/pgp.c
@@ -32,6 +32,7 @@
#include <grub/kernel.h>
#include <grub/extcmd.h>
#include <grub/verify.h>
+#include <grub/efi/efi.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -959,6 +960,33 @@ GRUB_MOD_INIT(pgp)
grub_pk_trusted = pk;
}
+#ifdef GRUB_MACHINE_EFI
+ {
+ grub_addr_t pubkey_section;
+ grub_uint32_t pubkey_vsz;
+
+ pubkey_section = grub_efi_section_addr (".pubkey", &pubkey_vsz);
+ if (pubkey_section)
+ {
+ struct grub_file pseudo_file;
+ struct grub_public_key *pk;
+
+ grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
+
+ pseudo_file.fs = &pseudo_fs;
+ pseudo_file.size = pubkey_vsz;
+ pseudo_file.data = (char *) pubkey_section;
+
+ pk = grub_load_public_key (&pseudo_file);
+ if (!pk)
+ grub_fatal ("error loading key from .pubkey section: %s\n", grub_errmsg);
+
+ pk->next = grub_pk_trusted;
+ grub_pk_trusted = pk;
+ }
+ }
+#endif /* GRUB_MACHINE_EFI */
+
if (!val)
grub_env_set ("check_signatures", grub_pk_trusted ? "enforce" : "no");
diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h
index 5841a2e..d580b6b 100644
--- a/include/grub/efi/efi.h
+++ b/include/grub/efi/efi.h
@@ -152,7 +152,7 @@ grub_err_t grub_arch_efi_linux_boot_image(grub_addr_t addr, grub_size_t size,
char *args, int nx_enabled);
#endif
-grub_addr_t grub_efi_section_addr (const char *section, grub_uint32_t *vsz);
+grub_addr_t EXPORT_FUNC(grub_efi_section_addr) (const char *section, grub_uint32_t *vsz);
void grub_efi_mm_init (void);
void grub_efi_mm_fini (void);
diff --git a/util/mkimage.c b/util/mkimage.c
index 1455c94..01362d1 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -65,14 +65,14 @@
+ GRUB_PE32_SIGNATURE_SIZE \
+ sizeof (struct grub_pe32_coff_header) \
+ sizeof (struct grub_pe32_optional_header) \
- + 5 * sizeof (struct grub_pe32_section_table), \
+ + 6 * sizeof (struct grub_pe32_section_table), \
GRUB_PE32_FILE_ALIGNMENT)
#define EFI64_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE \
+ GRUB_PE32_SIGNATURE_SIZE \
+ sizeof (struct grub_pe32_coff_header) \
+ sizeof (struct grub_pe64_optional_header) \
- + 5 * sizeof (struct grub_pe32_section_table), \
+ + 6 * sizeof (struct grub_pe32_section_table), \
GRUB_PE32_FILE_ALIGNMENT)
static const struct grub_install_image_target_desc image_targets[] =
@@ -887,12 +887,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
char *kernel_img, *core_img;
size_t total_module_size, core_size;
size_t memdisk_size = 0, config_size = 0;
- size_t prefix_size = 0, dtb_size = 0, sbat_size = 0;
+ size_t prefix_size = 0, dtb_size = 0, pubkey_size = 0, sbat_size = 0;
char *kernel_path;
size_t offset;
struct grub_util_path_list *path_list, *p;
size_t decompress_size = 0;
struct grub_mkimage_layout layout;
+ int pubkey_section = 0;
if (comp == GRUB_COMPRESSION_AUTO)
comp = image_target->default_compression;
@@ -911,7 +912,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
else
total_module_size = sizeof (struct grub_module_info32);
- {
+ if (npubkeys == 1 && image_target->id == IMAGE_EFI)
+ pubkey_section = 1;
+
+ if (!pubkey_section) {
size_t i;
for (i = 0; i < npubkeys; i++)
{
@@ -1048,24 +1052,25 @@ grub_install_generate_image (const char *dir, const char *prefix,
offset += mod_size;
}
- {
- size_t i;
- for (i = 0; i < npubkeys; i++)
- {
- size_t curs;
- struct grub_module_header *header;
-
- curs = grub_util_get_image_size (pubkey_paths[i]);
-
- header = (struct grub_module_header *) (kernel_img + offset);
- header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY);
- header->size = grub_host_to_target32 (curs + sizeof (*header));
- offset += sizeof (*header);
-
- grub_util_load_image (pubkey_paths[i], kernel_img + offset);
- offset += ALIGN_ADDR (curs);
- }
- }
+ if (!pubkey_section)
+ {
+ size_t i;
+ for (i = 0; i < npubkeys; i++)
+ {
+ size_t curs;
+ struct grub_module_header *header;
+
+ curs = grub_util_get_image_size (pubkey_paths[i]);
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY);
+ header->size = grub_host_to_target32 (curs + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_util_load_image (pubkey_paths[i], kernel_img + offset);
+ offset += ALIGN_ADDR (curs);
+ }
+ }
{
size_t i;
@@ -1351,7 +1356,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
break;
case IMAGE_EFI:
{
- char *pe_img, *pe_sbat, *header;
+ char *pe_img, *pe_pubkey, *pe_sbat, *header;
struct grub_pe32_section_table *section;
size_t n_sections = 4;
size_t scn_size;
@@ -1369,6 +1374,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
vma = raw_data = header_size;
+ if (pubkey_section)
+ {
+ pubkey_size = ALIGN_ADDR (grub_util_get_image_size (pubkey_paths[0]));
+ pubkey_size = ALIGN_UP (pubkey_size, GRUB_PE32_FILE_ALIGNMENT);
+ if (pubkey_size == 0)
+ grub_util_error (
+ _("embedding public key '%s' would result in invalid empty section"),
+ pubkey_paths[0]);
+ }
+
if (sbat_path != NULL)
{
sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path));
@@ -1376,7 +1391,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
}
pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) +
- ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size;
+ ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) +
+ pubkey_size + sbat_size;
header = pe_img = xcalloc (1, pe_size);
memcpy (pe_img + raw_data, core_img, core_size);
@@ -1391,6 +1407,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
+ GRUB_PE32_SIGNATURE_SIZE);
c->machine = grub_host_to_target16 (image_target->pe_target);
+ if (pubkey_section)
+ n_sections++;
+
if (sbat_path != NULL)
n_sections++;
@@ -1458,7 +1477,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT);
/* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */
- PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size +
+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + pubkey_size + sbat_size +
ALIGN_UP (total_module_size,
GRUB_PE32_FILE_ALIGNMENT));
@@ -1469,7 +1488,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
GRUB_PE32_SCN_MEM_READ |
GRUB_PE32_SCN_MEM_WRITE);
- scn_size = pe_size - layout.reloc_size - sbat_size - raw_data;
+ scn_size = pe_size - layout.reloc_size - pubkey_size - sbat_size - raw_data;
section = init_pe_section (image_target, pe_img, section, "mods",
&vma, scn_size, image_target->section_align,
&raw_data, scn_size,
@@ -1477,6 +1496,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
GRUB_PE32_SCN_MEM_READ |
GRUB_PE32_SCN_MEM_WRITE);
+ if (pubkey_section)
+ {
+ pe_pubkey = pe_img + raw_data;
+ grub_util_load_image (pubkey_paths[0], pe_pubkey);
+
+ section = init_pe_section (image_target, pe_img, section, ".pubkey",
+ &vma, pubkey_size,
+ image_target->section_align,
+ &raw_data, pubkey_size,
+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA |
+ GRUB_PE32_SCN_MEM_READ);
+ }
+
if (sbat_path != NULL)
{
pe_sbat = pe_img + raw_data;
--
2.39.0