diff mbox series

[v5,2/2] qemuarm64-secureboot: Enable UEFI Secure Boot

Message ID 20240904224349.108885-3-javier.tia@linaro.org
State New
Headers show
Series qemuarm64-secureboot: Add UEFI Secure Boot | expand

Commit Message

Javier Tia Sept. 4, 2024, 10:43 p.m. UTC
Encapsulate all UEFI Secure Boot required settings in one Kas
configuration file.

Introduce SBSIGN_KEYS_DIR variable where UEFI keys will be generated
to sign UEFI binaries. 

Introduce uefi-secureboot machine feature, which is being used to
conditionally set the proper UEFI settings in recipes.

Replace Grub bootloader with systemd-boot, which it makes easier to
enable Secure Boot.

Advantages using systemd as Init Manager:

- Extending secure boot to userspace is a lot easier with systemd than
with sysvinit where custom scripts will need to be written for all use
cases.

- systemd supports dm-verity and TPM devices for encryption usecases out
of the box. Enabling them is a lot easier than writing custom scripts
for sysvinit.

- systemd also supports EUFI signing the UKI binaries which merge kernel,
command line and initrd which helps in bringing secure boot towards
rootfs.

- systemd offers a modular structure with unit files that are more
predictable and easier to manage than the complex and varied scripts
used by SysVinit. This modularity allows for better control and
customization of the boot process, which is beneficial in Secure Boot
environments.

Add one test to verify Secure Boot using OE Testing infraestructure:

$ kas build ci/qemuarm64-secureboot.yml:ci/testimage.yml
...
RESULTS - uefi_secureboot.UEFI_SB_TestSuite.test_uefi_secureboot: PASSED (0.62s)
...
SUMMARY:
core-image-base () - Ran 73 tests in 28.281s
core-image-base - OK - All required tests passed (successes=19, skipped=54, failures=0, errors=0)

Signed-off-by: Javier Tia <javier.tia@linaro.org>
---
 ci/qemuarm64-secureboot.yml                   |  1 +
 ci/uefi-secureboot.yml                        | 34 +++++++++++++++++++
 .../lib/oeqa/runtime/cases/uefi_secureboot.py | 29 ++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 ci/uefi-secureboot.yml
 create mode 100644 meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py

Comments

Jon Mason Sept. 18, 2024, 2:53 p.m. UTC | #1
On Wed, Sep 04, 2024 at 04:43:49PM -0600, Javier Tia wrote:
> Encapsulate all UEFI Secure Boot required settings in one Kas
> configuration file.
> 
> Introduce SBSIGN_KEYS_DIR variable where UEFI keys will be generated
> to sign UEFI binaries.�
> 
> Introduce uefi-secureboot machine feature, which is being used to
> conditionally set the proper UEFI settings in recipes.
> 
> Replace Grub bootloader with systemd-boot, which it makes easier to
> enable Secure Boot.
> 
> Advantages using systemd as Init Manager:
> 
> - Extending secure boot to userspace is a lot easier with systemd than
> with sysvinit where custom scripts will need to be written for all use
> cases.
> 
> - systemd supports dm-verity and TPM devices for encryption usecases out
> of the box. Enabling them is a lot easier than writing custom scripts
> for sysvinit.
> 
> - systemd also supports EUFI signing the UKI binaries which merge kernel,
> command line and initrd which helps in bringing secure boot towards
> rootfs.
> 
> - systemd offers a modular structure with unit files that are more
> predictable and easier to manage than the complex and varied scripts
> used by SysVinit. This modularity allows for better control and
> customization of the boot process, which is beneficial in Secure Boot
> environments.
> 
> Add one test to verify Secure Boot using OE Testing infraestructure:
> 
> $ kas build ci/qemuarm64-secureboot.yml:ci/testimage.yml
> ...
> RESULTS - uefi_secureboot.UEFI_SB_TestSuite.test_uefi_secureboot: PASSED (0.62s)
> ...
> SUMMARY:
> core-image-base () - Ran 73 tests in 28.281s
> core-image-base - OK - All required tests passed (successes=19, skipped=54, failures=0, errors=0)
> 
> Signed-off-by: Javier Tia <javier.tia@linaro.org>
> ---
>  ci/qemuarm64-secureboot.yml                   |  1 +
>  ci/uefi-secureboot.yml                        | 34 +++++++++++++++++++
>  .../lib/oeqa/runtime/cases/uefi_secureboot.py | 29 ++++++++++++++++
>  3 files changed, 64 insertions(+)
>  create mode 100644 ci/uefi-secureboot.yml
>  create mode 100644 meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
> 
> diff --git a/ci/qemuarm64-secureboot.yml b/ci/qemuarm64-secureboot.yml
> index b26941e0..7866adbb 100644
> --- a/ci/qemuarm64-secureboot.yml
> +++ b/ci/qemuarm64-secureboot.yml
> @@ -4,6 +4,7 @@ header:
>    version: 14
>    includes:
>      - ci/base.yml
> +    - ci/uefi-secureboot.yml

