From 0963ba83dd92fefbc914bbde419bb613fbe5fa15 Mon Sep 17 00:00:00 2001 From: Julian Stecklina Date: Thu, 2 Feb 2023 14:38:34 +0100 Subject: [PATCH] tests: check whether disabled secure boot relaxes hash checks --- nix/tests/lanzaboote.nix | 85 ++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 26 deletions(-) diff --git a/nix/tests/lanzaboote.nix b/nix/tests/lanzaboote.nix index d8f0781..cc79538 100644 --- a/nix/tests/lanzaboote.nix +++ b/nix/tests/lanzaboote.nix @@ -6,7 +6,7 @@ let inherit (pkgs) lib; - mkSecureBootTest = { name, machine ? { }, testScript }: testPkgs.nixosTest { + mkSecureBootTest = { name, machine ? { }, useSecureBoot ? true, testScript }: testPkgs.nixosTest { inherit name testScript; nodes.machine = { lib, ... }: { imports = [ @@ -17,7 +17,8 @@ let virtualisation = { useBootLoader = true; useEFIBoot = true; - useSecureBoot = true; + + inherit useSecureBoot; }; boot.loader.efi = { @@ -31,14 +32,18 @@ let }; }; - # Execute a SB test that is expected to fail because of a hash mismatch. + # Execute a boot test that has an intentionally broken secure boot + # chain. This test is expected to fail with Secure Boot and should + # succeed without. # # Takes a set `path` consisting of a `src` and a `dst` attribute. The file at # `src` is copied to `dst` inside th VM. Optionally append some random data # ("crap") to the end of the file at `dst`. This is useful to easily change # the hash of a file and produce a hash mismatch when booting the stub. - mkHashMismatchTest = { name, path, appendCrap ? false }: mkSecureBootTest { + mkHashMismatchTest = { name, path, appendCrap ? false, useSecureBoot ? true }: mkSecureBootTest { inherit name; + inherit useSecureBoot; + testScript = '' import json import os.path @@ -62,9 +67,40 @@ let machine.succeed("sync") machine.crash() machine.start() + '' + (if useSecureBoot then '' machine.wait_for_console_text("Hash mismatch") - ''; + '' else '' + # Just check that the system came up. + print(machine.succeed("bootctl", timeout=120)) + ''); }; + + # The initrd is not directly signed. Its hash is embedded into + # lanzaboote. To make integrity verification fail, we actually have + # to modify the initrd. Appending crap to the end is a harmless way + # that would make the kernel still accept it. + mkModifiedInitrdTest = { name, useSecureBoot }: mkHashMismatchTest { + inherit name useSecureBoot; + + path = { + src = "bootspec.get('initrd')"; + dst = "convert_to_esp(bootspec.get('initrd'))"; + }; + + appendCrap = true; + }; + + mkModifiedKernelTest = { name, useSecureBoot }: mkHashMismatchTest { + inherit name useSecureBoot; + + path = { + src = "bootspec.get('kernel')"; + dst = "convert_to_esp(bootspec.get('kernel'))"; + }; + + appendCrap = true; + }; + in { # TODO: user mode: OK @@ -109,31 +145,28 @@ in ''; }; - # The initrd is not directly signed. Its hash is embedded - # into the UKI. To make integrity verification fail, we - # actually have to modify the initrd. Appending crap to the - # end is a harmless way that would make the kernel still - # accept it. - secured-initrd = mkHashMismatchTest { - name = "lanzaboote-secured-initrd"; - path = { - src = "bootspec.get('initrd')"; - dst = "convert_to_esp(bootspec.get('initrd'))"; - }; - appendCrap = true; + modified-initrd-doesnt-boot-with-secure-boot = mkModifiedInitrdTest { + name = "modified-initrd-doesnt-boot-with-secure-boot"; + useSecureBoot = true; }; - secured-kernel = mkHashMismatchTest { - name = "lanzaboote-secured-kernel"; - path = { - src = "bootspec.get('kernel')"; - dst = "convert_to_esp(bootspec.get('kernel'))"; - }; - appendCrap = true; + modified-initrd-boots-without-secure-boot = mkModifiedInitrdTest { + name = "modified-initrd-boots-without-secure-boot"; + useSecureBoot = false; }; - specialisation = mkSecureBootTest { - name = "lanzaboote-specialisation"; + modified-kernel-doesnt-boot-with-secure-boot = mkModifiedKernelTest { + name = "modified-kernel-doesnt-boot-with-secure-boot"; + useSecureBoot = true; + }; + + modified-kernel-boots-without-secure-boot = mkModifiedKernelTest { + name = "modified-kernel-boots-without-secure-boot"; + useSecureBoot = false; + }; + + specialisation-works = mkSecureBootTest { + name = "specialisation-still-boot-under-secureboot"; machine = { pkgs, ... }: { specialisation.variant.configuration = { environment.systemPackages = [