1.. _how-to-enable-acrn-secure-boot-with-grub:
2
3Enable ACRN Secure Boot With GRUB
4#################################
5
6This document shows how to enable ACRN secure boot with GRUB including:
7
8-  `ACRN Secure Boot Sequence`_
9-  `Generate GPG Key`_
10-  `Setup Standalone GRUB EFI Binary`_
11-  `Enable UEFI Secure Boot`_
12
13**Validation Environment:**
14
15- Hardware Platform: Tiger Lake, supported hardware described in
16  :ref:`hardware`.
17- ACRN Scenario: Shared
18- Service VM: Yocto & Ubuntu
19- GRUB: 2.04
20
21.. note::
22   Note that GRUB may stop booting in case of problems, make sure you
23   know how to recover a bootloader on your platform.
24
25ACRN Secure Boot Sequence
26*************************
27
28ACRN can be booted by a multiboot compatible bootloader. The following diagram
29illustrates the boot sequence of ACRN with GRUB:
30
31.. image:: images/acrn_secureboot_flow.png
32   :align: center
33   :width: 800px
34
35
36For details on enabling GRUB on ACRN, see :ref:`using_grub`.
37
38From a secure boot point of view:
39
40- UEFI firmware verifies shim/GRUB
41- GRUB verifies ACRN, Service VM kernel, and pre-launched User VM kernel
42- Service VM OS kernel verifies the Device Model (``acrn-dm``) and User
43  VM OVMF bootloader (with the help of ``acrn-dm``)
44- User VM virtual bootloader (e.g., OVMF) starts the guest side verified boot process
45
46This document shows you how to enable GRUB to
47verify ACRN binaries such as ``acrn.bin``, Service VM kernel (``bzImage``), and
48if present, a pre-launched User VM kernel image.
49
50.. rst-class:: numbered-step
51
52Generate GPG Key
53****************
54
55GRUB supports loading GPG signed files only if digital signatures are
56enabled. Here's an example of generating a GPG signing key::
57
58  mkdir --mode 0700 keys
59  gpg --homedir keys  --gen-key
60  gpg --homedir keys --export > boot.key
61
62The :command:`gpg --gen-key` generates a public and private key pair.
63The private key is used to sign GRUB configuration files and ACRN
64binaries. The public key will be embedded in GRUB and is used to verify
65GRUB configuration files or binaries GRUB tries to load.
66
67.. rst-class:: numbered-step
68
69Setup Standalone GRUB EFI Binary
70********************************
71
72Prepare Initial GRUB Configuration grub.init.cfg
73================================================
74
75Create file ``grub.init.cfg`` to store the following minimal GRUB
76configuration.  The environment variable ``check_signatures=enforce``
77tells GRUB to enable digital signatures::
78
79    set check_signatures=enforce
80    export check_signatures
81
82    search --no-floppy --fs-uuid --set=root ESP_UUID
83    configfile /grub.cfg
84    echo /grub.cfg did not boot the system, rebooting in 10 seconds.
85    sleep 10
86    reboot
87
88Replace the ESP_UUID with the UUID of your EFI system partition (found
89by running the :command:`lsblk -f`.  In the example output below,
90the UUID is ``24FC-BE7A``:
91
92.. code-block:: console
93    :emphasize-lines: 2
94
95    sda
96    ├─sda1 vfat   ESP    24FC-BE7A                            /boot/efi
97    ├─sda2 vfat   OS     7015-557F
98    ├─sda3 ext4   UBUNTU e8640994-b2a3-45ad-9b72-e68960fb22f0 /
99    └─sda4 swap          262d1113-64be-4910-a700-670b9d2277cc [SWAP]
100
101
102Enable Authentication in GRUB
103=============================
104
105With authentication enabled, a user/password is required to restrict
106access to the GRUB shell, where arbitrary commands could be run.
107A typical GRUB configuration fragment (added to ``grub.init.cfg``) might
108look like this::
109
110    set superusers="root"
111    export superusers
112    password_pbkdf2 root GRUB_PASSWORD_HASH
113
114Replace the ``GRUB_PASSWORD_HASH`` with the result of the :command:`grub-mkpasswd-pbkdf2`
115with your custom passphrase.
116
117Use this command to sign the :file:`grub.init.cfg` file with your private
118GPG key and create the :file:`grub.init.cfg.sig`::
119
120    gpg --homedir keys --detach-sign grub.init.cfg
121
122
123Create Standalone GRUB EFI Binary
124=================================
125
126Use the ``grub-mkstandalone`` tool to create a standalone GRUB EFI binary
127file with the buit-in modules and the signed ``grub.init.cfg`` file.
128The ``--pubkey`` option adds a GPG public key that will be used for
129verification. The public key ``boot.key`` is no longer required.
130
131.. note::
132    You should make a backup copy of your current GRUB image
133    (:file:`grubx64.efi`) before replacing it with the new signed GRUB image.
134    This would allow you to restore GRUB in case of errors updating it.
135
136Here's an example sequence to do this build::
137
138    #!/bin/bash
139    #
140
141    TARGET_EFI='path/to/grubx64.efi'
142
143    # GRUB doesn't allow loading new modules from disk when secure boot is in
144    # effect, therefore pre-load the required modules.
145
146    MODULES="all_video archelp boot bufio configfile crypto echo efi_gop efi_uga ext2 extcmd  \
147     fat font fshelp gcry_dsa gcry_rsa gcry_sha1 gcry_sha512 gettext gfxterm linux ls \
148     memdisk minicmd mmap mpi normal part_gpt part_msdos password_pbkdf2 pbkdf2 reboot relocator \
149     search search_fs_file search_fs_uuid search_label sleep tar terminal verifiers video_fb"
150
151    grub-mkstandalone \
152     --directory /usr/lib/grub/x86_64-efi \
153     --format x86_64-efi \
154     --modules "$MODULES" \
155     --pubkey ./boot.key \
156     --output ./grubx64.efi  \
157     "boot/grub/grub.cfg=./grub.init.cfg" \
158     "boot/grub/grub.cfg.sig=./grub.init.cfg.sig"
159
160    echo "writing signed grub.efi to '$TARGET_EFI'"
161    sudo cp ./grubx64.efi "$TARGET_EFI"
162
163
164Prepare grub.cfg
165================
166
167Define the menu entry for your system in a new GRUB configuration :file:`grub.cfg`.
168For example::
169
170    # @/boot/efi/grub.cfg for grub secure boot
171    set timeout_style=menu
172    set timeout=5
173    set gfxmode=auto
174    set gfxpayload=keep
175    terminal_output gfxterm
176
177    menuentry "ACRN Multiboot Ubuntu Service VM" --users "" --id ubuntu-service-vm {
178
179    search --no-floppy --fs-uuid --set 3df12ea1-ef12-426b-be98-774665c7483a
180
181    echo 'loading ACRN...'
182    multiboot2 /boot/acrn/acrn.bin  root=PARTUUID="c8ee7d92-8935-4e86-9e12-05dbeb412ad6"
183    module2 /boot/bzImage Linux_bzImage
184    }
185
186Use the output of the :command:`blkid` to find the right values for the
187UUID (``--set``) and PARTUUID (``root=PARTUUID=`` parameter) of the root
188partition (e.g., ``/dev/nvme0n1p2``) according to your hardware.
189
190Copy this new :file:`grub.cfg` to your ESP (e.g., ``/boot/efi/EFI/``).
191
192
193Sign grub.cfg and ACRN Binaries
194===============================
195
196The :file:`grub.cfg` and all ACRN binaries that will be loaded by GRUB
197**must** be signed with the same GPG key.
198
199Here's a sequence example of signing the individual binaries::
200
201    gpg --homedir keys --detach-sign path/to/grub.cfg
202    gpg --homedir keys --detach-sign path/to/acrn.bin
203    gpg --homedir keys --detach-sign path/to/service_vm_kernel/bzImage
204
205Now, you can reboot and the system will boot with the signed GRUB EFI binary.
206GRUB will refuse to boot if any files it attempts to load have been tampered
207with.
208
209
210.. rst-class:: numbered-step
211
212Enable UEFI Secure Boot
213***********************
214
215Creating UEFI Secure Boot Key
216=============================
217
218- Generate your own keys for Secure Boot::
219
220    openssl req -new -x509 -newkey rsa:2048 -subj "/CN=PK/"  -keyout PK.key  -out PK.crt  -days 7300 -nodes -sha256
221    openssl req -new -x509 -newkey rsa:2048 -subj "/CN=KEK/" -keyout KEK.key -out KEK.crt -days 7300 -nodes -sha256
222    openssl req -new -x509 -newkey rsa:2048 -subj "/CN=db/"  -keyout db.key  -out db.crt  -days 7300 -nodes -sha256
223
224- Convert ``*.crt`` keys to the ESL format understood for UEFI::
225
226    cert-to-efi-sig-list PK.crt PK.esl
227    cert-to-efi-sig-list KEK.crt KEK.esl
228    cert-to-efi-sig-list db.crt db.esl
229
230- Sign ESL files::
231
232    sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth
233    sign-efi-sig-list -k PK.key -c PK.crt KEK KEK.esl KEK.auth
234    sign-efi-sig-list -k KEK.key -c KEK.crt db db.esl db.auth
235
236- Convert to DER format::
237
238    openssl x509 -outform DER -in PK.crt -out PK.der
239    openssl x509 -outform DER -in KEK.crt -out KEK.der
240    openssl x509 -outform DER -in db.crt -out db.der
241
242
243The keys to be enrolled in UEFI firmware: :file:`PK.der`, :file:`KEK.der`, :file:`db.der`.
244The keys to sign bootloader image: :file:`grubx64.efi`, :file:`db.key` , :file:`db.crt`.
245
246Sign GRUB Image With db Key
247===========================
248
249Command example::
250
251    sbsign --key db.key --cert db.crt path/to/grubx64.efi
252
253:file:`grubx64.efi.signed` will be created, it will be your bootloader.
254
255Enroll UEFI Keys to UEFI Firmware
256=================================
257
258Enroll ``PK`` (:file:`PK.der`), ``KEK`` (:file:`KEK.der`) and ``db``
259(:file:`db.der`) in Secure Boot Configuration UI, which depends on your
260platform UEFI firmware.  In UEFI configuration menu UI, follow the steps
261in :ref:`this section <qemu_inject_boot_keys>` that shows how to enroll UEFI
262keys, using your own key files.  From now on, only EFI binaries
263signed with any ``db`` key (:file:`grubx64.efi.signed` in this case) can
264be loaded by UEFI firmware.
265