I don't think we want this.  What I think we want is to keep this file
as-is, then use the uefi-secureboot.yml as an add on.  Using the kas
line above, it would be:
$ kas build ci/qemuarm64-secureboot.yml:ci/uefi-secureboot.yml:ci/testimage.yml

Then, we would want to modify .gitlab-ci.yml with something like:

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7568c25e9d13..075e523c7d29 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -117,6 +117,7 @@ update-repos:
 #  TCLIBC: [glibc, musl]
 #  FIRMWARE: [u-boot, edk2]
 #  TS: [none, trusted-services]
+#  UEFISB: [none, uefi-secureboot]
 #  VIRT: [none, xen]
 #  TESTING: testimage
 #  SECUREDEBUG: [none, secure-debug]
@@ -274,6 +275,7 @@ qemuarm64-secureboot:
         TOOLCHAINS: [gcc, clang]
         TCLIBC: [glibc, musl]
         TS: [none, qemuarm64-secureboot-ts]
+        UEFISB: [none, uefi-secureboot]
         TESTING: testimage
       - KERNEL: linux-yocto-dev
         TESTING: testimage

When this is added, it'll be built and checked with our Gitlab CI.
Honestly, I think this is the only thing keeping it from being
included (unless Ross has additional feedback).

Thanks,
Jon

>  
>  machine: qemuarm64-secureboot
>  
> diff --git a/ci/uefi-secureboot.yml b/ci/uefi-secureboot.yml
> new file mode 100644
> index 00000000..d65beed3
> --- /dev/null
> +++ b/ci/uefi-secureboot.yml
> @@ -0,0 +1,34 @@
> +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json
> +
> +header:
> +  version: 14
> +  includes:
> +    - ci/meta-openembedded.yml
> +    - ci/meta-secure-core.yml
> +
> +local_conf_header:
> +  uefi_secureboot: |
> +    SBSIGN_KEYS_DIR = "${TOPDIR}/sbkeys"
> +    BB_ENV_PASSTHROUGH_ADDITIONS = "SBSIGN_KEYS_DIR"
> +
> +    # Detected by passing kernel parameter
> +    QB_KERNEL_ROOT = ""
> +
> +    # kernel is in the image, should not be loaded separately
> +    QB_DEFAULT_KERNEL = "none"
> +
> +    WKS_FILE = "efi-disk-no-swap.wks.in"
> +    KERNEL_IMAGETYPE = "Image"
> +
> +    MACHINE_FEATURES:append = " efi uefi-secureboot"
> +
> +    EFI_PROVIDER = "systemd-boot"
> +
> +    # Use systemd as the init system
> +    INIT_MANAGER = "systemd"
> +    DISTRO_FEATURES:append = " systemd"
> +    DISTRO_FEATURES_NATIVE:append = " systemd"
> +
> +    IMAGE_INSTALL:append = " systemd systemd-boot util-linux coreutils efivar"
> +
> +    TEST_SUITES:append = " uefi_secureboot"
> \ No newline at end of file
> diff --git a/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py b/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
> new file mode 100644
> index 00000000..9e47ea8d
> --- /dev/null
> +++ b/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
> @@ -0,0 +1,29 @@
> +#
> +# SPDX-License-Identifier: MIT
> +#
> +
> +from oeqa.runtime.case import OERuntimeTestCase
> +from oeqa.core.decorator.oetimeout import OETimeout
> +
> +
> +class UEFI_SB_TestSuite(OERuntimeTestCase):
> +    """
> +    Validate Secure Boot is Enabled
> +    """
> +
> +    @OETimeout(1300)
> +    def test_uefi_secureboot(self):
> +        # Validate Secure Boot is enabled by checking
> +        # 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot.
> +        # The GUID '8be4df61-93ca-11d2-aa0d-00e098032b8c' is a well-known
> +        # identifier for the Secure Boot UEFI variable. By checking the value of
> +        # this variable, specifically
> +        # '8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot', we can determine
> +        # whether Secure Boot is enabled or not. This variable is set by the
> +        # UEFI firmware to indicate the current Secure Boot state. If the
> +        # variable is set to a value of '0x1' (or '1'), it indicates that Secure
> +        # Boot is enabled. If the variable is set to a value of '0x0' (or '0'),
> +        # it indicates that Secure Boot is disabled.
> +        cmd = "efivar -d -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot"
> +        status, output = self.target.run(cmd, timeout=120)
> +        self.assertEqual(output, "1", msg="\n".join([cmd, output]))
> -- 
> 2.46.0
> 
>
Javier Tia Sept. 18, 2024, 11:18 p.m. UTC | #2
Hi,

