rhboot / shim

UEFI shim loader
Other
852 stars 290 forks source link

Bootloader has not verified loaded image error #138

Open tbk2 opened 6 years ago

tbk2 commented 6 years ago

Hi,

I was playing with https://github.com/ipxe/shimdemo and tried to load a linux kernel without to interfere with the build in machine's UEFI Secure Boot Keys (PK,KEK,DB).

The boot chain looks like this:

  1. UEFI PXE ->
  2. microsoft signed shim.ms.efi ->
  3. vendor1 key signed shim.vendor1.efi with VENDOR_CERT_FILE=vendor2.der ->
  4. vendor2 key signed ipxe.vendor2.efi ->
  5. vendor2 key signed kernel vmlinuz.vendor2

The Trust chain looks like this:

  1. shim.ms.efi boots because the MS keys are embedded in the UEFI firmware
  2. shim.vendor1.efi boots because I added the vendor1.esl to the MokLis
  3. ipxe.vendor2.efi boots because I added the vendor2.der inside shim.vendor1.efi
  4. vmlinuz.vendor2 is not booting because of the error Bootloader has not verified loaded image

But if I boot for example a vendor2 key signed shell.vendor2.efi instead of vmlinuz.vendor2 there is no Bootloader has not verified loaded image error and I'm successfully booted a vendor2 signed UEFI shell.

Is this the desired behavior?

bjornfor commented 5 years ago

I was wondering of the same.

I found these comments helpful: https://github.com/rhboot/shim/issues/172#issuecomment-472148346 and https://github.com/rhboot/shim/issues/172#issuecomment-472218891.

