An encrypted root with a keyfile

Hello, I faced with the problem of encryption (in fact, it is described in the header). During installation of Opensuse Leap 42.1 i checked “encrypt the whole root”. Prompted for a password, well, then I think will change it to keyfile. But i can’t do this. What i tried:

cryptsetup luksAddKey /dev/sda3 /secret/mykey
cryptsetup luksAddKey /dev/sda3 /secret/mykey --key-slot 0
cryptsetup luksAddKey /dev/sda3 --key-file /secret/mykey --key-slot 0

And then added “rd.luks.key=/dev/secret/mykey” to the /boot/grub2/grub.cfg

Nothing happened. How it works in Opensuse? Please, help. Searching does not give any valid results.

It is far from clear what you did or what you are wanting to do.

I have never seen a place where I can check that during install. As far as I know, the installer specifically does not allow an encrypted root unless you use an encrypted LVM. This is part of why it is unclear what you are doing.

And then added “rd.luks.key=/dev/secret/mykey” to the /boot/grub2/grub.cfg

If root is encrypted, then that path cannot be read until after the encryption key is provided.

As far as I know, you would have to give a device reference rather than a path reference. The Arch linux wiki has some information on that, but I don’t know how to do that with opensuse. For myself, I have just typed in the key during boot.

If the root file system is not encrypted, then you would put the path to the keyfile in “/etc/crypttab”.

http://i.piccy.info/i9/24b8e65fe49aed993c11cc126ad38018/1482927589/4850/1103912/IMG_4217_240.jpg](http://piccy.info/view3/10686220/3bbf0ddb0dce70d52a42aab18a3c3b72/)http://i.piccy.info/a3/2016-12-28-12-19/i9-10686220/240x180-r/i.gif](http://i.piccy.info/a3c/2016-12-28-12-19/i9-10686220/240x180-r)

I hope you see “Encrypt” here.

In my case keyfile will be placed in the /boot section, it will be separated from other root and unencrypted.

I know how to use google and archwiki, but we are on Opensuse forum, is not it? :wink:

You have no idea how much you want to help decrypt your disk, when red-hot soldering iron immersed in your anus, you can remember even those passwords that you do not know, and if people find a laptop with you, you have nowhere to go for sure. In the case of encryption with the keyfile, device with it can be quickly destroyed.

root will be encrypted, so crypttab is useless.

I do not see it your original question. To remind:

I fail to see anything related to /boot here. So may be you start over and explain step by step exactly you have done (so that others also understand it) and what problem you had with it.

Yes, I do. But it is not encrypting root. Rather, it is encrypting an LVM, with root inside. That’s exactly what I described in my first reply.

In my case keyfile will be placed in the /boot section, it will be separated from other root and unencrypted.

However, “/boot” is not accessible until mounted. Normally, it is mounted on an empty “/boot” directory which is part of the root file system. And that mount is not possible until after the decryption step.

Maybe there are ways of setting up the “initrd” to temporarily mount that partition somewhere other than “/boot”, where it would be accessible. But such is not part of a standard setup. I’ve never looked into that, because encryption seems pointless if the encryption key is publicly accessible.

That is exactly what rd.luks.key dracut parameter does (see man dracut.kernel); it accepts device name and path on this device, mounts it on temporary mount point and gets key from path. Except there were reports that this is broken when systemd is used in initrd …

But such is not part of a standard setup.

That’s true, YaST does not support it.

man dracut.kernel:

crypto LUKS - key on removable device support
rd.luks.key=<keypath>:<keydev>:<luksdev>
keypath is a path to key file to look for. It’s REQUIRED.

keydev is a device on which key file resides. It might be kernel name of devices (should start with “/dev/”), UUID (prefixed with “UUID=”) or label (prefix
with “LABEL=”). You don’t have to specify full UUID. Just its beginning will suffice, even if its ambiguous. All matching devices will be probed. This
parameter is recommended, but not required
. If not present, all block devices will be probed, which may significantly increase boot time.

       If luksdev is given, the specified key will only be applied  for that LUKS device. Possible values are the same as for keydev. **Unless you have several LUKS
       devices, you don’t have to specify this parameter**. The simplest usage is:
           rd.luks.key=/foo/bar.key

So i just used name of my keyfile without any patches, in startpost i wrote that patch for example.

I was surprised that after my actions the system is booted normally, because I erased the key in slot 0:


cryptsetup luksAddKey /dev/sda3 --key-file /secret/mykey --key-slot 0

I do not understand how this is possible, a luksDump can clarify the situation?

You never said where your keyfile is actually stored. From you original post it appears that your keyfile is located on root filesystem which of course will not work (you cannot access decryption key on filesystem, encrypted by this key; this is catch22).

Well, we found out that the file is on the /boot, what is next?

Is boot a separate partition?

If it is on the root partition it won’t work

Yes, the boot is separate partition on the separate device, mini-sd card.

Next would be to add correct parameter. Is your file actually named /boot/dev/secret/mykey?

Unfortunately I verified that key file on a filesystem is broken at least in TW if LVM2 is also present (which you should have). I opened https://bugzilla.opensuse.org/show_bug.cgi?id=1017574
Another problem is, if dracut is based on systemd (which is default in openSUSE), dracut handling of rd.luks.* parameters no more applies, it is replaced by systemd cryptsetup generator. Which means that to have key file on a filesystem you need to actually add this filesystem to /etc/fstab in initrd (or add directly systemd unit). Which is not done by default either. And finally there is a problem of unmounting this filesystem at the right time.

What does work, is using raw device to store key. You will need to pass key length (and probably offset). Something like

