4

I'm trying to understand why secure boot works on my machine. It is enabled in the UEFI config, everything boots just fine, and mokutil --sb-state says SecureBoot enabled. But I think it shouldn't. Here is how it's supposed to work AFAIK:

  1. I turn on the machine, and it starts running its builtin firmware.
  2. The firmware verifies the shim (signed by Microsoft) and jumps into it.
  3. The shim verifies GRUB (signed by the distro) and jumps into it.
  4. GRUB verifies its config, the initrd (signed by me?), the kernel (signed by the distro) and boots the kernel.
  5. The kernel verifies modules (signed by the distro) before loading them.

When I try to verify this manually, the only thing that has a valid signature is the shim. GRUB and the kernel image contain signatures but they fail verification. The initrd and the grub config are not signed. Yet the system boots which does not inspire confidence.

I used mokutil, sbverify, and osslsigncode. Maybe these are not the right tools? Maybe secure boot is actually disabled? I'll try to give as much information as I can.

Here is what I did

First, I exported all of the trusted public keys using mokutil and displayed the issuer and subject for reference.

# mokutil --export --pk
# mokutil --export --kek
# mokutil --export --db
# mokutil --export
# for derfile in ./*.der; do
>     openssl x509 -inform der -outform pem -in "$derfile" -out "${derfile}.pem"
> done
# rename 's/.der.pem$/.pem/' ./*.der.pem
# for pemfile in ./*.pem; do
>     echo "$pemfile"
>     openssl x509 -inform pem -in "$pemfile" -text | egrep 'CN ?='
> done
./DB-0001.pem
        Issuer: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Root Certificate Authority 2010
        Subject: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Windows Production PCA 2011
./DB-0002.pem
        Issuer: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Corporation Third Party Marketplace Root
        Subject: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Corporation UEFI CA 2011
./DB-0003.pem
        Issuer: C = US, O = HP Inc., CN = HP Inc. DB Key 2016 CA
        Subject: CN = HP UEFI Secure Boot DB 2017, OU = CODE-SIGN, C = US, O = HP Inc.
./KEK-0001.pem
        Issuer: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Corporation Third Party Marketplace Root
        Subject: C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, CN = Microsoft Corporation KEK CA 2011
./KEK-0002.pem
        Issuer: C = US, O = HP Inc., CN = HP Inc. KEK 2016 CA
        Subject: CN = HP UEFI Secure Boot KEK 2017, OU = CODE-SIGN, C = US, O = HP Inc.
./MOK-0001.pem
        Issuer: CN = strib.tech
        Subject: CN = strib.tech
./MOK-0002.pem
        Issuer: CN = Debian Secure Boot CA
        Subject: CN = Debian Secure Boot CA
./PK-0001.pem
        Issuer: C = US, O = HP Inc., CN = HP Inc. PK 2016 CA
        Subject: CN = HP UEFI Secure Boot PK 2017, OU = CODE-SIGN, C = US, O = HP Inc.

Then, I tried to verify all the relevant files with all of these public keys using sbverify.

