openzfs / zfs

OpenZFS on Linux and FreeBSD
https://openzfs.github.io/openzfs-docs
Other
10.52k stars 1.74k forks source link

Native encryption support in initramfs scripts #5489

Closed pstch closed 6 years ago

pstch commented 7 years ago

System information

Type Version/Name
Distribution Name Debian GNU/Linux
Distribution Version Jessie 8.6
Linux Kernel 3.16.0
Architecture amd64
ZFS Version 0.7.0-rc2_4_gf200b83
SPL Version 0.7.0-rc2 (with encryption patches from #4329 PR)

Describe the problem you're observing

The initramfs scripts fail to decrypt the root dataset.

Describe how to reproduce the problem

Install Debian 8.6 on encrypted root (following these instructions, with external /boot on ext4, and boot from encrypted root (adding boot=zfs to kernel command line).

Include any warning/errors/backtraces from the system logs

Loading, please wait...
lvm is not available

Command: mount -o zfsutil -t zfs BIB/TEST/debian-1 /root//
Message: filesystem 'BIB/TEST/debian-1' can not be mounted due to error 13
mount: mounting BIB/TEST/debian-1 on /root// failed: Permission denied
Error: 1

[ busybox shell ]

The problem seems that zfs key -l BIB/TEST is not called by the script. If I load the key manually, then mount, I can boot without any problems.

I am reporting this issue because I'm testing the #4329 PR by @tcaputi , and the native decryption support in initramfs is not part of the PR, and has already been committed.

Sidenote: other than this boot nitpick, my native encrypted root test system seems to work pretty fine, and it's really refreshing to be able to use per-dataset encryption on a Linux system. Thanks a lot for all of your hard work!

pstch commented 7 years ago

@behlendorf If I understand the code correctly, the feature is already implemented (in contrib/initramfs/scripts/zfs, but it doesn't work for some reason, which I'm still trying to find out.

tcaputi commented 7 years ago

@pstch It looks like that script is for the old encryption implementation that Oracle / Sun was working on before the ZFS project went closed source. It actually directly refers to sun kernel modules which is probably why it isnt working. I can take a look on Monday and see how hard it is to get this working.

sempervictus commented 7 years ago

@tcaputi: I meant to create an issue for these items when the PR hit master, but this is as good a place as any. Several integration points for common use cases which come to mind are:

  1. User home directory decryption hooks like the ones used for ecryptfs by most distros
  2. Initramfs scripts for encrypted root datasets/pools
  3. Grub, syslinux, and other bootloaders

I imagine the mailing lists for the various initramfs generator implementations and bootloaders will eventually pick up on their own, but may be beneficial to give them a heads up. Far as the home directory thing, that will probably require ZFS userspace to hook PAM for auth (if we're using some directory integrated auth mechanism to pass a token permitting decryption) or implement its own hooks for user logins into encrypted home dirs.

tcaputi commented 7 years ago

@sempervictus I can probably try to figure out scripts for home directory decryption and the initramfs scripts. I imagine bootloader projects won't even want to look at getting this integrated until the on-disk format is finalized, So I'll probably hold off on that.

tcaputi commented 7 years ago

@pstch I do not currently have a machine available to test an encrypted zfs root. However, I believe that changing the decrypt_fs() function in contrib/initramfs/scripts/zfs to the following should allow you to boot.

decrypt_fs()
{
    local fs="$1"

    # Check if filesystem is encrypted. If not, exit right here.
    [ "$(get_fs_value "$fs" encryption)" != "off" ] || return 0

    [ "$quiet" != "y" ] && \
        zfs_log_begin_msg "Loading crypto wrapper key for $fs"

    # If the key isn't availible, then this will fail!
    ZFS_CMD="${ZFS} key -l $fs"
    ZFS_STDERR="$(${ZFS_CMD} 2>&1)"
    ZFS_ERROR="$?"

    if [ "${ZFS_ERROR}" != 0 ]
    then
        [ "$quiet" != "y" ] && zfs_log_failure_msg "${ZFS_ERROR}"

        disable_plymouth
        echo ""
        echo "Command: $ZFS_CMD"
        echo "Message: $ZFS_STDERR"
        echo "Error: $ZFS_ERROR"
        echo ""
        echo "Failed to load zfs encryption wrapping key (s)."
        echo "Please verify dataset property 'keysource' for datasets"
        echo "and rerun:  $ZFS_CMD"
        /bin/sh
    else
        [ "$quiet" != "y" ] && zfs_log_end_msg
    fi

    return 0
}

Basically all I did was remove the Sun-isms (we don't have separate crypto modules to load, our zfs key command is slightly different from theirs, etc). I will be able to confirm it myself later but if it works then you can start using it without waiting until then.

sempervictus commented 7 years ago

@tcaputi: thanks as always. Far as bootloaders go, having the kernel and initramfs on an encrypted dataset would go a long way toward improving boot integrity, and they only need to be able to read kernel and initramfs data.

More to the point i guess, what still remains to be defined in the on-disk format? I thought the prospective conflicts with other companies changes from upstream were addressed.

tcaputi commented 7 years ago

@sempervictus

More to the point i guess, what still remains to be defined in the on-disk format? I thought the prospective conflicts with other companies changes from upstream were addressed.

The big remaining issue is that we are still working on getting everything reviewed from a cryptographic perspective. Although I am fairly confident in the work I've done and I've addressed quite a few issues that are even present in Oracle's encryption implementation, I may have missed something that would require an on-disk format change to fix.

almereyda commented 6 years ago

It appears this is dependent on https://github.com/zfsonlinux/grub/issues/24

sylveon commented 6 years ago

I'll pull this argument once again (it's pretty much my only activity on this repo), but you don't need GRUB to boot. You can use something else, such as systemd-boot, EFISTUB or rEFInd.

Waiting for GRUB support to implement this is preventing people using other bootloaders to use an encrypted root, just because a bootloader they don't use isn't supporting it yet.

sempervictus commented 6 years ago

Not really, the grub support deals with /boot being encrypted, initramfs is one of the things loaded from /boot by grub.

sjau commented 6 years ago

I'm rather new to ZFS but I've been using mdadm raid1, luks/dm-crypt for quite some time. While I see that having also encrypted /boot is something to desire, I tend to think that it is not as important as having encrypted root easily available.

On my notebook I use Nixos and it's fairly simple to create encrypted root zfs (witch unencrypted ext4 /boot partition). However getting encrypted root zfs on Debian to run took me some trial and error.

Also many thanks to tcaputi for providing zfs encryption - also I learnt a lot about how full disk encryption actually works watching your announcement presentation video.