On 9/18/24 8:53 AM, Jon Mason wrote:
> On Wed, Sep 04, 2024 at 04:43:49PM -0600, Javier Tia wrote:
>> Encapsulate all UEFI Secure Boot required settings in one Kas
>> configuration file.
>>
>> Introduce SBSIGN_KEYS_DIR variable where UEFI keys will be generated
>> to sign UEFI binaries.
>>
>> Introduce uefi-secureboot machine feature, which is being used to
>> conditionally set the proper UEFI settings in recipes.
>>
>> Replace Grub bootloader with systemd-boot, which it makes easier to
>> enable Secure Boot.
>>
>> Advantages using systemd as Init Manager:
>>
>> - Extending secure boot to userspace is a lot easier with systemd than
>> with sysvinit where custom scripts will need to be written for all use
>> cases.
>>
>> - systemd supports dm-verity and TPM devices for encryption usecases out
>> of the box. Enabling them is a lot easier than writing custom scripts
>> for sysvinit.
>>
>> - systemd also supports EUFI signing the UKI binaries which merge kernel,
>> command line and initrd which helps in bringing secure boot towards
>> rootfs.
>>
>> - systemd offers a modular structure with unit files that are more
>> predictable and easier to manage than the complex and varied scripts
>> used by SysVinit. This modularity allows for better control and
>> customization of the boot process, which is beneficial in Secure Boot
>> environments.
>>
>> Add one test to verify Secure Boot using OE Testing infraestructure:
>>
>> $ kas build ci/qemuarm64-secureboot.yml:ci/testimage.yml
>> ...
>> RESULTS - uefi_secureboot.UEFI_SB_TestSuite.test_uefi_secureboot: PASSED (0.62s)
>> ...
>> SUMMARY:
>> core-image-base () - Ran 73 tests in 28.281s
>> core-image-base - OK - All required tests passed (successes=19, skipped=54, failures=0, errors=0)
>>
>> Signed-off-by: Javier Tia <javier.tia@linaro.org>
>> ---
>>   ci/qemuarm64-secureboot.yml                   |  1 +
>>   ci/uefi-secureboot.yml                        | 34 +++++++++++++++++++
>>   .../lib/oeqa/runtime/cases/uefi_secureboot.py | 29 ++++++++++++++++
>>   3 files changed, 64 insertions(+)
>>   create mode 100644 ci/uefi-secureboot.yml
>>   create mode 100644 meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
>>
>> diff --git a/ci/qemuarm64-secureboot.yml b/ci/qemuarm64-secureboot.yml
>> index b26941e0..7866adbb 100644
>> --- a/ci/qemuarm64-secureboot.yml
>> +++ b/ci/qemuarm64-secureboot.yml
>> @@ -4,6 +4,7 @@ header:
>>     version: 14
>>     includes:
>>       - ci/base.yml
>> +    - ci/uefi-secureboot.yml
>
> I don't think we want this.  What I think we want is to keep this file
> as-is, then use the uefi-secureboot.yml as an add on.  Using the kas
> line above, it would be:
> $ kas build ci/qemuarm64-secureboot.yml:ci/uefi-secureboot.yml:ci/testimage.yml

