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