Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Revocation Delivery Proposal #655

Open
jsetje opened this issue Apr 16, 2024 · 6 comments
Open

RFC: Revocation Delivery Proposal #655

jsetje opened this issue Apr 16, 2024 · 6 comments
Assignees

Comments

@jsetje
Copy link
Collaborator

jsetje commented Apr 16, 2024

Problem:

Revocations beyond dbx require updating non-authenticated boot
services variables. Unlike the signed dbx blobs that can be applied at
runtime independently from updating the first stage bootloader, these
revocations were initially built into shim as an optional “latest” and
automatic payload. These payloads exist for both SBAT (shim based
Linux distros) and SKU Si (bootmgr based Windows distros). Binaries
from both ecosystems can be used to attack both ecosystems on typical
systems that trust both the UEFI and Window CA.

While automatically putting a system into the most secure state
possible by applying the latest revocation quickly is desirable, it
carries a very real risk of preventing a legitimately installed system
from booting. These scenarios are fall-back after and update and dual
boot. While shim now supports picking up the revocation payload from a
separate binary blob that can be updated independently from shim, the
policy for deploying this blob will depend on how a particular system
is being managed, similar to how dbx updates are being deployed.

Current state:

Most Linux distros are able to deliver a built-in automatic SBAT
revocation that revokes binaries that are roughly 1 year old or
older. Ones that are not have shifted to an empty automatic SBAT
payload. All Linux distros deliver a shim that allows an opt-in SKU Si
revocation to be applied, none of them do this automatically.

Windows currently only applies SKU Si revocations based on a manual
opt-in and does not deliver SBAT revocations.

Proposal:

Systems should automatically apply the most recent payload for the
ecosystem they are not in, unless the other binary is seen as an
active bootloader before the one being booted on the boot list. (XXX:
This seems awfully complex to protect dual boot systems that already
have terrible compatibility. - Still this should be handled the same
way by shim and bootmgr)

Systems that potentially need to support falling back to an older
version of the same OS will need to manage revocations either manually
or as part of an automated orchestration that drives the update /
fallback process above the OS instance.

Solution:

Deliver revocations in a separate package that has dependencies that
prevent it from being installed on an OS that it would revoke. This
package also delivers previous revocations in cumulative blobs. Which
revocation is put in place for shim to install can be configured as:

  1. Apply the most recent revocation that does not revoke the OS being
    updated to.

  2. Apply the most recent revocation that does not revoke the OS being
    updated from.

  3. Apply the most recent revocation that does not revoke the OS
    installed at an alternate, supplied, mount location.

  4. Manually lock revocations at a specific level.

Defaulting to (2) where (2) is effectively (1) for a fresh install.

Optional dual boot friendly packages:

Deliver an alternate stream of these packages that do not deliver SKU
Si revocations for dual boot systems that an admin can opt into under
the assumption that they are sometimes booting Windows and want
Windows to manage its own revocations.

Rejected Proposal:

Record the hash of in-use bootloaders and add them to an SBAT specific
exception list that allows only that binary to elude SBAT based
revocation at the same time as applying the revocation.

Pros:
- This would protect from automated attacks using a binary that
doesn't precisely match the one listed by hash.

Cons:
- The fallback OS version could be updated to an intermediate
version.
- Complex to apply correctly without risking a roll-back attack.
shim would need to examine the binary and determine that it matches
the sbat level that's being revoked at the same time. This creates
a new, non-trivial attack surface.

Orthogonal concept:

Generic UEFI CA signed revocation.efi binaries could be delivered to fwupd
and installed via that framework.

@jsetje jsetje self-assigned this Apr 16, 2024
@jsetje
Copy link
Collaborator Author

jsetje commented Apr 22, 2024

I posted this issue under the shim repo since more folks are likely to see it here. I expect this to mostly be implemented in https://github.com/rhboot/certwrapper unless I find a bug with the revocation.efi support in shim.

Additional information on the bootmgr SKU Si revocation mechanism can be found here:
https://support.microsoft.com/en-us/topic/kb5027455-guidance-for-blocking-vulnerable-windows-boot-managers-522bb851-0a61-44ad-aa94-ad11119c5e91 As of 15.8 shim does have support to apply those revocations as "latest".

@hughsie
Copy link

hughsie commented Apr 25, 2024

I was pinged about this today -- and I'm wondering what exactly fwupd and the LVFS should do. For instance, could we read /sys/firmware/efi/efivars/SbatLevelRT-605dab50-e046-4300-abb6-3dd810dd8b23 compare it against the metadata from the LVFS and fail an HSI check if the EFI key is older than the metadata value? Or read the shim binary and parse the .sbat section and do the same? That'd get us a nice few FAILED lines on a Insights report for instance.

@jsetje
Copy link
Collaborator Author

jsetje commented Apr 25, 2024