There is talk about patched GRUB and "linuxefi" commands various places (like in the comments above). But GRUB master branch now has support for the shim lock protocol built into the normal "linux" command. (I've verified this myself, with grub-2.04-rc1. Remember to enable the shim_lock module.)

I guess the question is, would it be a good idea to extend the Linux EFI STUB code with support for the shim lock protocol?

codernavi18 commented 4 years ago

I used master-sb branch with HEAD c6a389813f715818c942c6b612494cba8e5fa320 pulled today Aug-19 2020.

I am using this GRUB with OVMF and Rhboot Shim.

I have the following GRUB config :

menuentry "SecBoot" {
        set root=(hd0,msdos1)
        linux (hd0,msdos1)/bzImage rootwait console=ttyS0,115200n8 console=tty0
}

I have intentionally not provided any initrd or rootfs disk, because i am just testing the secure loading of the kernel. For me this still fails and gives the error "Bootloader has not verified loaded image."

Here is some portion of the logs :

loader/efi/linux.c:44: shim_lock: 0x7de6fb90
loader/efi/linux.c:51: Asking shim to verify kernel signature
loader/efi/linux.c:53: shim_lock->verify(): 0
loader/efi/linux.c:56: Kernel signature verification passed
loader/i386/efi/linux.c:214: params = 0x3ffff000
loader/i386/efi/linux.c:223: copying 119 bytes from 0x7b933571 to 0x3ffff1f1
loader/i386/efi/linux.c:228: lh is at 0x3ffff000
loader/i386/efi/linux.c:229: checking lh->boot_flag
loader/i386/efi/linux.c:236: checking lh->setup_sects
loader/i386/efi/linux.c:243: checking lh->version
loader/i386/efi/linux.c:250: checking lh->handover_offset
loader/i386/efi/linux.c:258: checking lh->xloadflags
loader/i386/efi/linux.c:276: setting up cmdline
loader/i386/efi/linux.c:286: linux_cmdline = 3fffe000
loader/i386/efi/linux.c:293: cmdline:BOOT_IMAGE=(hd0,msdos1)/bzImage rootwait
console=ttyS0,115200n8 console=tty0
loader/i386/efi/linux.c:294: setting lh->cmd_line_ptr
loader/i386/efi/linux.c:297: computing handover offset
loader/i386/efi/linux.c:315: kernel_mem = 3eddb000
loader/i386/efi/linux.c:319: setting lh->code32_start to 0x3eddb000
loader/i386/efi/linux.c:324: setting lh->type_of_loader
loader/i386/efi/linux.c:327: setting lh->ext_loader_{type,ver}
loader/i386/efi/linux.c:331: kernel_mem: 0x3eddb000 handover_offset: 00000190
kern/disk.c:295: Closing `hd0'.
disk/efi/efidisk.c:534: closing hd0
script/script.c:65: free 0x7be7e400
script/script.c:65: free 0x7be7e440
script/script.c:65: free 0x7be7e480
script/script.c:65: free 0x7be7dc40
script/script.c:65: free 0x7be7dca0
script/script.c:65: free 0x7be7dce0
script/script.c:65: free 0x7be7dd40
script/script.c:65: free 0x7be7dda0
script/script.c:65: free 0x7be7dde0
script/script.c:65: free 0x7be7de40
script/script.c:65: free 0x7be7dea0
script/script.c:65: free 0x7be7df00
script/script.c:65: free 0x7be7df60
script/script.c:65: free 0x7be7dfc0
script/script.c:65: free 0x7be7e000
script/script.c:65: free 0x7be7e060
script/script.c:65: free 0x7be7e0c0
script/script.c:65: free 0x7be7e120
script/script.c:65: free 0x7be7e300
script/script.c:65: free 0x7be7e360
script/script.c:65: free 0x7be7e4e0
script/lexer.c:321: token 259 text [
]
script/script.c:50: malloc 0x7be7e3c0
script/script.c:50: malloc 0x7be7e380
script/lexer.c:321: token 0 text []
script/script.c:50: malloc 0x7be7e4e0
script/script.c:50: malloc 0x7be7e4a0
script/script.c:65: free 0x7be7e4a0
script/script.c:65: free 0x7be7e4e0
script/script.c:65: free 0x7be7e380
script/script.c:65: free 0x7be7e3c0
PixelBlueGreenRedReserved8BitPerColor
ConvertPages: range 1000000 - 2222FFF covers multiple entries
Bootloader has not verified loaded image.
System is compromised.  halting.
DXE ResetSystem2: ResetType Shutdown, Call Depth = 1.

The logs clearly says the it requested SHIM to verify and the shim passed the verification as successful, still it says "system compromised" and "bootloader has not verified loaded image". What am I missing here? Why this error? Any hint or guidance is really appreciated.

codernavi18 commented 4 years ago

I debugged it by attaching gdb to QEMU and found that loader_is_participating was 0 before the GRUB called shim_verify()

Screenshot 2020-08-23 at 9 28 01 PM

and was set to 1 when shim_verify() returned.

Screenshot 2020-08-23 at 9 29 55 PM

Then how is it possible that shim halts the system saying "bootloader has not verified the image" ?? This does not make sense. As per the check in exit_boot_services, it expects loader_is_participating to be 1 to let the system boot, but exactly opposite is happening. Why? Under what circumstances can it happen? Can someone please share any ideas?

pcmoore commented 3 years ago

You are using multiple UEFI shims in a chained together as part of the boot process, right? I think you might be running into the problem where the loader_is_participating check succeeds in one of the shims, but not the others.

I've seen similar problems when chaining shims together for development purposes: the last shim's ExitBootServices hook is satisfied, but the previous hooks fail.

Neightro commented 3 years ago

@pcmoore I can't prove that it's not a configuration issue on my end, as I don't know how to use QEMU, but I think that it might be possible to encounter the problem when using only one instance of Shim.

I'm currently using shim-signed from the AUR. My bootloader and kernel image are signed with my key, and my key was enrolled with MokManager. I've tried with both Arch Linux's GRUB package as well as the master branch of rhboot/grub2 and gotten the same error. By contrast the system boots without error if hashes are enrolled.

pcmoore commented 3 years ago

Hi @Neightro. If you've enrolled the second shim's hash in the MOK and used that for authorization I would expect everything to work as expected since shims ExitBootServices hook has a special case for hash-based verification. Possibly to make it easier for people not using distro signed kernels and/or to make life a bit easier for the shim developers.

static EFI_STATUS EFIAPI
exit_boot_services(EFI_HANDLE image_key, UINTN map_key)
{
        if (loader_is_participating ||
            verification_method == VERIFIED_BY_HASH) {
                unhook_system_services();
                EFI_STATUS efi_status;
                efi_status = gBS->ExitBootServices(image_key, map_key);
                if (EFI_ERROR(efi_status))
                        hook_system_services(systab);
                return efi_status;
        }

...
codernavi18 commented 3 years ago

@pcmoore I was using only one SHIM. Secondly I found that if I boot the shim from EFI shell by typing "SHIMX64.EFI" then I encounter this issue. If I rather create a UEFI boot entry using bcfg command and let the system boot normally (no manual intervention) then it succeeds fine.

Neightro commented 3 years ago

@pcmoore I'm only running one instance of Shim as well. I run it directly as a BIOS entry, and it runs GRUB just fine. I get the 'bootloader has not verified image' error as soon as I try to run my Linux kernel.

If it helps anyone, I can post more detail about my setup, such as snippets of my GRUB config; just say the word! This is nowhere near my area of expertise, so I don't have any intuition of my one as to what would be useful.

pcmoore commented 3 years ago

Hi @codernavi18 and @Neightro. Are both of you running GRUB binaries which are known to work with UEFI secure boot and shim? I'm far from an expert on shim, but I have been playing with it a lot lately and in all the cases where the Linux Kernel failed during boot is when it called into the EFI ExitBootServices (part of the kernel's EFI stub) without something in the boot chain calling the shim verification protocol; typically that is GRUB.

I don't know if it would help at all, but I've got a mostly-automated UEFI Secure Boot dev/test environment (using QEMU+OVMF+swtpm) which I've been using for my shim work and it boots Linux distros just fine. I can add a README and post that if you like.