grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] verifiers: Don't return error for deferred image


From: Leo Yan
Subject: Re: [PATCH] verifiers: Don't return error for deferred image
Date: Mon, 26 Dec 2022 16:13:20 +0800

Hi Boyang,

On Thu, Dec 22, 2022 at 10:37:01PM +0800, Zhang Boyang wrote:

[...]

> > > On 2022/12/22 19:14, Leo Yan wrote:
> > > > When boot from menu and the flag GRUB_VERIFY_FLAGS_DEFER_AUTH is set,
> > > > grub returns error:
> > > > 
> > > >    Booting a command list
> > > > 
> > > >    error: verification requested but nobody cares: (hd0,gpt1)/Image.
> > > > 
> > > >    Press any key to continue...
> > > > 
> > > > In this case, the image should be deferred for authentication, grub
> > > > should return the file handle and pass down to later firmware (e.g.
> > > > U-Boot, etc) for authentication.
> > > 
> > > This is probably not what verification framework designed to be. It seems 
> > > to
> > > be designed to verify files during GRUB is executing (e.g. check file
> > > signature if UEFI Secure Boot is enabled).
> > 
> > Good point.  We expect the solution is grub can defer authentication for
> > an image and invokes EFI LoadImage service, then EFI loader can load
> > and verify the image.
> 
> Since you mentioned "authentication" and "verify", I guess you are
> using/implementing some kind of secure boot mechanism. Is it an standard
> UEFI Secure Boot implementation?

I don't read specification for standard UEFI secure boot, but from my
very limited understanding, I don't think now I am using a standard
UEFI secure boot sequence.

Anyway, I will explain more in below comments.

> The standard UEFI Secure Boot for Linux works like this (at least on x86):
> 
> 1) Firmware verifies and loads shim (shimx64.efi), which is signed by
> Microsoft. (https://github.com/rhboot/shim )
> 
> 2) shim registers an EFI protocol, to provide an API for verifying files.
> 
> 3) shim verifies and loads GRUB (grubx64.efi), using certificate embedded in
> itself. The certificate is generated by vendor (e.g. Debian).
> 
> 4) GRUB opens kernel image file and loads and executes that file. The key
> point is, during grub_file_open() of the kernel image, the verifier
> framework will call shim lock verifier, which calls the API provided by
> shim, to verify the signature of kernel file. (grub-core/kern/efi/sb.c)
> 
> In the above example, the kernel is loaded by GRUB, not shim, not EFI
> firmware. GRUB calls the API provided by shim to verify the kernel.
> 
> Another example is GRUB can also chainload Windows:
> 
> 1) 2) 3) is same
> 
> 4) GRUB invokes EFI firmware's LoadFile() and StartImage(). The verification
> is completely delegated to EFI firmware. shim is not envolved.
> 
> In this example, the verification is done by EFI firmware, and GRUB/shim has
> no control of it. You can't even chainload GRUB itself because it's not
> signed by Microsoft.

Very good summary, thanks a lot!

> > For more specific, now I am debugging U-boot EFI with grub, since U-boot
> > EFI provides functionality for loading and authentication image (see
> > efi_load_image() in [1]), this is my purpose to use U-boot EFI to
> > authenticate kernel image (and even for initrd image).
> > 
> 
> It seems efi_load_image() is just a wrapper of EFI firmware's LoadFile() and
> there is no implementation of verification in U-boot?

This isn't right.  U-boot EFI service verifies image with below flow:

  efi_load_image()
    `> efi_load_pe()
         `> efi_image_authenticate()

> I'd like to ask what kind of image you are trying to boot/execute? If it is
> an EFI application, I think you can "chainloader" it and forget U-boot (if
> U-boot have no verification in it self).

We want to create a trust of chian:

  firmware -> U-boot -> GRUB -> Linux kernel image / initrd / grub.cfg

Comparing against you mentioned solution which uses shim to verify and
load GRUB, we use U-boot to verify and load GRUB.  Therefore, in our
implementation we don't use shim verifier for GRUB, and not for later
Linux kernel image / initrd / GRUB config files.

> Let me guess: You are using standard Secure Boot, and want to boot linux
> kernel image directly signed by keys in EFI firmware, and your GRUB is
> installed with --disable-shim-lock. If this is what you are doing, you might
> run into the following situation:
> 
> 1) During GRUB init, grub_efi_init() detects Secure Boot is enabled, so it
> calls grub_lockdown(). [grub-core/kern/efi/init.c]
> 
> 2) grub_lockdown() registers lockdown verifier. [grub-core/kern/lockdown.c]
> 
> 3) grub_efi_init() also calls grub_shim_lock_verifier_setup(). However,
> grub_shim_lock_verifier_setup() does nothing because of
> "--disable-shim-lock" [grub-core/kern/efi/sb.c]
> 
> 4) During GRUB load linux kernel, the lockdown verifier sets a flag
> (GRUB_VERIFY_FLAGS_DEFER_AUTH) for kernel file, and expect shim lock
> verifier to do the verification.
> 
> 5) However, there is no shim lock verifier. As a security measure, it
> reports the error "verification requested but nobody cares".
> 
> So the root cause seems like --disable-shim-lock is broken?

Excellent analysis, and it's exactly an issue I am facing.

> As a workaround, you can use shim: build shim for you platform and install
> GRUB with shim support.
> 
> You can also submit a fix to --disable-shim-lock (recommended). However it
> should be done very carefully. I'm afraid you can't remove the security
> measure (i.e. the "verification requested but nobody cares") directly. I
> think it is a good idea to add an EFI verifier (like shim verifier), which
> use LoadImage() to do verification, and enable it if (and only if)
> --disable-shim-lock is specified. You can talk to GRUB maintainers about
> your proposal before coding.

Thanks a lot for the suggestion.  As you proposed to add an EFI
verifier, this would be a candidate solution we should consider
seriously, seems to me, this is a neat way to allow us to hook the
verifier in U-boot and GRUB.

However, I found actually we have another choice (though it's not neat
but it does work after I did some experiments).  We can enable GRUB's
internal verifier 'gpg', thus we can sign grub.cfg / kernel image
/ initrd with the gpg key and GRUB will use 'gpg' verifier to load
these images, please note, we sign these files with detached format so
every file has a corresponding signature file with suffix '.sig'.

The tricky thing is the kernel image, since GRUB invokes EFI LoadImage()
to load kernel image, and the kernel image has a self-contained
signature, so finally the kernel image also will be authenticated by
U-boot's EFI service.  This means the kernel image will be
authenticated for twice, one is by GRUB's verifier and another is by
U-boot's efi_load_image().

At least it's a pragmatic solution for me, I will check internally if we
should move forward for using a central place (like U-boot) for all files
authentication and it also can simplify the key management.

> The above is what I guess about what's happening. It might be wrong. Please
> point out if there is something wrong.

I would like to step back a bit and ask a question: if GRUB doesn't
enable any crypto verifier and it runs into grub_verifiers_open(), in
current code grub_verifiers_open() prevents to load kernel image.  In
this case, here I am confused why we cannot proceed to load kernel
image?  Or I want to check with maintainers if this patch is still
valid :)

Very appreciate your insight comments and suggestions!

Leo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]