LVFS could distribute revocations.efi as well, but it's also not strictly necessary. It might be good to have that mechanism in place in case we ever had to rapidly respond to something bad happening.

I'm not sure I entirely understand what you mean by the check. Would that basically be an audit that would flag if a system is not up to date? That might be nice to have.

@hughsie
Copy link

hughsie commented Apr 29, 2024

Would that basically be an audit that would flag if a system is not up to date?

Yes -- although I'm a bit unsure where the "canonical truth" is for the sbat level -- and then there's also the sbat data in each file in the ESP, e.g. fwupdtool firmware-parse /boot/efi/EFI/fedora/shimx64.efi pefile gives:

<firmware gtype="FuPefileFirmware">
  <data size="0xe7cb0">[GInputStream]</data>
  <firmware>
    ...
  </firmware>
  <firmware gtype="FuSbatlevelSection">
    <id>.sbatlevel</id>
    <offset>0x7c200</offset>
    <data size="0x6a">AAAAAAgAAAA3AAAAc2JhdCwxLDIwMjMwMTI5MDAKc2hpbSwyCmdydWIsMwpncnViLmRlYmlhbiw0CgBzYmF0LDEsMjAyNDAxMDkwMApzaGltLDQKZ3J1YiwzCmdydWIuZGViaWFuLDQKAA==</data>
    <firmware gtype="FuCsvFirmware">
      <flags>no-auto-detection</flags>
      <id>previous</id>
      <offset>0xc</offset>
      <data size="0x2d">c2JhdCwxLDIwMjMwMTI5MDAKc2hpbSwyCmdydWIsMwpncnViLmRlYmlhbiw0</data>
      <write_column_ids>false</write_column_ids>
      <firmware gtype="FuCsvEntry">
        <id>sbat</id>
        <data size="0x11">c2JhdCwxLDIwMjMwMTI5MDA=</data>
        <values>
          <component_generation>1</component_generation>
          <date_stamp>2023012900</date_stamp>
        </values>
      </firmware>
      <firmware gtype="FuCsvEntry">
        <id>shim</id>
        <idx>0x1</idx>
        <data size="0x6">c2hpbSwy</data>
        <values>
          <component_generation>2</component_generation>
        </values>
      </firmware>
      <firmware gtype="FuCsvEntry">
        <id>grub</id>
        <idx>0x2</idx>
        <data size="0x6">Z3J1Yiwz</data>
        <values>
          <component_generation>3</component_generation>
        </values>
      </firmware>
      <firmware gtype="FuCsvEntry">
        <id>grub.debian</id>
        <idx>0x3</idx>
        <data size="0xd">Z3J1Yi5kZWJpYW4sNA==</data>
        <values>
          <component_generation>4</component_generation>
        </values>
      </firmware>
    </firmware>
    <firmware gtype="FuCsvFirmware">
      <flags>no-auto-detection</flags>
      <id>latest</id>
      <idx>0x1</idx>
      <offset>0x3b</offset>
      <data size="0x2d">c2JhdCwxLDIwMjQwMTA5MDAKc2hpbSw0CmdydWIsMwpncnViLmRlYmlhbiw0</data>
      <write_column_ids>false</write_column_ids>
      <firmware gtype="FuCsvEntry">
        <id>sbat</id>
        <data size="0x11">c2JhdCwxLDIwMjQwMTA5MDA=</data>
        <values>
          <component_generation>1</component_generation>
          <date_stamp>2024010900</date_stamp>
        </values>
      </firmware>
      <firmware gtype="FuCsvEntry">
        <id>shim</id>
        <idx>0x1</idx>
        <data size="0x6">c2hpbSw0</data>
        <values>
          <component_generation>4</component_generation>
        </values>
      </firmware>
      <firmware gtype="FuCsvEntry">
        <id>grub</id>
        <idx>0x2</idx>
        <data size="0x6">Z3J1Yiwz</data>
        <values>
          <component_generation>3</component_generation>
        </values>
      </firmware>
      <firmware gtype="FuCsvEntry">
        <id>grub.debian</id>
        <idx>0x3</idx>
        <data size="0xd">Z3J1Yi5kZWJpYW4sNA==</data>
        <values>
          <component_generation>4</component_generation>
        </values>
      </firmware>
    </firmware>
  </firmware>
  <firmware>
    <id>.data</id>
    <offset>0x7c400</offset>
    <data size="0x2e4f4">[GInputStream]</data>
  </firmware>
  <firmware>
    <id>.vendor_cert</id>
    <offset>0xaaa00</offset>
    <data size="0x46f">[GInputStream]</data>
  </firmware>
  <firmware>
    <id>.dynamic</id>
    <offset>0xab000</offset>
    <data size="0x100">EAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAgDgAAAAAABgAAAAAAAAAAMA0AAAAAAAoAAAAAAAAArqsAAAAAAAALAAAAAAAAABgAAAAAAAAABwAAAAAAAAAAYAsAAAAAAAgAAAAAAAAAaLQBAAAAAAAJAAAAAAAAABgAAAAAAAAAHgAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</data>
  </firmware>
  <firmware>
    <id>.rela</id>
    <offset>0xab200</offset>
    <data size="0x1b468">[GInputStream]</data>
  </firmware>
  <firmware gtype="FuCsvFirmware">
    <flags>no-auto-detection</flags>
    <id>.sbat</id>
    <offset>0xc6800</offset>
    <data size="0x19f">[GInputStream]</data>
    <write_column_ids>true</write_column_ids>
    <firmware gtype="FuCsvEntry">
      <id>sbat</id>
      <version>1</version>
      <version_raw>0x1</version_raw>
      <data size="0x4b">c2JhdCwxLFNCQVQgVmVyc2lvbixzYmF0LDEsaHR0cHM6Ly9naXRodWIuY29tL3JoYm9vdC9zaGltL2Jsb2IvbWFpbi9TQkFULm1k</data>
      <values>
        <vendor_name>SBAT Version</vendor_name>
        <vendor_package_name>sbat</vendor_package_name>
        <vendor_url>https://github.com/rhboot/shim/blob/main/SBAT.md</vendor_url>
      </values>
    </firmware>
    <firmware gtype="FuCsvEntry">
      <id>shim</id>
      <idx>0x1</idx>
      <version>1</version>
      <version_raw>0x4</version_raw>
      <data size="0x36">c2hpbSw0LFVFRkkgc2hpbSxzaGltLDEsaHR0cHM6Ly9naXRodWIuY29tL3JoYm9vdC9zaGlt</data>
      <values>
        <vendor_name>UEFI shim</vendor_name>
        <vendor_package_name>shim</vendor_package_name>
        <vendor_url>https://github.com/rhboot/shim</vendor_url>
      </values>
    </firmware>
    <firmware gtype="FuCsvEntry">
      <id>shim.rh</id>
      <idx>0x2</idx>
      <version>15.8</version>
      <version_raw>0x3</version_raw>
      <data size="0x5b">c2hpbS5yaCwzLFRoZSBGZWRvcmEgUHJvamVjdCxzaGltLDE1LjgsaHR0cHM6Ly9zcmMuZmVkb3JhcHJvamVjdC5vcmcvcnBtcy9zaGltLXVuc2lnbmVkLXg2NA==</data>
      <values>
        <vendor_name>The Fedora Project</vendor_name>
        <vendor_package_name>shim</vendor_package_name>
        <vendor_url>https://src.fedoraproject.org/rpms/shim-unsigned-x64</vendor_url>
      </values>
    </firmware>
    <firmware gtype="FuCsvEntry">
      <id>shim.redhat</id>
      <idx>0x3</idx>
      <version>15.8</version>
      <version_raw>0x3</version_raw>
      <data size="0x5f">c2hpbS5yZWRoYXQsMyxUaGUgRmVkb3JhIFByb2plY3Qsc2hpbSwxNS44LGh0dHBzOi8vc3JjLmZlZG9yYXByb2plY3Qub3JnL3JwbXMvc2hpbS11bnNpZ25lZC14NjQ=</data>
      <values>
        <vendor_name>The Fedora Project</vendor_name>
        <vendor_package_name>shim</vendor_package_name>
        <vendor_url>https://src.fedoraproject.org/rpms/shim-unsigned-x64</vendor_url>
      </values>
    </firmware>
    <firmware gtype="FuCsvEntry">
      <id>shim.fedora</id>
      <idx>0x4</idx>
      <version>15.8</version>
      <version_raw>0x3</version_raw>
      <data size="0x5f">c2hpbS5mZWRvcmEsMyxUaGUgRmVkb3JhIFByb2plY3Qsc2hpbSwxNS44LGh0dHBzOi8vc3JjLmZlZG9yYXByb2plY3Qub3JnL3JwbXMvc2hpbS11bnNpZ25lZC14NjQ=</data>
      <values>
        <vendor_name>The Fedora Project</vendor_name>
        <vendor_package_name>shim</vendor_package_name>
        <vendor_url>https://src.fedoraproject.org/rpms/shim-unsigned-x64</vendor_url>
      </values>
    </firmware>
  </firmware>
</firmware>

@jsetje
Copy link
Collaborator Author

jsetje commented Apr 29, 2024

At the moment, the canonical truth for SbatLevel is tracked here: https://github.com/rhboot/shim/blob/main/SbatLevel_Variable.txt

However as part of addressing this issue, I very much want to make that a single (probably sub) repo that will drive building the various pieces.

@hughsie
Copy link

hughsie commented Apr 29, 2024

I don't think that document qualifies as canonical truth :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants