From owner-freebsd-bugs@freebsd.org Mon Mar 29 06:50:34 2021 Return-Path: Delivered-To: freebsd-bugs@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 6A1575BE0FB for ; Mon, 29 Mar 2021 06:50:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from mailman.nyi.freebsd.org (mailman.nyi.freebsd.org [IPv6:2610:1c1:1:606c::50:13]) by mx1.freebsd.org (Postfix) with ESMTP id 4F83B22M7cz4h0W for ; Mon, 29 Mar 2021 06:50:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: by mailman.nyi.freebsd.org (Postfix) id 50D7D5BE2F7; Mon, 29 Mar 2021 06:50:34 +0000 (UTC) Delivered-To: bugs@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 509FD5BE5C3 for ; Mon, 29 Mar 2021 06:50:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4F83B21jQJz4ggt for ; Mon, 29 Mar 2021 06:50:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org (kenobi.freebsd.org [IPv6:2610:1c1:1:606c::50:1d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2DFF3684C for ; Mon, 29 Mar 2021 06:50:34 +0000 (UTC) (envelope-from bugzilla-noreply@freebsd.org) Received: from kenobi.freebsd.org ([127.0.1.5]) by kenobi.freebsd.org (8.15.2/8.15.2) with ESMTP id 12T6oY5j090727 for ; Mon, 29 Mar 2021 06:50:34 GMT (envelope-from bugzilla-noreply@freebsd.org) Received: (from www@localhost) by kenobi.freebsd.org (8.15.2/8.15.2/Submit) id 12T6oYp4090726 for bugs@FreeBSD.org; Mon, 29 Mar 2021 06:50:34 GMT (envelope-from bugzilla-noreply@freebsd.org) X-Authentication-Warning: kenobi.freebsd.org: www set sender to bugzilla-noreply@freebsd.org using -f From: bugzilla-noreply@freebsd.org To: bugs@FreeBSD.org Subject: [Bug 254637] [PATCH] Read kern.geom.eli.passphrase from UEFI variable for unattended boot without passphrase on disk Date: Mon, 29 Mar 2021 06:50:34 +0000 X-Bugzilla-Reason: AssignedTo X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: Base System X-Bugzilla-Component: kern X-Bugzilla-Version: 12.2-RELEASE X-Bugzilla-Keywords: X-Bugzilla-Severity: Affects Many People X-Bugzilla-Who: kgeorge@tcpsoft.com X-Bugzilla-Status: New X-Bugzilla-Resolution: X-Bugzilla-Priority: --- X-Bugzilla-Assigned-To: bugs@FreeBSD.org X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version rep_platform op_sys bug_status bug_severity priority component assigned_to reporter attachments.created Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: https://bugs.freebsd.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Mar 2021 06:50:34 -0000 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D254637 Bug ID: 254637 Summary: [PATCH] Read kern.geom.eli.passphrase from UEFI variable for unattended boot without passphrase on disk Product: Base System Version: 12.2-RELEASE Hardware: Any OS: Any Status: New Severity: Affects Many People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: kgeorge@tcpsoft.com Created attachment 223677 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=3D223677&action= =3Dedit Patch to loader.efi to read kern.geom.eli.passphrase from UEFI environment TL;DR this patch reads kern.geom.eli.passphrase from a namespaced UEFI "environment variable" (NVRAM firmware variable), setting it in the boot environment for unattended boot of encrypted boot disks, without storing anything on-disk in the clear. GELI is used in FreeBSD to encrypt disks / partitions. When doing encrypti= on of the boot disk, the options to decrypt the boot disk at boot time are eit= her enter a passphrase, or (if applicable) keep an unencrypted /boot partition = on the disk with keys. However, in addition to not being a great idea (consid= er the threat model of having to RMA a drive, for example), the latter option = does not work with UEFI: the UEFI loader.efi [0] stage probes devices and when it probes a GELI partition, it prompts for a passphrase. So storing on disk in /boot is not an option with UEFI (and not really great anyway), and, at lea= st on ZFS root, /boot is part of the zpool and thus encrypted by GELI regardle= ss.=20 While the /boot option does work with legacy BIOS in some configurations, t= his is going away on modern systems. The FreeBSD boot system already looks for the variable kern.geom.eli.passph= rase in the boot runtime environment and, when present, this passphrase is used before prompting the user when it encounters a GELI-encrypted partition. S= o if there was some way to get kern.geom.eli.passphrase populated it would solve this problem ... UEFI has the ability to store arbitrary, namespaced variables in system NVR= AM.=20 These are stored separate from any boot media (like on the motherboard). T= his is good for at least two reasons: 1) we can read them early in the boot process, separate from any disk block and 2) because they're separate from = the disks, the keys are never written in the clear to disk. FreeBSD already ha= s a (mostly unused, as far as I can tell) UEFI variable namespace (cfee69ad-a0de-47a9-93a8-f63106f8ae99). We can store kern.geom.eli.passphr= ase there and read it into the boot environment _before_ disks are probed, maki= ng the rest of the boot infrastructure try it before prompting. The attached patch does just that. kern.geom.eli.passphrase can be written and read by userspace tool efivar: # write % cat passphrase | head -1 | tr -d $'\n' | doas efivar --name cfee69ad-a0de-47a9-93a8-f63106f8ae99-kern.geom.eli.passphrase -w # read % doas efivar -n cfee69ad-a0de-47a9-93a8-f63106f8ae99-kern.geom.eli.passphr= ase cfee69ad-a0de-47a9-93a8-f63106f8ae99-kern.geom.eli.passphrase 0000: 74 65 73 74 31 32 33 34 ^^^^^^^^^^^^^^^^^^^^^^^ test1234 efivar requires root to read/write. The patch, which is fairly simple (but took a while to figure out exactly where/how to patch), is inline and attached: diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index a5213a51d88b..ecce7a2e4bba 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -869,6 +869,8 @@ main(int argc, CHAR16 *argv[]) char boot_info[4096]; char buf[32]; bool uefi_boot_mgr; + char geom_eli_passphrase[256]; + UINTN geom_eli_bufsz; archsw.arch_autoload =3D efi_autoload; archsw.arch_getdev =3D efi_getdev; @@ -902,6 +904,22 @@ main(int argc, CHAR16 *argv[]) */ bcache_init(32768, 512); + /* + * Read kern.geom.eli.passphrase from the EFI environment under= the + * FreeBSD EFI GUID namespace (efi_freebsd_getenv). Read before scanning + * block IO media so that it's available when probing. + */ + geom_eli_bufsz =3D sizeof(geom_eli_passphrase); + bzero(geom_eli_passphrase, geom_eli_bufsz); + rv =3D efi_freebsd_getenv("kern.geom.eli.passphrase", geom_eli_passphrase, + &geom_eli_bufsz); + if (rv =3D=3D EFI_SUCCESS) { + printf("kern.geom.eli.phassphrase read from EFI env\n"); + env_setenv("kern.geom.eli.passphrase", EV_VOLATILE, + &geom_eli_passphrase, env_noset, env_nounset); + bzero(geom_eli_passphrase, geom_eli_bufsz); + } + /* * Scan the BLOCK IO MEDIA handles then * march through the device switch probing for things. To build: % cd /usr/src % patch -p1 < /path/to/patch.patch % cd /usr/src/stand/efi/loader % make % make install # changes /boot/loader.efi To install: % mount -t msdosfs /dev/gpt/efiboot0 /mnt/efi % cp /boot/loader.efi /mnt/efi/efi/boot/BOOTx64.efi To test: On any UEFI + GELI boot system, set the passphrase like above, and rebo= ot.=20 Your system should boot without prompting (assuming your passphrase is corr= ect, of course). I've tested this / I'm using this on my own machine: 12.2-RELEASE amd64, wi= th UEFI + GELI + zfsboot. Patch is made against 12.2 branch from the git mirr= or. [0] loader.efi is the first and last stage loader now, according to http://freebsd.1045724.x6.nabble.com/UEFI-loader-efi-and-boot-config-td6308= 485.html. boot1.efi, which used to be the first stage, is being phased out. --=20 You are receiving this mail because: You are the assignee for the bug.=