# for imgfile in /boot/vmlinuz-* /boot/initrd.img-* /boot/efi/EFI/devuan/*; do
>     for pemfile in ./*.pem; do
>         sbverify --cert "$pemfile" "$imgfile" &> /dev/null && echo "$imgfile is signed with $pemfile"
>     done
> done
/boot/efi/EFI/devuan/shimx64.efi is signed with ./DB-0002.pem

Oops. Let's check why. I'll show the GRUB image here, but the situation is the same for the shim helper modules and the kernel image.

# sbverify --list /boot/efi/EFI/devuan/grubx64.efi
signature 1
image signature issuers:
 - /CN=Debian Secure Boot CA
image signature certificates:
 - subject: /CN=Debian Secure Boot Signer 2020
   issuer:  /CN=Debian Secure Boot CA

It is claiming to be signed by a key that is signed by MOK-0002.pem. Maybe I don't have that key? Turns out I do, it's just hidden in the same file along with the signature. So I got it out.

# osslsigncode extract-signature -pem -in /boot/efi/EFI/devuan/grubx64.efi -out signature.pem
Succeeded
# openssl pkcs7 -in signature.pem -print_certs -out intermediate.pem
# openssl x509 -in intermediate.pem -text | grep CN
        Issuer: CN = Debian Secure Boot CA
        Subject: CN = Debian Secure Boot Signer 2020

Unfortunately, verification still fails. Same thing if I cat intermediate.pem and MOK-0002.pem together, in any order, or if I remove the junk before BEGIN CERTIFICATE.

# sbverify --cert intermediate.pem /boot/efi/EFI/devuan/grubx64.efi
Signature verification failed

osslsigncode also has a verify option, and gives more information than sbverify.

# osslsigncode verify -in /boot/efi/EFI/devuan/grubx64.efi -CAfile both.pem -verbose
Current PE checksum   : 00183046
Calculated PE checksum: 00183046

Signature Index: 0  (Primary Signature)
Message digest algorithm  : SHA256
Current message digest    : A9BDE7F125657CB9E30974274B8B2762B2AA7CB86D8DE9386A645A49077AAF8E
Calculated message digest : A9BDE7F125657CB9E30974274B8B2762B2AA7CB86D8DE9386A645A49077AAF8E

Signer's certificate:
    Signer #0:
        Subject: /CN=Debian Secure Boot Signer 2020
        Issuer : /CN=Debian Secure Boot CA
        Serial : B55EB3B9
        Certificate expiration date:
            notBefore : Jul 21 15:52:54 2020 GMT
            notAfter : Jul 21 15:52:54 2030 GMT

Number of certificates: 1
    Signer #0:
        Subject: /CN=Debian Secure Boot Signer 2020
        Issuer : /CN=Debian Secure Boot CA
        Serial : B55EB3B9
        Certificate expiration date:
            notBefore : Jul 21 15:52:54 2020 GMT
            notAfter : Jul 21 15:52:54 2030 GMT

CAfile: both.pem
TSA's certificates file: /usr/lib/ssl/certs/ca-bundle.crt

Timestamp is not available

Unsupported Signer's certificate purpose XKU_CODE_SIGN
Signature verification: failed

Number of verified signatures: 1
Failed

Maybe the shim ignores all other superfluous fields like the certificate purpose. I'd be fine with this. But to believe that, I'd need to see a different error with a modified GRUB image. The problem is when I overwrite a few bytes here and there, osslsigncode just segfaults.

Partial solution

I know it is possible to embed the initrd inside the kernel image, and the GRUB config in the GRUB image, which I could then sign with my own key, MOK-0001.pem. So if I can get those signatures verified, I'd be basically done. Verifying the kernel modules would be great, but since they'd be loaded from a verified initrd or a LUKS partition, it's not a huge deal.

What about the kernel modules

The kernel modules are signed according to modinfo (sbverify and osslsigncode don't recognize the file format).

# modinfo iwlwifi | egrep -A12 '^sig'
sig_id:         PKCS#7
signer:         Debian Secure Boot CA
sig_key:        B5:5E:B3:B9
sig_hashalgo:   sha256
signature:      A1:B8:D5:51:C0:C2:80:AD:01:7A:6E:E9:E9:96:E8:BB:4F:53:7F:09:
        1A:62:04:8F:5A:62:97:0C:37:0D:98:17:C4:30:E3:39:9D:4B:FB:7E:
        64:03:69:CA:A6:37:59:8C:F9:05:66:FB:A5:F1:66:88:8B:11:75:05:
        0C:52:8B:A4:44:D7:70:BD:02:9F:29:1C:87:F4:37:15:6F:83:C8:D7:
        2B:BC:CE:F9:9E:D4:D2:23:5A:26:48:A1:C7:43:A7:74:0C:6A:9C:18:
        12:A7:D5:93:F2:D8:0D:9D:28:6F:34:CD:88:79:A1:26:32:D3:9F:BF:
        8F:B7:91:CA:AF:1E:36:96:B0:F8:FA:B9:05:80:A5:E3:5B:5C:BB:A8:
        5B:EC:5D:B6:97:B8:8F:00:99:62:69:19:C5:58:F4:13:D9:3C:5A:C0:
        9F:08:49:43:CF:30:DB:CD:8E:9B:6F:65:21:5E:64:68:5B:33:26:93:
        38:F5:DA:40:B1:F4:5F:E9:A0:E3:C3:10:C6:0C:EA:A1:42:BF:A8:DD:
        59:88:32:E9:7B:4A:2B:0D:89:9D:6F:E7:CE:0D:A6:E9:28:D8:3F:C8:
        B1:4F:FC:DD:35:22:D6:23:C4:86:C3:78:1F:5D:E8:2E:FD:3E:D4:D8:
        CC:30:1D:BF:5A:2C:C2:2E:83:E8:63:CB:1F:D3:7D:FD

Does modinfo actually verify this or does it just print whatever signature it finds I don't know. I tried changing random bytes in the .ko file to get a failure, but it is unclear from the error message whether it is because of the signature, or just some ELF checksum.

# modinfo iwlwifi.ko
filename:       /root/iwlwifi.ko
modinfo: ERROR: could not get modinfo from 'iwlwifi': Invalid argument

Updates

I modified the osslsigncode source, and I can now verify signatures. The problem was it explicitly disallowed XKU_CODE_SIGN as a certificate purpose.

--- osslsigncode-2.1.orig/osslsigncode.c
+++ osslsigncode-2.1/osslsigncode.c
@@ -2521,12 +2521,6 @@ static int verify_authenticode(SIGNATURE
            goto out;
    }
 
-   /* check extended key usage flag XKU_CODE_SIGN */
-   if (!(X509_get_extended_key_usage(signer) & XKU_CODE_SIGN)) {
-       printf("Unsupported Signer's certificate purpose XKU_CODE_SIGN\n");
-       goto out;
-   }
-
    verok = 1; /* OK */
 out:
    if (!verok)