rd.luks.key=/dev/disk/by-id/whatever-is-unique-to-your-device rd.luks.options=keyfile-size=NNNN,keyfile-offset=0

Challenge is to address device, you cannot use label or UUID for obvious reasons.
EDIT: if you key file on a filesystem is contiguous, you in principle can find physical location and use it. Similar to what grub does (blocklist, except here you are restricted to the single block). May be this is the simplest way to do it in your case. Use filfefrag to see file location(s).

Of course, yet another possibility is to disable systemd dracut module and rely on legacy dracut keyfile handling. This may work, I have not tested. But as this setup is probably not tested by DEV/QA either, you are essentially on your own.

There are many ways to skin a cat … :slight_smile:

Yes, this works.

localhost:~ # lsblk
NAME                                        MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
sdb                                           8:16   0    8G  0 disk
├─sdb2                                        8:18   0  7.9G  0 part
│ └─luks-502cca08-a4ff-4592-a5cc-ec4ef6650200
│   254:0    0  7.9G  0 crypt
└─sdb1                                        8:17   0  100M  0 part  /key
sr0                                          11:0    1 1024M  0 rom
sda                                           8:0    0    8G  0 disk
├─sda2                                        8:2    0  6.9G  0 part  /
└─sda1                                        8:1    0  1.1G  0 part  [SWAP]
localhost:~ # filefrag -v /key/sdb2.key
Filesystem type is: ef53
Filesystem cylinder groups approximately 13
File size of /key/sdb2.key is 4096 (4 blocks of 1024 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       3:       1025..      1028:      4:             last,merged,eof
/key/sdb2.key: 1 extent found
localhost:~ # cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.9.0-2-default root=UUID=3391002a-3ede-4037-8fd5-6c70b8b9465c resume=/dev/sda1 splash=silent quiet showopts luks.uuid=502cca08-a4ff-4592-a5cc-ec4ef6650200 luks.key=/dev/disk/by-uuid/476e6458-604d-4726-8618-1302ec3e4386 luks.options=keyfile-size=4096,keyfile-offset=1049600
localhost:~ # journalctl -b | grep -i crypt
Dec 30 05:12:53 localhost kernel: Key type encrypted registered
Dec 30 05:12:53 localhost systemd[1]: systemd 232 running in system mode. (+PAM -AUDIT +SELINUX -IMA +APPARMOR -SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID -ELFUTILS +KMOD +IDN)
Dec 30 05:12:53 localhost kernel: random: systemd-cryptse: uninitialized urandom read (16 bytes read)
Dec 30 05:12:54 localhost systemd[1]: Starting Cryptography Setup for luks-502cca08-a4ff-4592-a5cc-ec4ef6650200...
Dec 30 05:12:54 localhost systemd-cryptsetup[396]: Set cipher aes, mode xts-plain64, key size 256 bits for device /dev/disk/by-uuid/502cca08-a4ff-4592-a5cc-ec4ef6650200.
Dec 30 05:12:57 localhost systemd[1]: Started Cryptography Setup for luks-502cca08-a4ff-4592-a5cc-ec4ef6650200.
Dec 30 05:12:57 localhost systemd[1]: Reached target Encrypted Volumes.
Dec 30 05:12:57 localhost systemd[1]: Stopped target Encrypted Volumes.
Dec 30 05:12:59 localhost systemd[1]: systemd 232 running in system mode. (+PAM -AUDIT +SELINUX -IMA +APPARMOR -SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID -ELFUTILS +KMOD +IDN)
Dec 30 05:13:11 localhost systemd[1]: Reached target Encrypted Volumes.
localhost:~ #

Many thanks to all, and especially arvidjaar, his post was decisive! (i hope translator is not too disfigured this).

small step by step guide:

Standart installation of OpenSuse 42.1, during the installation process tick “Create LVM-based Proposal” and "Encrypt Volume Group"http://i.piccy.info/i9/24b8e65fe49aed993c11cc126ad38018/1482927589/4850/1103912/IMG_4217_240.jpg](http://piccy.info/view3/10686220/3bbf0ddb0dce70d52a42aab18a3c3b72/)http://i.piccy.info/a3/2016-12-28-12-19/i9-10686220/240x180-r/i.gif](http://i.piccy.info/a3c/2016-12-28-12-19/i9-10686220/240x180-r)

Keyfile creation:

dd if=/dev/random of=/dev/mmcblk0 bs=1 count=256

mmcblk0 is my external SD-card, how to use separate keyfile i did not understand

Adding keyfile to the encrypted volume:

cryptsetup luksAddKey /dev/sda3 --key-file /dev/mmcblk0 --keyfile-size 256

edit /boot/gub2/grub.cfg

adding to the kernel commandline these options:

luks.uuid=502cca08-a4ff-4592-a5cc-ec4ef6650200 # this is UUID of /dev/sda3 not LVM partition!
luks.key=/dev/mmcblk0
luks.options=keyfile-size=256
lsblk
blkid

will help you to figure out, who is who.

Now i must remove old keyphrase

cryptsetup luksOpen -v /dev/sda3 anyname

after entering passphrase you will see:

Keyslot X unlocked

Where X is likely to be 0, but it is always better to check, right? :wink:

also you can check active keyslots with:

crypsetup luksDump /dev/sda3

Deleting unneeded slot:

cryptsetup luksKillSlot /dev/sda3 0 --key-file /dev/mmcblk0 --keyfile-size 256

Now there is only one way to unencrypt you container, it’s yours keyfile.

Sorry, i did not understand, how to use keyfile-offset, it will be great, if someone explain it.

I hope my terrible English is not too messed up. Cheers!