Wiki - https://fedoraproject.org/wiki/Changes/Grub2LightForConfidentialComputing
Discussion thread -
https://discussion.fedoraproject.org/t/f45-change-proposal-grub-efi-for-confidential-computing-self-contained/193574
This is a proposed Change for Fedora Linux.
This document represents a proposed Change. As part of the Changes
process, proposals are publicly announced in order to receive
community feedback. This proposal will only be implemented if approved
by the Fedora Engineering Steering Committee.
== Summary ==
An independent separate incarnation (package) of the GRUB bootloader
for UEFI only that contains a minimal number of built-in modules, and
can quickly boot a Unified Kernel Image (UKI) using Bootloader
Specification (BLS) files. It will be built separately from the main
GRUB package, and does not replace it for general usage.
== Owner ==
* Name: [[User:lsandova| Leo Sandoval]] | lsandova@redhat.com
* Name: [[User:mlewando| Marta Lewandowska]] | mlewando@redhat.com
== Detailed Description ==
There is a need for a smaller, lighter version of the GRUB bootloader
on UEFI to support booting sealed bootable container images, such as
for Confidential Computing.
Since confidential VMs rely on remote attestation, TPM PCR values need
to be stable and predictable over long periods of time. Updating the
bootloader results in changes to PCRs, and should therefore be avoided
if possible.
Additionally, Unified Kernel Images (UKIs) have become the preferred
choice over the regular signed kernel because the whole payload is
bundled and signed for Secure Boot, thus removing the vulnerability of
the unsigned initramfs. They are used often in virtual environments,
for confidential computing, and by CoreOS.
Taken together, the ideal bootloader for these types of environments
should be small, light, and not get updated too often. The fewer
modules are built-in, the smaller the attack surface, and the less
frequent updates need to be. The resulting idea is to create a smaller
version of GRUB, the supported bootloader in most Linux environments,
for UEFI, which is built as a separate package from the main GRUB
build, contains only the modules that are absolutely necessary for
VMs, and natively supports UKI loading. This new package is not meant
to be a replacement for GRUB for general use; rather it's an
additional package for specific applications.
A separate rpm that is still a part of the grub2 build is already
available for [https://kojipkgs.fedoraproject.org//packages/grub2/2.12/60.fc45/x86_64/grub2-efi-x64-cc-2.12-60.fc45.x86_64.rpm
x86_64] and [https://kojipkgs.fedoraproject.org//packages/grub2/2.12/60.fc45/aarch64/grub2-efi-aa64-cc-2.12-60.fc45.aarch64.rpm
aarch64] in Fedora Rawhide for testing. It is signed for Secure Boot
with the GRUB key. In the future, it is expected to get its own Secure
Boot signing key.
Work is in progress to add support for this new build of GRUB in
bootupd to enable safe bootloader updates on bootable container
systems: https://github.com/coreos/bootupd/issues/1080
== Feedback ==
The original idea was to use systemd-boot for this application, but
this was rejected for a number of reasons:
* While the systemd team can support sd-boot in its present form, they
view any additional features as a no-go
* Although sd-boot is a light and trivial bootloader, it has not been
widely tested or fuzzed, like GRUB has been
* Long term maintenance of more than one bootloader would result in a
lack of parity and added technical debt
* Potential expansion to other architectures would necessitate a
compatible bootloader anyway.
The new lighter GRUB build is already being tested by CoreOS, and is
generally working as expected. Small changes are still being made, and
suggestions for changes are welcome.
== Benefit to Fedora ==
This change will create a minimal UEFI bootloader for virtual
environments that can further be tailored for use in those
environments. It will natively load UKIs, support Secure Boot, and be
a part of a robust and tested bootloader used in many Linux
environments.
== Scope ==
* Proposal owners: The bootloader engineering team needs to create a
new GRUB package, separate from the core package that includes all the
changes mentioned.
* Other developers: CoreOS, who will be the main users, at least in
the beginning, need to test, provide feedback, and perhaps change some
of their workflows as needed.
* Release engineering:
[https://forge.fedoraproject.org/releng/tickets/issues #Releng issue
number]
* Policies and guidelines: N/A (not needed for this Change)
* Trademark approval: N/A (not needed for this Change)
* Alignment with the Fedora Strategy:
== Upgrade/compatibility impact ==
This is a new package, independent of the normal all-purpose GRUB, so
unless a user installs it on purpose, there is no compatibility
impact.
== Early Testing (Optional) ==
This new package is designed specifically for VMs that run UEFI
firmware, so an x86_64 or aarch64 VM is the environment to use.
===Prepare the test environment:===
* Install or create one or more UKIs
** Install `kernel-uki-virt` and add a command line addon using
`ukify`, see instructions below
** Use `ukify` to create the UKI from scratch, see instructions below
* If booting with Secure Boot enabled, sign your add-on or UKI, and
enroll your public key in the MOK, see instructions below.<br> '''If
you will not sign your UKI/addon, don't forget to disable Secure
Boot.'''
* Create the `/boot/efi/loader/entries` directory
* Create BLS entries in that directory for each UKI. Specify the path
to the UKI using the `efi` keyword, as you normally would use `linux`
for the kernel. A minimal BLS file only needs to have a title and the
path to the UKI:
<pre>
# cat /boot/efi/loader/entries/7.0.10-200-UKI.fc45.x86_64.conf
title Fedora 45 UKI (7.0.10-200.fc45.x86_64)
efi /EFI/Linux/7.0.10-200.fc45.x86_64.efi
</pre>
=== (If you don't feel like doing all of that, you can boot regular
kernels instead): ===
Because this version of GRUB is intended for UKIs, it expects those
UKIs to be on the EFI system partition, but it can load a regular
kernel too, as long as it's in the correct place. If you copy a kernel
and its initrd from `/boot` to `/boot/efi/EFI/Linux` and that kernel's
BLS configuration file from `/boot/loader/entries` to
`/boot/efi/loader/entries` (and edit it to reflect the correct paths),
then it should simply boot as usual.
=== Test: ===
* Download the [https://kojipkgs.fedoraproject.org//packages/grub2/2.12/60.fc45/x86_64/grub2-efi-x64-cc-2.12-60.fc45.x86_64.rpm
grub2-efi-x64-cc rpm], unpack it, and replace your regular grub efi
with it:
<pre>
# cp ./usr/lib/efi/grub2/1\:2.12-60.fc45/EFI/fedora/cc/grubx64-cc.efi
/boot/efi/EFI/fedora/grubx64.efi
</pre>
* Reboot your machine
You should see the GRUB menu with entries for each of the UKIs that
you installed. If you press 'e' to edit an entry, you should see
something like `chainloader /path/to/UKI` and when you execute any of
the entries, they should successfully boot.
You can check the size of the efi, and see that it is smaller than the
normal grubx64.efi.
Use the `tpm2_pcrread` command between reboots of different UKIs to
see that the value of PCR8 does not change.
==== How to build your own UKI addon ====
The generic UKI that fedora ships has only `console=tty0
console=ttyS0` on its kernel command line. In order for it to actually
boot on your system, it needs more information, like the root
filesystem UUID, which you can see if you
`# cat /proc/cmdline`. Since the UKI already has the command line
bundled, you need to create a command line addon containing the
additional information. You can do this using the
[https://www.man7.org/linux/man-pages//man1/ukify.1.html ukify]
command. First get the generic UKI by installing `kernel-virt-uki` and
the command by installing `systemd-ukify`. Then something like this
should work:
<pre>
# ukify build \
-cmdline "$(cat /proc/cmdline | cut -d' ' -f2-6)" \
--output set_root.unsigned.addon.efi
</pre>
You then need to copy the addon to the UKI's extra.d directory in
`/boot/efi/EFI/Linux/` if you want to only apply it to a single UKI,
or create `/boot/efi/loader/addons/` and copy it there, if you want it
to work for all UKIs. (If you are planning to sign the addon, wait to
move it until after you have signed it.)
==== How to build your own UKI ====
You can build your own UKI using kernels and initrds that you already
have installed on your system once you have also installed
`systemd-ukify`. Building one for the running kernel using the
[https://www.man7.org/linux/man-pages//man1/ukify.1.html ukify]
command, looks like this:
<pre>
# ukify build \
--linux /usr/lib/modules/$(uname -r)/vmlinuz \
--initrd /boot/initramfs-$(uname -r).img \
--uname $(uname -r) \
--cmdline "$(cat /proc/cmdline | cut -d' ' -f2-6)" \
--output kernel-$(uname -r | rev | cut -d'.' -f3-6 | rev)-UKI.efi \
--profile "kernel $(uname -r | rev | cut -d'.' -f3-6 | rev) UKI
(Fedora $(cat /etc/os-release | grep VERSION_ID | sed -e
's/VERSION_ID=//g'))"
</pre>
You then need to copy the UKI to the correct directory. Typically this
is `/boot/efi/EFI/Linux/` but can be the directory of your choosing,
as long as you specify that in the UKI's BLS file. (If you are
planning to sign the UKI, wait to move it until after you have signed
it.)
==== How to sign for Secure Boot ====
It's actually possible to sign your UKI or addon during the ukify
build, but this more generic procedure can be used to sign any
artifact for Secure Boot.
Install `openssl` and `pesign` and generate your signing key:
<pre>
# openssl req -quiet -newkey rsa:4096 -nodes \
-keyout custom_db.key -new -x509 -sha256 -days 3650 \
-subj "/CN=UKI Signing key/" \
--outform DER -out custom_db.der
</pre>
In this case the key size is 4096 bit, uses
[https://en.wikipedia.org/wiki/RSA_cryptosystem RSA] for encryption,
and can be used for signing for 10 years.
Import the public key into the NSS database that `pesign` uses and
give it a nickname:
<pre>
# certutil -A -t ",," -d /etc/pki/pesign -n \
'My Secureboot Signer' -i custom_db.der
</pre>
Convert the public and private keys to PKCS12 format and import the
result to enable signing using `pesign`:
<pre>
# openssl pkcs12 -export -out custom_db.pfx \
-inkey custom_db.key -in custom_db.der
</pre>
<pre>
# pk12util -i custom_db.pfx \
-d/etc/pki/pesign -n 'My Secureboot Signer'
</pre>
Sign your UKI or addon with your private key:
<pre>
# pesign --certificate 'My Secureboot Signer' \
--in set_root.unsigned.addon.efi \
--out set_root.addon.efi --sign
</pre>
Move or copy the UKI or addon to the proper directory, see above.
Import your public key into the Machine Owner Key (MOK) database:
<pre>
# mokutil --import custom_db.der
</pre>
You will be asked to create a password. You need to reboot the machine
to complete the enrollment, and you will be asked for this password at
that time.
After rebooting, you can check that your key is actually in the MOK database:
<pre>
# mokutil --list-enrolled
</pre>
== Dependencies ==
N/A as this is a new package.
== Documentation ==
N/A (not a System Wide Change) or to be determined.
== Release Notes ==
To be determined.
--
Aoife Moloney
Fedora Operations Architect
Fedora Project
Matrix: @amoloney:fedora.im
IRC: amoloney
--
_______________________________________________
devel-announce mailing list -- devel-announce@lists.fedoraproject.org
To unsubscribe send an email to devel-announce-leave@lists.fedoraproject.org
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedoraproject.org/archives/list/devel-announce@lists.fedoraproject.org
Do not reply to spam, report it: https://forge.fedoraproject.org/infra/tickets/issues/new