With this new version, I can successfully verify the shim helper modules, GRUB, and the kernel. Now I can create a GRUB image using grub-mkstandalone with an embedded public key, and a minimal config that enables signature checking and loads the main config. This covers all files read by GRUB and uses good old GPG detached signatures. Which means there is no need to use CONFIG_INITRAMFS_SOURCE (that would have been super annoying).

Artem S. Tashkinov's answer clarifies the situation with the kernel modules. I think that's all. I'll create a bootable signer USB stick and keep the secret keys there, which I'll need for updating GRUB (shouldn't be that often).

2
  • 1
    You might find this article useful: rodsbooks.com/efi-bootloaders/controlling-sb.html -- sorry, I've not touched UEFI with a six foot pole for quite some time having preferred to move off x86 after implementing UEFI/SB in our distro and looking where it all goes so didn't quite go through your question in detail... Commented Feb 25, 2021 at 17:04
  • 1
    It's interesting, I might want to kick out Microsoft and sign my own shim, or hell, do I even need a shim at that point? I could just load GRUB directly. But I'm not quite there yet. First I want to understand how and why it currently works, and predict if the host is going to come back after a reboot. Realistically, I don't really want to kick out the distro and HP, because they sign kernels and firmware updates. But MS is just kind of there in the boot process for whatever reason, doing almost nothing.
    – stribika
    Commented Feb 25, 2021 at 18:54

1 Answer 1

2

This is not an answer but a comment which I'd like to add anyways because I believe it's relevant.

The Secure boot EFI mechanism only verifies binaries and libraries (e.g. executable code) signatures which are being run, it does not and cannot verify anything beyond that because it would make booting impossible. Any OS needs to know where to boot from and this information comes from user modifiable unsigned configuration files, e.g. /boot/efi/EFI/Microsoft/Boot/BCD in case of Windows and /boot/efi/EFI/$distro/grub.cfg in case of Linux distros.

This situation is kinda scary because in case of Linux where almost all existing distros use initrd it allows the attacker to modify the initrd and completely circumvent any protections in case he's got hardware access to your device. If you're concerned about that you should have only an encrypted storage on your device and boot from an encrypted USB flash drive.

Lastly, again sorry for not answering your question, this command will tell you whether your system is running in secure boot mode:

dmesg | grep -i secure\ boot\ enabled

Lastly, modinfo does not verify signatures, it only shows them. The kernel absolutely does that - here's a result after I've changed a few random bytes using hexedit:

# modprobe orangefs 
modprobe: ERROR: could not insert 'orangefs': Key was rejected by service
5
  • The kernel does think secure boot is enabled, and also goes to lockdown mode. This is helpful, at least I don't have to worry about the kernel modules.I also looked into this a bit more, GRUB supports proper GPG signatures on its configs, so only a minimal config needs to be included in the image. It also updates the PCR registers with everything it loads, including configs, initrd, the kernel command line, etc. I am not yet sure how to use that though.
    – stribika
    Commented Feb 25, 2021 at 15:46
  • The whole topic is quite complicated and the information about it is scattered unless you're ready to dive deep into the EUFI specification which is several hundred pages long. And then there's not just one specification, Apple has its own, as well as ARM. Commented Feb 25, 2021 at 16:11
  • 1
    Yeah, I wanted to read the specs before starting, I think it's good practice. Then, on about page 20 I realized it's 2637 pages. So, maybe later.
    – stribika
    Commented Feb 25, 2021 at 16:43
  • 1
    LMAO. You made my day. Commented Feb 25, 2021 at 16:57
  • well this might help somehow: en.altlinux.org/UEFI_SecureBoot_mini-HOWTO Commented Feb 26, 2021 at 20:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .