Re: How to use serial console to enter GELI password to boot kernel on a GELI encrypted ZFS pool
Date: Sun, 21 Aug 2022 11:11:22 UTC
On Fri, Aug 19, 2022 at 09:07:25AM -0600, Warner Losh wrote:
> On Fri, Aug 19, 2022 at 2:20 AM Guido van Rooij <[1]guido@gvr.org>
> wrote:
>
> On Wed, Aug 17, 2022 at 09:19:42AM -0600, Warner Losh wrote:
> >Â Â On Wed, Aug 17, 2022 at 7:35 AM Guido van Rooij
> <[1][2]guido@gvr.org>
> >Â Â wrote:
> >
> >Â Â Â On 16 Aug 2022, at 19:09, Warner Losh
> <[2][3]imp@bsdimp.com> wrote:
> >
> >  ï»¿
> >Â Â On Tue, Aug 16, 2022 at 3:44 AM Guido van Rooij
> <[3][4]guido@gvr.org>
> >Â Â wrote:
> >
> >Â Â Â On Mon, Aug 15, 2022 at 02:20:32PM -0600, Warner Losh
> wrote:
> >Â Â Â >ÃÂ ÃÂ On Mon, Aug 15, 2022 at 8:23 AM Guido van Rooij
> >Â Â Â <[1][4][5]guido@gvr.org>
> >Â Â Â >ÃÂ ÃÂ wrote:
> >Â Â Â >
> >Â Â Â >ÃÂ ÃÂ ÃÂ Currently I have a system with ZFS on GELI. I
> use the
> >Â Â Â ability in
> >Â Â Â >ÃÂ ÃÂ ÃÂ the EFI loader to enter the GELI password.
> >Â Â Â >ÃÂ ÃÂ ÃÂ Is it possible somehow to use a serial
> console to enter
> >Â Â Â the
> >Â Â Â >ÃÂ ÃÂ ÃÂ password?
> >Â Â Â >ÃÂ ÃÂ ÃÂ My system does have a COM1 port but it isn't
> recognised at
> >Â Â Â the early
> >Â Â Â >ÃÂ ÃÂ ÃÂ bot stage. There I only see:
> >Â Â Â >ÃÂ ÃÂ ÃÂ ÃÃÂ ÃÃÂ Consoles: EFI console
> >Â Â Â >ÃÂ ÃÂ ÃÂ ÃÃÂ ÃÃÂ GELI Passphrase for disk0p4:
> >Â Â Â >ÃÂ ÃÂ ÃÂ (Note: this is early in the boot process so
> there is no
> >Â Â Â access to
> >Â Â Â >ÃÂ ÃÂ ÃÂ boot.config (or any other file in the ZFS
> pool) as it
> >Â Â Â still on
> >Â Â Â >ÃÂ ÃÂ ÃÂ encrypted storage at that time).
> >Â Â Â >
> >Â Â Â >ÃÂ ÃÂ The boot loader.efi will read
> ESP:/efi/freebsd/loader.env for
> >Â Â Â >ÃÂ ÃÂ environment
> >Â Â Â >ÃÂ ÃÂ variables. You can use that to set the COM1 port
> since it
> >Â Â Â appears your
> >Â Â Â >ÃÂ ÃÂ EFI system doesn't do console redirection.
> >Â Â Â >ÃÂ ÃÂ If you want it to only prompt COM1 for the
> password, but
> >Â Â Â everything
> >Â Â Â >ÃÂ ÃÂ else is
> >Â Â Â >ÃÂ ÃÂ on the efi console, that's a lot harder.
> >Â Â Â Hi Warner,
> >Â Â Â Thanks, but somehow I still cannot get it to work
> properly.
> >Â Â Â Content of /efi/freebsd/loader.env:
> >Â Â Â boot_multicons="YES"
> >Â Â Â console="efi comconsole"
> >Â Â Â The boot prompt still only shows "Consoles: EFI console".
> >
> >Â Â Yes. That's printed before we process the ESP file and switch
> to the
> >Â Â new console...
> >Â Â Ã
> >
> >Â Â Â When I boot I get the GELI passphrase prompt at the EFI
> console
> >Â Â Â only. But when the kernel starts
> >Â Â Â to run I do get output to the serial console, staring
> with:
> >Â Â Â ---<<BOOT>>---
> >Â Â Â Copyright (c) 1992-2021 The FreeBSD Project.
> >Â Â Â So it seems the loader.env file is read correctly (it
> didn't output
> >Â Â Â anything to the serial
> >Â Â Â console before I created efi/freebsd/loader.env). But
> looking at the
> >Â Â Â source I see in
> >Â Â Â efi/loader/main.c:read_loader_env():
> >Â Â Â ÃÂ ÃÂ ÃÂ ÃÂ if (fn) {
> >Â Â Â ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ printf("ÃÂ ÃÂ Reading
> loader env vars from
> >Â Â Â %s\n", fn);
> >Â Â Â ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ Ã
> >Â Â Â parse_loader_efi_config(boot_img->DeviceHandle, fn);
> >Â Â Â ÃÂ ÃÂ ÃÂ ÃÂ }
> >Â Â Â I never saw the printf appearing. I do not understand
> this.
> >
> >Â Â It should have appeared on the video console of the EFI
> console
> >Â Â (assuming no serial
> >Â Â redirect is going on in that BIOS).
> >
> >Â Â It surely did not.
> >
> >Â Â I'd have to delve more deeply into the prompts for the GELI
> password
> >Â Â than I have
> >Â Â time to do this morning. What if you type the password blind
> into the
> >Â Â serial port?
> >
> >Â Â Tried that but nothing happened. When I
> >Â Â enter the passphrase after typing it in via
> >Â Â the serial port, it worked immediately so
> >Â Â we can conclude that no single keystrokeÃ
> >Â Â got through.
> >
> >Â Â OK. I'll have to delve a little more deeply then...
> I Think I know why it does not work. The "Consoles:" line is printed
> in cons_probe()
> which is called in main():
> Â Â Â Â setenv("console", "efi", 1);
> Â Â Â Â cons_probe();
> So that explains why we see Consoles: EFI console
> Then we see in main():
> Â Â Â Â for (i = 0; devsw[i] != NULL; i++)
> Â Â Â Â Â Â Â Â if (devsw[i]->dv_init != NULL)
> Â Â Â Â Â Â Â Â Â Â Â Â (devsw[i]->dv_init)();
> The way I understand it, is this the place where the GELI passphrase
> prompt originates
> from.
>
> Well, not quite. We prompt for the GELI password when we first open a
> device in devopen
> (at least that's where we call geli_probe_and_attach())[*]. This should
> be a bit later, though.
> I'll have to put some debug prints in to see when it's called... But it
> looks like we probe for
> geli, according to the debug, at this point, so something needs to be
> done to sort out this
> chicken and egg problem.
> Â
>
> But only after that, we see the call to load /efi/freebsd/loader.env
> Shouldn't the dv_init() calls be moved to after the call to
> boot_howto_to_env(howto)?
>
> You have discovered a wonderful chicken and egg. If we don't call
> dv_init we can't do I/O
> to the devices, so we can't change the console.
> But, the boot_hwoto_to_env() call only sets env variables that will be
> used to either set
> boot args to the kernel or other env variables that are used to
> communicate the console.
> It doesn't actually change the console, so is the wrong thing to
> locate.
> The likely best way to approach this is to fix loader.efi to initialize
> enough of the devices
> so that we can read files off the ESP early enough to set a good
> console for further
> interaction.
> Warner
> [*] this leads to a bit of a layering violation that causes a circular
> dependency, but I digress...
>
Hi Warner,
We know for sure that the filesystem the EFI loader is read from is not
encrypted and thus we should be able to read the /efi/freebsd/loader.env.
So how about doing the dv_init() loop twice: The first time without trying
to unlock encrypted geom's. We can then safely read /efi/freebsd/loader.env.
The second dv_init() loop, we only trying to unlock the encrypted ones.
-Guido