After reading your first comment in previous email, I initially understood using uefi-secureboot as an add-on. However, when I added the entire command, I thought it would become redundant because the qemuarm64-secureboot.yml file already contains the word "secureboot." In this case, I suppose the meaning of "secureboot" is unique to optee.

I will follow your comment to call uefi-secureboot.yml an add-on from kas tool in the next patch series.

> Then, we would want to modify .gitlab-ci.yml with something like:
>
> diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
> index 7568c25e9d13..075e523c7d29 100644
> --- a/.gitlab-ci.yml
> +++ b/.gitlab-ci.yml
> @@ -117,6 +117,7 @@ update-repos:
>   #  TCLIBC: [glibc, musl]
>   #  FIRMWARE: [u-boot, edk2]
>   #  TS: [none, trusted-services]
> +#  UEFISB: [none, uefi-secureboot]
>   #  VIRT: [none, xen]
>   #  TESTING: testimage
>   #  SECUREDEBUG: [none, secure-debug]
> @@ -274,6 +275,7 @@ qemuarm64-secureboot:
>           TOOLCHAINS: [gcc, clang]
>           TCLIBC: [glibc, musl]
>           TS: [none, qemuarm64-secureboot-ts]
> +        UEFISB: [none, uefi-secureboot]
>           TESTING: testimage
>         - KERNEL: linux-yocto-dev
>           TESTING: testimage
>
> When this is added, it'll be built and checked with our Gitlab CI.
> Honestly, I think this is the only thing keeping it from being
> included (unless Ross has additional feedback).
>
> Thanks,
> Jon
>
>>
>>   machine: qemuarm64-secureboot
>>
>> diff --git a/ci/uefi-secureboot.yml b/ci/uefi-secureboot.yml
>> new file mode 100644
>> index 00000000..d65beed3
>> --- /dev/null
>> +++ b/ci/uefi-secureboot.yml
>> @@ -0,0 +1,34 @@
>> +# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json
>> +
>> +header:
>> +  version: 14
>> +  includes:
>> +    - ci/meta-openembedded.yml
>> +    - ci/meta-secure-core.yml
>> +
>> +local_conf_header:
>> +  uefi_secureboot: |
>> +    SBSIGN_KEYS_DIR = "${TOPDIR}/sbkeys"
>> +    BB_ENV_PASSTHROUGH_ADDITIONS = "SBSIGN_KEYS_DIR"
>> +
>> +    # Detected by passing kernel parameter
>> +    QB_KERNEL_ROOT = ""
>> +
>> +    # kernel is in the image, should not be loaded separately
>> +    QB_DEFAULT_KERNEL = "none"
>> +
>> +    WKS_FILE = "efi-disk-no-swap.wks.in"
>> +    KERNEL_IMAGETYPE = "Image"
>> +
>> +    MACHINE_FEATURES:append = " efi uefi-secureboot"
>> +
>> +    EFI_PROVIDER = "systemd-boot"
>> +
>> +    # Use systemd as the init system
>> +    INIT_MANAGER = "systemd"
>> +    DISTRO_FEATURES:append = " systemd"
>> +    DISTRO_FEATURES_NATIVE:append = " systemd"
>> +
>> +    IMAGE_INSTALL:append = " systemd systemd-boot util-linux coreutils efivar"
>> +
>> +    TEST_SUITES:append = " uefi_secureboot"
>> \ No newline at end of file
>> diff --git a/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py b/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
>> new file mode 100644
>> index 00000000..9e47ea8d
>> --- /dev/null
>> +++ b/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
>> @@ -0,0 +1,29 @@
>> +#
>> +# SPDX-License-Identifier: MIT
>> +#
>> +
>> +from oeqa.runtime.case import OERuntimeTestCase
>> +from oeqa.core.decorator.oetimeout import OETimeout
>> +
>> +
>> +class UEFI_SB_TestSuite(OERuntimeTestCase):
>> +    """
>> +    Validate Secure Boot is Enabled
>> +    """
>> +
>> +    @OETimeout(1300)
>> +    def test_uefi_secureboot(self):
>> +        # Validate Secure Boot is enabled by checking
>> +        # 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot.
>> +        # The GUID '8be4df61-93ca-11d2-aa0d-00e098032b8c' is a well-known
>> +        # identifier for the Secure Boot UEFI variable. By checking the value of
>> +        # this variable, specifically
>> +        # '8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot', we can determine
>> +        # whether Secure Boot is enabled or not. This variable is set by the
>> +        # UEFI firmware to indicate the current Secure Boot state. If the
>> +        # variable is set to a value of '0x1' (or '1'), it indicates that Secure
>> +        # Boot is enabled. If the variable is set to a value of '0x0' (or '0'),
>> +        # it indicates that Secure Boot is disabled.
>> +        cmd = "efivar -d -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot"
>> +        status, output = self.target.run(cmd, timeout=120)
>> +        self.assertEqual(output, "1", msg="\n".join([cmd, output]))
>> --
>> 2.46.0

