Subject: bug#21843: Generated grub.cfg does not support encrypted roots

From: Andreas Enge <[email-masked]>
Date: Tue, 8 Mar 2016 20:21:04 +0100

I tried the installation with unencrypted /boot, encrypted / using the
following snippet in the configuration file:
  (bootloader (grub-configuration (device "/dev/sda")))
  (mapped-devices (list (mapped-device
                         (source "/dev/sda2")
                         (target "root")
                         (type luks-device-mapping))))
  (file-systems (cons* (file-system
                        (device "/dev/mapper/root")
                        (title 'device)
                        (mount-point "/")
                        (type "ext4")
                        (needed-for-boot? #t))
                       (file-system
                         (device "boot")
                         (title 'label)
                         (mount-point "/boot")
                         (type "ext4")
                         (needed-for-boot? #t))
                       %base-file-systems))

Grub did not start, as it did not find the kernel etc. in /gnu/store.

So I typed "c" at the grub menu (in text mode without the splash screen,
which also resides in /gnu/store), and issued the following two commands:
  insmod luks
  cryptomount hd0,msdos2

This prompted me for the password a first time. The "insmod cryptodisk" was
not necessary. There was a new device called "(crypto0)" now; "ls (crypto0)/"
showed, among others, the /gnu directory.

Now I still needed to define the kernel; running "boot" was not enough.

I executed
  configfile (hd0,msdos1)/grub/grub.cfg
and now obtained the normal grub menu (with the splash screen) and could now
boot as usual. I was prompted a second time for the password.
According to the grub.cfg, grub searches for the kernel by file name and
uses the device where it is found automatically as root. So the second time
it must also have searched (crypto0).

This can be automated; I just added the two lines
  insmod luks
  cryptomount hd0,msdos2
to the top of grub.cfg, and the next time everything worked out of the box
(with two password prompts: the first one in text mode before grub was visibly
started, then the grub splash screen appeared, then during the normal boot).

The only difficulty here is the mapping between the mapped-device /dev/sda2
and the grub device hd0,msdos2. We would need to determine this automatically
when creating the grub.cfg during the call to "guix system init".

Maybe UUIDs can help. The command
   crytsetup luksUUID /dev/sda2
returns a hex string with dashes, in my case 1aa...-...
This could be run during "guix system init" with the source field of
mapped-device.
The grub manual at:
  https://www.gnu.org/software/grub/manual/html_node/Device-syntax.html#Device-syntax
mentions a device syntax such as
  (cryptouuid/123456789abcdef0123456789abcdef0)
I tried replacing
  cryptomount hd0,msdos2
by
  cryptomount cryptouuid/1aa...
(without the dashes), but this did not work.
The strange thing is that grub somehow knows this uuid; when I type
   cryptomount hd0,msdos2
I am presented with the prompt
   Enter passphrase for hd0,msdos2 (1aa...):

So I am stuck here.

A first tentative solution would be to look for mapped-devices of type
luks-device-mapping that correspond to file-systems with needed-for-boot?
set to #t, and then add the corresponding "cryptomount" lines to grub.cfg,
with the obvious mapping sda->hd0, sdb->hd1,..., and 1->msdos1, 2->msdos2
and so on.

This would not be perfect, but at least better than what we have now.

And the line "insmod luks" could be added unconditionally (or only in the
presence of a mapped-device of type luks-device-mapping).

Andreas