]>
Commit | Line | Data |
---|---|---|
031e5cce SM |
1 | # UEFI shim bootloader secure boot life-cycle improvements |
2 | ||
3 | ## Background | |
4 | ||
5 | In the PC ecosystem, [UEFI Secure Boot](https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-secure-boot) | |
6 | is typically configured to trust 2 authorities for signing UEFI boot code, the | |
7 | Microsoft UEFI Certificate Authority (CA) and Windows CA. When malicious or | |
8 | security compromised code is detected, 2 revocation mechanisms are provided by | |
9 | compatible UEFI implementations, signing certificate or image hash. The UEFI | |
10 | Specification does not provides any well tested additional revocation | |
11 | mechanisms. | |
12 | ||
13 | Signing certificate revocation is not practical for the Windows and Microsoft | |
14 | UEFI CAs because it would revoke too many UEFI applications and drivers, | |
15 | especially for Option ROMs. This is true even for the UEFI CA leaf certificates | |
16 | as they generally sign 1 entire year of UEFI images. For this reason UEFI | |
17 | revocations have, until recently, been performed via image hash. | |
18 | ||
19 | The UEFI shim bootloader provides a level of digital signature indirection, | |
20 | enabling more authorities to participate in UEFI Secure Boot. Shims' | |
21 | certificates typically sign targeted UEFI applications, enabling | |
22 | certificate-based revocation where it makes sense. As part of the recent | |
23 | "BootHole" security incident | |
24 | [CVE-2020-10713](https://nvd.nist.gov/vuln/detail/CVE-2020-10713), 3 | |
25 | certificates and 150 image hashes were added to the UEFI Secure Boot revocation | |
26 | database `dbx` on the popular x64 architecture. This single revocation event | |
27 | consumes 10kB of the 32kB, or roughly one third, of revocation storage | |
28 | typically available on UEFI platforms. Due to the way that UEFI merges | |
29 | revocation lists, this plus prior revocation events can result in a `dbx` that | |
30 | is almost 15kB in size, approaching 50% capacity. | |
31 | ||
32 | The large size of the BootHole revocation event is due to the inefficiency of | |
33 | revocation by image hash when there is a security vulnerability in a popular | |
34 | component signed by many authorities, sometimes with many versions. | |
35 | ||
36 | Coordinating the BootHole revocation has required numerous person months of | |
37 | planning, implementation, and testing multiplied by the number of authorities, | |
38 | deployments, & devices. It is not yet complete, and we anticipate many months | |
39 | of upgrades and testing with a long tail that may last years. | |
40 | ||
41 | Additionally, when bugs or features require updates to UEFI shim, the number of | |
42 | images signed are multiplied by the number of authorities. | |
43 | ||
44 | ## Summary | |
45 | ||
46 | Given the tremendous cost and disruption of a revocation event like BootHole, | |
47 | and increased activity by security researchers in the UEFI Secure Boot space, | |
48 | we should take action to greatly improve this process. Updating revocation | |
49 | capabilities in the UEFI specification and system firmware implementations will | |
50 | take years to deploy into the ecosystem. As such, the focus of this document is | |
51 | on improvements that can be made to the UEFI shim, which are compatible with | |
52 | existing UEFI implementations. Shim can move faster than the UEFI system | |
53 | firmware ecosystem while providing large impact to the in-market UEFI Secure | |
54 | Boot ecosystem. | |
55 | ||
56 | The background section identified 2 opportunities for improvement: | |
57 | ||
58 | 1. Improving the efficiency of revocation when a number of versions have a | |
59 | vulnerability | |
60 | ||
61 | * For example, a vulnerability spans some number of versions, it might be | |
62 | more efficient to be able to revoke by version, and simply modify the | |
63 | revocation entry to modify the version each time a vulnerability is | |
64 | detected. | |
65 | ||
66 | 2. Improving the efficiency of revocation when there are many shim variations | |
67 | ||
68 | * For example, a new shim is released to address bugs or adding features. In | |
69 | the current model, the number of images signed are multiplied by the | |
70 | number of authorities as they sign shims to gain the fixes and features. | |
71 | ||
72 | Microsoft has brainstormed with partners possible solutions for evaluation and | |
73 | feedback: | |
74 | ||
75 | 1. To improve revocation when there are many versions of vulnerable boot | |
76 | images, shim, GRUB, or otherwise, investigate methods of revoking by image | |
77 | metadata that includes generation numbers. Once targeting data is | |
78 | established (e.g. Company foo, product bar, boot component zed), each | |
79 | revocation event ideally edits an existing entry, increasing the trusted | |
80 | minimum security generation. | |
81 | ||
82 | 2. To improve revocation when there is a shim vulnerability, and there are many | |
83 | shim images, standardize on a single image shared by authorities. Each | |
84 | release of bug fixes and features result in 1 shim being signed, compressing | |
85 | the number by dozens. This has the stellar additional benefit of reducing | |
86 | the number of shim reviews, which should result in much rejoicing. The | |
87 | certificates used by a vendor to sign individual boot components would be | |
88 | picked up from additional PE files that are signed either by a shim-specific | |
89 | key controlled by Microsoft, or controlled by a vendor, but used only to | |
90 | sign additional key files. This key built into shim is functionally similar | |
91 | to a CA certificate. The certificates built into shim can be revoked by | |
92 | placing the image hash into dbx, similar to the many shim solution we have | |
93 | today. | |
94 | ||
95 | ## Proposals | |
96 | ||
97 | This document focuses on the shim bootloader, not the UEFI specification or | |
98 | updates to UEFI firmware. | |
99 | ||
100 | ### Generation Number Based Revocation | |
101 | ||
102 | Microsoft may refer to this as a form of UEFI Secure Boot Advanced Targeting | |
103 | (SBAT), perhaps to be named EFI_CERT_SBAT. This introduces a mechanism to | |
104 | require a specific level of resistance to UEFI Secure Boot bypasses. | |
105 | ||
106 | #### Generation-Based Revocation Overview | |
107 | ||
108 | Metadata that includes the vendor, product family, product, component, version | |
109 | and generation are added to artifacts. This metadata is protected by the | |
110 | digital signature. New image authorization data structures, akin to the | |
111 | EFI_CERT_foo EFI_SIGNATURE_DATA structure (see Signature Database in UEFI | |
112 | specification), describe how this metadata can be incorporated into allow or | |
113 | deny lists. In a simple implementation, 1 SBAT entry with security generations | |
114 | could be used for each revocable boot module, replacing many image hashes with | |
115 | 1 entry with security generations. To minimize the size of EFI_CERT_SBAT, the | |
116 | signature owner field might be omitted, and recommend that either metadata use | |
117 | shortened names, or perhaps the EFI_CERT_SBAT contains a hash of the | |
118 | non-generation metadata instead of the metadata itself. | |
119 | ||
120 | Ideally, servicing of the image authorization databases would be updated to | |
121 | support replacement of individual EFI_SIGNATURE_DATA items. However, if we | |
122 | assume that new UEFI variable(s) are used, to be serviced by 1 entity per | |
123 | variable (no sharing), then the existing, in-market SetVariable(), without the | |
124 | APPEND attribute, could be used. Microsoft currently issues dbx updates | |
125 | exclusively with the APPEND attribute under the assumption that multiple | |
126 | entities might be servicing dbx. When a new revocation event takes place, | |
127 | rather than increasing the size of variables with image hashes, existing | |
128 | variables can simply be updated with new security generations, consuming no | |
129 | additional space. This constrains the number of entries to the number of unique | |
130 | boot components revoked, independent of generations revoked. The solution may | |
131 | support several major/minor versions, limiting revocation to build/security | |
132 | generations, perhaps via wildcards. | |
133 | ||
134 | While previously the APPEND attribute guaranteed that it would not be possible | |
135 | to downgrade the set of revocations on a system using a previously signed | |
136 | variable update, this guarantee can also be accomplished by setting the | |
137 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute. This will verify | |
138 | that the timestamp value of the signed data is later than the current timestamp | |
139 | value associated with the data currently stored in that variable. | |
140 | ||
141 | #### Generation-Based Revocation Scenarios | |
142 | ||
143 | Products (**not** vendors, a vendor can have multiple products or even pass a | |
144 | product from one vendor to another over time) are assigned a name. Product | |
145 | names can specify a specific version or refer to the entire product family. For | |
146 | example mydistro and mydistro,12. | |
147 | ||
148 | Components that are used as a link in the UEFI Secure Boot chain of trust are | |
149 | assigned names. Examples of components are shim, GRUB, kernel, hypervisors, etc. | |
150 | ||
151 | We could conceivably support sub-components, but it's hard to conceive of a | |
152 | scenario that would trigger a UEFI variable update that wouldn't justify a | |
153 | hypervisor or kernel re-release to enforce that sub-component level from there. | |
154 | Something like a "level 1.5 hypervisor" that can exist between different kernel | |
155 | generations can be considered its own component. | |
156 | ||
157 | Each component is assigned a minimum global generation number. Vendors signing | |
158 | component binary artifacts with a specific global generation number are | |
159 | required to include fixes for any public or pre-disclosed issue required for | |
160 | that generation. Additionally, in the event that a bypass only manifests in a | |
161 | specific product's component, vendors may ask for a product-specific generation | |
162 | number to be published for one of their product's components. This avoids | |
163 | triggering an industry wide re-publishing of otherwise safe components. | |
164 | ||
165 | A product-specific minimum generation number only applies to the instance of | |
166 | that component that is signed with that product name. Another product's | |
167 | instance of the same component may be installed on the same system and would | |
168 | not be subject to the other product's product-specific minimum generation | |
169 | number. However, both of those components will need to meet the global minimum | |
170 | generation number for that component. A very likely scenario would be that a | |
171 | product is shipped with an incomplete fix required for a specific minimum | |
172 | generation number, but is labeled with that number. Rather than having the | |
173 | entire industry that uses that component re-release, just that product's | |
174 | minimum generation number would be incremented and that product's component | |
175 | re-released along with a UEFI variable update specifying that requirement. | |
176 | ||
177 | The global and product-specific generation number name spaces are not tied to | |
178 | each other. The global number is managed externally, and the vast majority of | |
179 | products will never publish a minimum product-specific generation number for | |
180 | any of their components. Unspecified, more specific generation numbers are | |
181 | treated as 0. | |
182 | ||
183 | A minimum feature set, for example enforced kernel lock down, may be required | |
184 | as well to sign and label a component with a specific generation number. As | |
185 | time goes on, it is likely that the minimum feature set required for the | |
186 | currently valid generation number will expand. (For example, hypervisors | |
187 | supporting UEFI Secure Boot guests may at some point require memory encryption | |
188 | or similar protection mechanism.) | |
189 | ||
190 | The footprint of the UEFI variable payload will expand as product-specific | |
191 | generation numbers ahead of the global number are added. However, it will | |
192 | shrink again as the global number for that component is incremented again. The | |
193 | expectation is that a product-specific or vendor-specific generation number is | |
194 | a rare event, and that the generation number for the upstream code base will | |
195 | suffice in most cases. | |
196 | ||
197 | A product-specific generation number is needed if a CVE is fixed in code that | |
198 | **only** exists in a specific product's branch. This would either be something | |
199 | like product-specific patches, or a mis-merge that only occurred in that | |
200 | product. Setting a product-specific generation number for such an event | |
201 | eliminates the need for other vendors to have to re-release the binaries for | |
202 | their products with an incremented global number. | |
203 | ||
204 | However, once the global number is bumped for the next upstream CVE fix there | |
205 | will be no further need to carry that product-specific generation number. | |
206 | Satisfying the check of the global number will also exclude any of the older | |
207 | product-specific binaries. | |
208 | ||
209 | For example: There is a global CVE disclosure and all vendors coordinate to | |
210 | release fixed components on the disclosure date. This release bumps the global | |
211 | generation number for GRUB to 4. | |
212 | ||
213 | SBAT revocation data would then require a GRUB with a global generation number | |
214 | of 4. | |
215 | ||
216 | However, Vendor C mis-merges the patches into one of their products and does | |
217 | not become aware of the fact that this mis-merge created an additional | |
218 | vulnerability until after they have published a signed binary in that, | |
219 | vulnerable, state. | |
220 | ||
221 | Vendor C's GRUB binary can now be used to compromise anyone's system. | |
222 | ||
223 | To remedy this, Vendor C will release a fixed binary with the same global | |
224 | generation number and the product-specific generation number set to 1. | |
225 | ||
226 | SBAT revocation data would then require a GRUB with a global generation number | |
227 | of 4, as well as a product-specific generation number of 1 for the product that | |
228 | had the vulnerable binary. | |
229 | ||
230 | If and when there is another upstream fix for a CVE that would bump the global | |
231 | number, this product-specific number can be dropped from the UEFI revocation | |
232 | variable. | |
233 | ||
234 | If this same Vendor C has a similar event after the global number is | |
235 | incremented, they would again set their product-specific or version-specific | |
236 | number to 1. If they have a second event on with the same component, they would | |
237 | set their product-specific or version-specific number to 2. | |
238 | ||
239 | In such an event, a vendor would set the product-specific or version-specific | |
240 | generation number based on whether the mis-merge occurred in all of their | |
241 | branches or in just a subset of them. The goal is generally to limit end | |
242 | customer impact with as few re-releases as possible, while not creating an | |
243 | unnecessarily large UEFI revocation variable payload. | |
244 | ||
245 | | | prior to<br>disclosure | after<br>disclosure | after Vendor C's<br>first update | after Vendor C's<br>second update | after next global<br>disclosure | | |
246 | |--------------------------------------------------------------------------------------|------------------------|---------------------|----------------------------------|----------------------------------|---------------------------------| | |
247 | | GRUB global<br>generation number in<br>artifacts .sbat section | 3 | 4 | 4 | 4 | 5 | | |
248 | | Vendor C's product-specific<br>generation number in artifact's<br>.sbat section | 1 | 1 | 5 | 6 | 1 | | |
249 | | GRUB global<br>generation number in<br>UEFI SBAT revocation variable | 3 | 4 | 4 | 4 | 5 | | |
250 | | Vendor C's product-specific<br>generation number in<br>UEFI SBAT revocation variable | not set | not set | 5 | 6 | not set | | |
251 | ||
252 | The product-specific generation number does not reset and continues to | |
253 | monotonically increase over the course of these events. Continuity of more | |
254 | specific generation numbers must be maintained in this way in order to satisfy | |
255 | checks against older revocation data. | |
256 | ||
257 | The variable payload will be stored publicly in the shim source base and | |
258 | identify the global generation associated with a product or version-specific | |
259 | one. The payload is also built into shim to additionally limit exposure. | |
260 | ||
261 | #### Retiring Signed Releases | |
262 | ||
263 | Products that have reached the end of their support life by definition no | |
264 | longer receive patches. They are also generally not examined for CVEs. Allowing | |
265 | such unsupported products to continue to participate in UEFI Secure Boot is at | |
266 | the very least questionable. If an EoSL product is made up of commonly used | |
267 | components, such as the GRUB and the Linux kernel, it is reasonable to assume | |
268 | that the global generation numbers will eventually move forward and exclude | |
269 | those products from booting on a UEFI Secure Boot enabled system. However a | |
270 | product made up of GRUB and a closed source kernel is just as conceivable. In | |
271 | that case the kernel version may never move forward once the product reaches | |
272 | its end of support. Therefor it is recommended that the product-specific | |
273 | generation number be incremented past the latest one shown in any binary for | |
274 | that product, effectively disabling that product on UEFI Secure Boot enabled | |
275 | systems. | |
276 | ||
277 | A subset of this case would be a beta-release that may contain eventually | |
278 | abandoned, experimental, kernel code. Such releases should have their | |
279 | product-specific generation numbers incremented past the latest one shown in | |
280 | any released, or unreleased, binary signed with a production key. | |
281 | ||
282 | Until a release is retired in this manner, vendors are responsible for keeping | |
283 | up with fixes for CVEs and ensuring that any known signed binaries containing | |
284 | known CVEs are denied from booting on UEFI Secure Boot enabled systems via the | |
285 | most up to date UEFI metadata. | |
286 | ||
287 | #### Vendor Key Files | |
288 | ||
289 | Even prior to or without moving to one-shim, it is desirable to get every | |
290 | vendor onto as few shims as possible. Ideally a vendor would have a single shim | |
291 | signed with their certificate embedded and then use that certificate to sign | |
292 | additional <Vendor>_key.EFI key files that then contain all the keys that the | |
293 | individual components for their products are signed with. This file name needs | |
294 | to be registered at the time of shim review and should not be changed without | |
295 | going back to a shim review. A vendor should be able to store as many | |
296 | certificated (or a CA certificate) as they need for all the components of all | |
297 | of their products. Older versions of this file can be revoked via SBAT. In | |
298 | order to limit the footprint of the SBAT revocation metadata, it is vital that | |
299 | vendors do not create additional key files beyond what they have been approved | |
300 | for at shim review. | |
301 | ||
302 | #### Key Revocations | |
303 | ||
304 | Since Vendor Product keys are brought into Shim as signed binaries, generation | |
305 | numbering can and should be used to revoke them in case of a private key | |
306 | compromise. | |
307 | ||
308 | #### Kernel support for SBAT | |
309 | ||
310 | The initial SBAT implementation will add SBAT metadata to Shim and GRUB and | |
311 | enforce SBAT on all components labeled with it. Until a component (e.g. the | |
312 | Linux kernel gains SBAT metadata) it can not be revoked via SBAT, but only by | |
313 | revoking the keys signing that component. These keys will should live in | |
314 | separate, product-specific signed PE files that contain **only** the | |
315 | certificate and SBAT metadata for the key files. These key files can then be | |
316 | revoked via SBAT in order to invalidate and replace a specific key. While | |
317 | certificates built into Shim can be revoked via SBAT and Shim introspection, | |
318 | this practice would still result in a proliferation of Shim binaries that would | |
319 | need to be revoked via dbx in the event of an early Shim code bug. Therefore, | |
320 | SBAT must be used in conjunction with separate Vendor Product Key binaries. | |
321 | ||
322 | At the time of this writing, revoking a Linux kernel with a lockdown compromise | |
323 | is not spelled out as a requirement for shim signing. In fact, with limited dbx | |
324 | space and the size of the attack surface for lockdown it would be impractical | |
325 | do so without SBAT. With SBAT it should be possible to raise the bar, and treat | |
326 | lockdown bugs that would allow a kexec of a tampered kernel as revocations. | |
327 | ||
328 | #### Kernels execing other kernels (aka kexec, fast reboot) | |
329 | ||
330 | It is expected that kexec and other similar implementations of kernels spawning | |
331 | other kernels will eventually consume and honor SBAT metadata. Until they do, | |
332 | the same Vendor Product Key binary based revocation will need to be used for | |
333 | them. | |
334 | ||
335 | #### Generation-Based Revocation Metadata | |
336 | ||
337 | Adding a .sbat section containing the SBAT metadata structure to PE images. | |
338 | ||
339 | | field | meaning | | |
340 | |---|---| | |
341 | | component_name | the name we're comparing | |
342 | | component_generation | the generation number for the comparison | |
343 | | vendor_name | human readable vendor name | |
344 | | vendor_package_name | human readable package name | |
345 | | vendor_version | human readable package version (maybe machine parseable too, not specified here) | |
346 | | vendor_url | url to look stuff up, contact, whatever. | |
347 | ||
348 | The format of this .sbat section is comma separated values, or more | |
349 | specifically UTF-8 encoded strings. | |
350 | ||
351 | ## Example sbat sections | |
352 | ||
353 | For grub, a build from a fresh checkout of upstream might have the following in | |
354 | `.sbat`: | |
355 | ``` | |
356 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
357 | grub,1,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/ | |
358 | ``` | |
359 | ||
360 | A Fedora build believed to have exactly the same set of vulnerabilities plus | |
361 | one that was never upstream might have: | |
362 | ``` | |
363 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
364 | grub,1,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/ | |
365 | grub.fedora,1,The Fedora Project,grub2,2.04-31.fc33,https://src.fedoraproject.org/rpms/grub2 | |
366 | ``` | |
367 | ||
368 | Likewise, Red Hat has various builds for RHEL 7 and RHEL 8, all of which have | |
369 | something akin to the following in `.sbat`: | |
370 | ``` | |
371 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
372 | grub,1,Free Software Foundation,grub,2.02,https://www.gnu.org/software/grub/ | |
373 | grub.fedora,1,Red Hat Enterprise Linux,grub2,2.02-0.34.fc24,mail:secalert@redhat.com | |
374 | grub.rhel,1,Red Hat Enterprise Linux,grub2,2.02-0.34.el7_2,mail:secalert@redhat.com | |
375 | ``` | |
376 | ||
377 | The Debian package believed to have the same set of vulnerabilities as upstream | |
378 | might have: | |
379 | ``` | |
380 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
381 | grub,1,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/ | |
382 | grub.debian,1,Debian,grub2,2.04-12,https://packages.debian.org/source/sid/grub2 | |
383 | ``` | |
384 | ||
385 | Another party known for less than high quality software who carry a bunch of | |
386 | out of tree grub patches on top of a very old grub version from before any of | |
387 | the upstream vulns were committed to the tree. They haven't ever had the | |
388 | upstream vulns, and in fact have never shipped any vulnerabilities. Their grub | |
389 | `.sbat` might have the following (which we'd be very suspect of signing, but | |
390 | hey, suppose it turns out to be correct): | |
391 | ``` | |
392 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
393 | grub.acme,1,Acme Corporation,grub,1.96-8191,https://acme.arpa/packages/grub | |
394 | ``` | |
395 | ||
396 | At the same time, we're all shipping the same `shim-16` codebase, and in our | |
397 | `shim` builds, we all have the following in `.sbat`: | |
398 | ``` | |
399 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
400 | shim,1,UEFI shim,shim,16,https://github.com/rhboot/shim | |
401 | ``` | |
402 | ||
403 | ## How to add .sbat sections | |
404 | ||
405 | Components that do not have special code to construct the final PE files can | |
406 | simply add this section using objcopy(1): | |
407 | ||
408 | ``` | |
409 | objcopy --set-section-alignment '.sbat=512' --add-section .sbat=sbat.csv foo.efi | |
410 | ||
411 | ``` | |
412 | ||
413 | Older versions of objcopy(1) do not support --set-section-alignment which is | |
414 | required to force the correct alignment expected from a PE file. As long as | |
415 | there is another step, later in the build process, such as an linker invocation | |
416 | that forces alignment, objcopy(1) does not need to align an intermediate file. | |
417 | ||
418 | #### UEFI SBAT Variable content | |
419 | ||
420 | The SBAT UEFI variable contains a descriptive form of all components used by | |
421 | all UEFI signed Operating Systems, along with a minimum generation number for | |
422 | each one. It may also contain a product-specific generation number, which in | |
423 | turn may also specify version-specific generation numbers. It is expected that | |
424 | specific generation numbers will be exceptions that will be obsoleted if and | |
425 | when the global number for a component is incremented. | |
426 | ||
427 | Initially the SBAT UEFI variable will set generation numbers for | |
428 | components to 1, but is expected to grow as CVEs are discovered and | |
429 | fixed. The following show the evolution over a sample set of events: | |
430 | ||
431 | ## Starting point | |
432 | ||
433 | Before CVEs are encountered, an undesirable moudule was built into the a fedora | |
434 | grub, so it's product-specific generation number has been bumped: | |
435 | ||
436 | ``` | |
437 | sbat,1 | |
438 | shim,1 | |
439 | grub,1 | |
440 | grub.fedora,2 | |
441 | ``` | |
442 | ||
443 | ## Along comes bug 1 | |
444 | ||
445 | Another kind security researcher shows up with a serious bug, and this one was | |
446 | in upstream grub-0.94 and every version after that, and is shipped by all | |
447 | vendors. | |
448 | ||
449 | At this point, each vendor updates their grub builds, and updates the | |
450 | `component_generation` in `.sbat` to `2`. The GRUB upstream build now looks like: | |
451 | ``` | |
452 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
453 | grub,2,Free Software Foundation,grub,2.05,https://www.gnu.org/software/grub/ | |
454 | ``` | |
455 | ||
456 | But Fedora's now looks like: | |
457 | ``` | |
458 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
459 | grub,2,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/ | |
460 | grub.fedora,2,The Fedora Project,grub2,2.04-33.fc33,https://src.fedoraproject.org/rpms/grub2 | |
461 | ``` | |
462 | ||
463 | Other distros either rebase on 2.05 or theirs change similarly to Fedora's. We | |
464 | now have two options for Acme Corp: | |
465 | - add a `grub.acme,2` entry to `SBAT` | |
466 | - have Acme Corp add | |
467 | `grub,2,Free Software Foundation,grub,1.96,https://www.gnu.org/software/grub/` | |
468 | to their new build's `.sbat` | |
469 | ||
470 | We talk to Acme and they agree to do the latter, thus saving flash real estate | |
471 | to be developed on another day. Their binary now looks like: | |
472 | ``` | |
473 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
474 | grub,2,Free Software Foundation,grub,1.96,https://www.gnu.org/software/grub/ | |
475 | grub.acme,1,Acme Corporation,grub,1.96-8192,https://acme.arpa/packages/grub | |
476 | ``` | |
477 | ||
478 | The UEFI CA issues an update which looks like: | |
479 | ``` | |
480 | sbat,1 | |
481 | shim,1 | |
482 | grub,2 | |
483 | grub.fedora,2 | |
484 | ``` | |
485 | ||
486 | Which is literally the byte array: | |
487 | ``` | |
488 | { | |
489 | 's', 'b', 'a', 't', ',', '1', '\n', | |
490 | 's', 'h', 'i', 'm', ',', '1', '\n', | |
491 | 'g', 'r', 'u', 'b', ',', '2', '\n', | |
492 | 'g', 'r', 'u', 'b', '.', 'f', 'e', 'd', 'o', 'r', 'a', ',', '2', '\n', | |
493 | } | |
494 | ``` | |
495 | ||
496 | ## Acme Corp gets with the program | |
497 | ||
498 | Acme at this point discovers some features have been added to grub and they | |
499 | want them. They ship a new grub build that's completely rebased on top of | |
500 | upstream and has no known vulnerabilities. Its `.sbat` data looks like: | |
501 | ``` | |
502 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
503 | grub,2,Free Software Foundation,grub,2.05,https://www.gnu.org/software/grub/ | |
504 | grub.acme,1,Acme Corporation,grub,2.05-1,https://acme.arpa/packages/grub | |
505 | ``` | |
506 | ||
507 | ## Someone was wrong on the Internet and bug 2 | |
508 | ||
509 | Debian discovers that they actually shipped bug 0 as well (woops). They | |
510 | produce a new build which fixes it and has the following in `.sbat`: | |
511 | ``` | |
512 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
513 | grub,2,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/ | |
514 | grub.debian,2,Debian,grub2,2.04-13,https://packages.debian.org/source/sid/grub2 | |
515 | ``` | |
516 | ||
517 | Before the UEFI CA has released an update, though, another upstream issue is | |
518 | found. Everybody updates their builds as they did for bug 1. Debian also | |
519 | updates theirs, as they would, and their new build has: | |
520 | ``` | |
521 | sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md | |
522 | grub,3,Free Software Foundation,grub,2.04,https://www.gnu.org/software/grub/ | |
523 | grub.debian,2,Debian,grub2,2.04-13,https://packages.debian.org/source/sid/grub2 | |
524 | ``` | |
525 | ||
526 | And the UEFI CA issues an update to SBAT which has: | |
527 | ``` | |
528 | sbat,1 | |
529 | shim,1 | |
530 | grub,3 | |
531 | grub.fedora,2 | |
532 | ``` | |
533 | ||
534 | The grub.fedora product-specific line could be dropped since a Fedora GRUB with | |
535 | a global generation number that also contained the bug that prompted the | |
536 | fedora-specific revocation was never published. This results in the following | |
537 | reduced UEFI SBAT revocation update: | |
538 | ``` | |
539 | sbat,1 | |
540 | shim,1 | |
541 | grub,3 | |
542 | ``` | |
543 | ||
544 | Two key things here: | |
545 | - `grub.debian` still got updated to `2` in their `.sbat` data, because a | |
546 | vulnerability was fixed that is only covered by that updated number. | |
547 | - There is still no `SBAT` update for `grub.debian`, because there's no binary | |
548 | that needs it which is not covered by updating `grub` to `3`. |