» Javier Tia 
diff mbox series

Patch

diff --git a/ci/qemuarm64-secureboot.yml b/ci/qemuarm64-secureboot.yml
index b26941e0..7866adbb 100644
--- a/ci/qemuarm64-secureboot.yml
+++ b/ci/qemuarm64-secureboot.yml
@@ -4,6 +4,7 @@  header:
   version: 14
   includes:
     - ci/base.yml
+    - ci/uefi-secureboot.yml
 
 machine: qemuarm64-secureboot
 
diff --git a/ci/uefi-secureboot.yml b/ci/uefi-secureboot.yml
new file mode 100644
index 00000000..d65beed3
--- /dev/null
+++ b/ci/uefi-secureboot.yml
@@ -0,0 +1,34 @@ 
+# yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json
+
+header:
+  version: 14
+  includes:
+    - ci/meta-openembedded.yml
+    - ci/meta-secure-core.yml
+
+local_conf_header:
+  uefi_secureboot: |
+    SBSIGN_KEYS_DIR = "${TOPDIR}/sbkeys"
+    BB_ENV_PASSTHROUGH_ADDITIONS = "SBSIGN_KEYS_DIR"
+
+    # Detected by passing kernel parameter
+    QB_KERNEL_ROOT = ""
+
+    # kernel is in the image, should not be loaded separately
+    QB_DEFAULT_KERNEL = "none"
+
+    WKS_FILE = "efi-disk-no-swap.wks.in"
+    KERNEL_IMAGETYPE = "Image"
+
+    MACHINE_FEATURES:append = " efi uefi-secureboot"
+
+    EFI_PROVIDER = "systemd-boot"
+
+    # Use systemd as the init system
+    INIT_MANAGER = "systemd"
+    DISTRO_FEATURES:append = " systemd"
+    DISTRO_FEATURES_NATIVE:append = " systemd"
+
+    IMAGE_INSTALL:append = " systemd systemd-boot util-linux coreutils efivar"
+
+    TEST_SUITES:append = " uefi_secureboot"
\ No newline at end of file
diff --git a/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py b/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
new file mode 100644
index 00000000..9e47ea8d
--- /dev/null
+++ b/meta-arm/lib/oeqa/runtime/cases/uefi_secureboot.py
@@ -0,0 +1,29 @@ 
+#
+# SPDX-License-Identifier: MIT
+#
+
+from oeqa.runtime.case import OERuntimeTestCase
+from oeqa.core.decorator.oetimeout import OETimeout
+
+
+class UEFI_SB_TestSuite(OERuntimeTestCase):
+    """
+    Validate Secure Boot is Enabled
+    """
+
+    @OETimeout(1300)
+    def test_uefi_secureboot(self):
+        # Validate Secure Boot is enabled by checking
+        # 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot.
+        # The GUID '8be4df61-93ca-11d2-aa0d-00e098032b8c' is a well-known
+        # identifier for the Secure Boot UEFI variable. By checking the value of
+        # this variable, specifically
+        # '8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot', we can determine
+        # whether Secure Boot is enabled or not. This variable is set by the
+        # UEFI firmware to indicate the current Secure Boot state. If the
+        # variable is set to a value of '0x1' (or '1'), it indicates that Secure
+        # Boot is enabled. If the variable is set to a value of '0x0' (or '0'),
+        # it indicates that Secure Boot is disabled.
+        cmd = "efivar -d -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SecureBoot"
+        status, output = self.target.run(cmd, timeout=120)
+        self.assertEqual(output, "1", msg="\n".join([cmd, output]))