diff --git a/doc/develop.rst b/doc/develop.rst index b233cde32..2b19faac3 100644 --- a/doc/develop.rst +++ b/doc/develop.rst @@ -72,6 +72,7 @@ Enable ACRN Features tutorials/setup_openstack_libvirt tutorials/acrn_on_qemu tutorials/using_grub + tutorials/acrn-secure-boot-with-grub tutorials/pre-launched-rt tutorials/enable_ivshmem diff --git a/doc/tutorials/acrn-secure-boot-with-grub.rst b/doc/tutorials/acrn-secure-boot-with-grub.rst new file mode 100644 index 000000000..3fbe82cff --- /dev/null +++ b/doc/tutorials/acrn-secure-boot-with-grub.rst @@ -0,0 +1,259 @@ +.. _how-to-enable-acrn-secure-boot-with-grub: + +Enable ACRN Secure Boot with GRUB +################################# + +This document shows how to enable ACRN secure boot with GRUB including: + +- ACRN Secure Boot Sequence +- Generate GPG Key +- Setup Standalone GRUB EFI Binary +- Enable UEFI Secure Boot + +**Validation Environment:** + +- Hardware Platform: TGL-I7, Supported hardware described in + :ref:`hardware`. +- ACRN Scenario: Industry +- Service VM: Yocto & Ubuntu +- GRUB: 2.04 + +.. note:: + Note that GRUB may stop booting in case of problems, make sure you + know how to recover a bootloader on your platform. + +ACRN Secure Boot Sequence +************************* + +ACRN can be booted by Multiboot compatible bootloader, following diagram +illustrates the boot sequence of ACRN with GRUB: + +.. image:: images/acrn_secureboot_flow.png + :align: center + :width: 800px + + +For details on enabling GRUB on ACRN, see :ref:`using_grub`. + +From a secureboot point of view: + +- UEFI firmware verifies shim/GRUB +- GRUB verifies ACRN, Service VM kernel, and pre-launched User VM kernel +- Service VM OS kernel verifies the Device Model (``acrn-dm``) and User + VM OVMF bootloader (with the help of ``acrn-dm``) +- User VM virtual bootloader (e.g. OVMF) starts the guest side verified boot process + +This document shows you how to enable GRUB to +verify ACRN binaries such ``acrn.bin``, Service VM kernel (``bzImage``), and +if present, a pre-launched User VM kernel image. + +.. rst-class:: numbered-step + +Generate GPG Key +**************** + +GRUB supports loading GPG signed files only if digital signatures are +enabled. Here's an example of generating a GPG signing key:: + + mkdir --mode 0700 keys + gpg --homedir keys --gen-key + gpg --homedir keys --export > boot.key + +The :command:`gpg --gen-key` generates a public and private key pair. +The private key is used to sign GRUB configuration files and ACRN +binaries. The public key will be embedded in GRUB and is used to verify +GRUB configuration files or binaries GRUB tries to load. + +.. rst-class:: numbered-step + +Setup Standalone GRUB EFI Binary +******************************** + +Prepare Initial GRUB Configuration grub.init.cfg +================================================ + +Create file ``grub.init.cfg`` to store the following minimal GRUB +configuration. The environment variable ``check_signatures=enforce`` +tells GRUB to enable digital signatures:: + + set check_signatures=enforce + export check_signatures + + search --no-floppy --fs-uuid --set=root ESP_UUID + configfile /grub.cfg + echo /grub.cfg did not boot the system, rebooting in 10 seconds. + sleep 10 + reboot + +Replace the ESP_UUID with the UUID of your EFI system partition (found +by running the :command:`lsblk -f`. In the example output below, +the UUID is ``24FC-BE7A``: + +.. code-block:: console + :emphasize-lines: 2 + + sda + ├─sda1 vfat ESP 24FC-BE7A /boot/efi + ├─sda2 vfat OS 7015-557F + ├─sda3 ext4 UBUNTU e8640994-b2a3-45ad-9b72-e68960fb22f0 / + └─sda4 swap 262d1113-64be-4910-a700-670b9d2277cc [SWAP] + + +Enable Authentication in GRUB +============================= + +With authentication enabled, a user/password is required to restrict +access to the GRUB shell, where arbitrary commands could be run. +A typical GRUB configuration fragment (added to ``grub.init.cfg``) might +look like this:: + + set superusers="root" + export superusers + password_pbkdf2 root GRUB_PASSWORD_HASH + +Replace the ``GRUB_PASSWORD_HASH`` with the result of the :command:`grub-mkpasswd-pbkdf2` +with your custom passphrase. + +Use this command to sign the :file:`grub.init.cfg` file with your private +GPG key and create the :file:`grub.init.cfg.sig`:: + + gpg --homedir keys --detach-sign grub.init.cfg + + +Create Standalone GRUB EFI Binary +================================= + +Use the ``grub-mkstandalone`` tool to create a standalone GRUB EFI binary +file with the buit-in modules and the signed ``grub.init.cfg`` file. +The ``--pubkey`` option adds a GPG public key that will be used for +verification. The public key ``boot.key`` is no longer required. + +.. note:: + You should make a backup copy of your current GRUB image + (:file:`grubx64.efi`) before replacing it with the new signed GRUB image. + This would allow you to restore GRUB in case of errors updating it. + +Here's an example sequence to do this build:: + + #!/bin/bash + # + + TARGET_EFI='path/to/grubx64.efi' + + # GRUB doesn't allow loading new modules from disk when secure boot is in + # effect, therefore pre-load the required modules. + + MODULES="all_video archelp boot bufio configfile crypto echo efi_gop efi_uga ext2 extcmd \ + fat font fshelp gcry_dsa gcry_rsa gcry_sha1 gcry_sha512 gettext gfxterm linux linuxefi ls \ + memdisk minicmd mmap mpi normal part_gpt part_msdos password_pbkdf2 pbkdf2 reboot relocator \ + search search_fs_file search_fs_uuid search_label sleep tar terminal verifiers video_fb" + + grub-mkstandalone \ + --directory /usr/lib/grub/x86_64-efi \ + --format x86_64-efi \ + --modules "$MODULES" \ + --pubkey ./boot.key \ + --output ./grubx64.efi \ + "boot/grub/grub.cfg=./grub.init.cfg" \ + "boot/grub/grub.cfg.sig=./grub.init.cfg.sig" + + echo "writing signed grub.efi to '$TARGET_EFI'" + sudo cp ./grubx64.efi "$TARGET_EFI" + + +.. rst-class:: numbered-step + +Prepare grub.cfg +**************** + +Define the menu entry for your system in a new GRUB configuration :file:`grub.cfg`. +For example:: + + # @/boot/efi/grub.cfg for grub secure boot + set timeout_style=menu + set timeout=5 + set gfxmode=auto + set gfxpayload=keep + terminal_output gfxterm + + menuentry "ACRN Multiboot Ubuntu Service VM" --users "" --id ubuntu-service-vm { + + search --no-floppy --fs-uuid --set 3df12ea1-ef12-426b-be98-774665c7483a + + echo 'loading ACRN...' + multiboot2 /boot/acrn/acrn.bin root=PARTUUID="c8ee7d92-8935-4e86-9e12-05dbeb412ad6" + module2 /boot/bzImage Linux_bzImage + } + +Use the output of the :command:`blkid` to find the right values for the +UUID (``--set``) and PARTUUID (``root=PARTUUID=`` parameter) of the root +partition (e.g. `/dev/nvme0n1p2`) according to your your hardware. + +Copy this new :file:`grub.cfg` to your ESP (e.g. `/boot/efi/EFI/`). + + +.. rst-class:: numbered-step + +Sign grub.cfg and ACRN Binaries +******************************* + +The :file:`grub.cfg` and all ACRN binaries that will be loaded by GRUB +**must** be signed with the same GPG key. + +Here's sequence example of signing the individual binaries:: + + gpg --homedir keys --detach-sign path/to/grub.cfg + gpg --homedir keys --detach-sign path/to/acrn.bin + gpg --homedir keys --detach-sign path/to/sos_kernel/bzImage + +Now, you can reboot and the system will boot with the signed GRUB EFI binary. +GRUB will refuse to boot if any files it attempts to load have been tampered +with. + + +.. rst-class:: numbered-step + +Enable UEFI Secure Boot +*********************** + +Creating UEFI Secure Boot Key +============================= + +-Generate your own keys for Secure Boot:: + + openssl req -new -x509 -newkey rsa:2048 -subj "/CN=PK/" -keyout PK.key -out PK.crt -days 7300 -nodes -sha256 + openssl req -new -x509 -newkey rsa:2048 -subj "/CN=KEK/" -keyout KEK.key -out KEK.crt -days 7300 -nodes -sha256 + openssl req -new -x509 -newkey rsa:2048 -subj "/CN=db/" -keyout db.key -out db.crt -days 7300 -nodes -sha256 + +-Convert ``*.crt`` keys to the ESL format understood for UEFI:: + + cert-to-efi-sig-list PK.crt PK.esl + cert-to-efi-sig-list KEK.crt KEK.esl + cert-to-efi-sig-list db.crt db.esl + +-Sign ESL files:: + + sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth + sign-efi-sig-list -k PK.key -c PK.crt KEK KEK.esl KEK.auth + sign-efi-sig-list -k KEK.key -c KEK.crt db db.esl db.auth + +The keys to be enrolled in UEFI firmware: :file:`PK.der`, :file:`KEK.der`, :file:`db.der`. +The keys to sign bootloader image: :file:`grubx64.efi`, :file:`db.key` , :file:`db.crt`. + +Sign GRUB Image With ``db`` Key +================================ + + sbsign --key db.key --cert db.crt path/to/grubx64.efi + +:file:`grubx64.efi.signed` will be created, it will be your bootloader. + +Enroll UEFI Keys To UEFI Firmware +================================= + +Enroll ``PK`` (:file:`PK.der`), ``KEK`` (:file:`KEK.der`) and ``db`` +(:file:`db.der`) in Secure Boot Configuration UI, which depends on your +platform UEFI firmware. In UEFI configuration menu UI, follow the steps +in :ref:`this section ` that shows how to enroll UEFI +keys, using your own key files. From now on, only EFI binaries +signed with any ``db`` key (:file:`grubx64.efi.signed` in this case) can +be loaded by UEFI firmware. diff --git a/doc/tutorials/images/acrn_secureboot_flow.png b/doc/tutorials/images/acrn_secureboot_flow.png new file mode 100644 index 000000000..0a9183ef2 Binary files /dev/null and b/doc/tutorials/images/acrn_secureboot_flow.png differ diff --git a/doc/tutorials/waag-secure-boot.rst b/doc/tutorials/waag-secure-boot.rst index 6c4aed136..cdfe181f8 100644 --- a/doc/tutorials/waag-secure-boot.rst +++ b/doc/tutorials/waag-secure-boot.rst @@ -473,6 +473,8 @@ Notes: - Make sure your GCC is 5.X. GCC 6 and above is NOT supported. +.. _qemu_inject_boot_keys: + Use QEMU to inject secure boot keys into OVMF *********************************************