Compare commits

...

6 Commits

View File

@@ -63,9 +63,11 @@ After installation you're going to want to at least touch these points in your n
# Password change # Password change
After installation you're going to want to change your ZFS encryption password.
## Steps ## Steps
After installation you're going to want to change your ZFS encryption password. This generally means in a running OS: In a running OS:
1. Change password in `keylocation` file, e.g. `/etc/zfs/zpool.key` or whatever other `"${zpool_name}"'.key'` file you used during setup 1. Change password in `keylocation` file, e.g. `/etc/zfs/zpool.key` or whatever other `"${zpool_name}"'.key'` file you used during setup
1. Set this key as the new encryption key: 1. Set this key as the new encryption key:
@@ -83,7 +85,7 @@ After installation you're going to want to change your ZFS encryption password.
With your password changed in two locations (key file and initramfs) The boot process works as follows. With your password changed in two locations (key file and initramfs) The boot process works as follows.
At boot time ZFSBootMenu will scan all pools that it can import for a `bootfs` property. If it only finds one pool with that property the dataset given as `bootfs` will be selected for boot with a 10-second countdown allowing manual interaction. With `bootfs` set ZFSBootMenu will not actively search through datasets for valid kernel and initramfs combinations, it'll instead accept `bootfs` as the default boot entry without entering the pool decryption passphrase. At boot time ZFSBootMenu will scan all pools that it can import for a `bootfs` property. If it only finds one pool with that property the dataset given as `bootfs` will be selected for boot with a 10-second countdown allowing manual interaction. With `bootfs` set ZFSBootMenu will not actively search through datasets for valid kernel and initramfs combinations, it'll instead accept `bootfs` as the default boot entry without us entering the pool decryption passphrase.
Upon loading into a given dataset ZFSBootMenu will attempt to auto-load the matching decryption key. In our setup this will fail because we purposely stored the encryption key inside our `zpool/root/archlinux` dataset. ZFSBootMenu will prompt us to type in the decryption key. Upon loading into a given dataset ZFSBootMenu will attempt to auto-load the matching decryption key. In our setup this will fail because we purposely stored the encryption key inside our `zpool/root/archlinux` dataset. ZFSBootMenu will prompt us to type in the decryption key.
@@ -91,9 +93,9 @@ Lastly ZFSBootMenu loads our OS' kernel and initramfs combination via `kexec`. F
## Caveats in a password change ## Caveats in a password change
ZFS differentiates between user keys - also called wrapping keys - and the master key for any given encryption root. You never interact with the master key, you only pick your personal user key. Subsequently a user key change (in our use case we perceive this simply as a password change) has zero effect on data that's already encrypted. The operation is instant and merely reencrypted the already existing master key, the so-called _wrapped_ master key. ZFS differentiates between user keys - also called wrapping keys - and the master key for any given encryption root. You never interact with the master key, you only pick your personal user key. Subsequently a user key change (in our use case we perceive this simply as a password change) has zero effect on data that's already encrypted. The operation is instant and merely reencrypts the already existing master key, the so-called _wrapped_ master key.
ZFS generates the master key exactly once when you enable encryption on a dataset - technically when it becomes an encryption root. Among other inputs it uses your user key to encrypt (to _wrap_) the master key. So when you change your user key it just means that the master key stays exactly the same and only the encrypted (_wrapped_) key changes. ZFS generates the master key exactly once when you enable encryption on a dataset - technically when it becomes an encryption root. Among other inputs it uses your user key to encrypt (to _wrap_) the master key. When you change your user key it just means that the master key stays exactly the same and only the encrypted (_wrapped_) key changes.
`man 8 zfs-change-key` from `zfs-utils` version 2.1.9 adds: `man 8 zfs-change-key` from `zfs-utils` version 2.1.9 adds:
> If the user's key is compromised, `zfs change-key` does not necessarily protect existing or newly-written data from attack. Newly-written data will continue to be encrypted with the same master key as the existing data. The master key is compromised if an attacker obtains a user key and the corresponding wrapped master key. Currently, `zfs change-key` does not overwrite the previous wrapped master key on disk, so it is accessible via forensic analysis for an indeterminate length of time. > If the user's key is compromised, `zfs change-key` does not necessarily protect existing or newly-written data from attack. Newly-written data will continue to be encrypted with the same master key as the existing data. The master key is compromised if an attacker obtains a user key and the corresponding wrapped master key. Currently, `zfs change-key` does not overwrite the previous wrapped master key on disk, so it is accessible via forensic analysis for an indeterminate length of time.
@@ -110,6 +112,7 @@ In order to generate a new master key after you've changed your user key as ment
1. Change user key 1. Change user key
- Update `/etc/zfs/zpool.key` - Update `/etc/zfs/zpool.key`
- Update zpool with new key via `zfs change-key -l zpool`
- Generate new initramfs with `mkinitcpio -P` - Generate new initramfs with `mkinitcpio -P`
1. Create a snapshot from current system dataset 1. Create a snapshot from current system dataset
``` ```
@@ -140,19 +143,29 @@ In order to generate a new master key after you've changed your user key as ment
- We `zfs receive -F` destroying any target snapshots and file systems beyond the snapshot we're transferring. In this example the target `zpool/root/archlinux-frn` doesn't even exist so `-F` isn't necessary to clean anything up. It's just good practice. - We `zfs receive -F` destroying any target snapshots and file systems beyond the snapshot we're transferring. In this example the target `zpool/root/archlinux-frn` doesn't even exist so `-F` isn't necessary to clean anything up. It's just good practice.
- With `-v` we get verbose progress output - With `-v` we get verbose progress output
- Argument `-u` makes sure the dataset does not get mounted after transfer. ZFS would mount it into `/` which wouldn't be helpful since we're currently using that filesystem ourselves. - Argument `-u` makes sure the dataset does not get mounted after transfer. ZFS would mount it into `/` which wouldn't be helpful since we're currently using that filesystem ourselves.
- We set encryption properties `keyformat`, `keylocation` and most importantly `encryption`. The latter will turn our transferred dataset into its own `encryptionroot` which in turn generates a new master key. The auto-generated new master key gets wrapped with our updated passphrase in `keylocation`. This basically rekeys all data on our pool during transfer. - We set encryption properties `keyformat`, `keylocation` and most importantly `encryption`. The latter will turn our transferred dataset into its own `encryptionroot` which in turn generates a new master key. The auto-generated new master key gets wrapped with our updated passphrase in `keylocation`. This basically reencrypts all data in this dataset during transfer.
- We set `mountpoint` and `canmount` as well as a `org.zfsbootmenu:commandline` as we would for any new system dataset. - We set `mountpoint` and `canmount` as well as a `org.zfsbootmenu:commandline` as we would for any new system dataset.
1. Change zpool's `bootfs` property to new system dataset 1. Change zpool's `bootfs` property to new system dataset
``` ```
zpool set bootfs=zpool/root/archlinux-frn zpool zpool set bootfs=zpool/root/archlinux-frn zpool
``` ```
1. Boot into new system dataset 1. Boot into new system dataset
1. Update the new system dataset's `encryptionroot` by letting it inherit key data from its parent: 1. After reboot and now that you're in the new system dataset change its `encryptionroot` by letting it inherit data from its parent:
``` ```
zfs change-key -i -l zpool/root/archlinux-frn zfs change-key -i -l zpool/root/archlinux-frn
``` ```
The parent `zpool/root` is inheriting this property from `zpool` which will make sure that `zpool/root/archlinux-frn` essentially gets its key now from `zpool`. Both `zpool/root/archlinux-frn` and `zpool` use the same exact `keylocation` with identical content. This operation is instant. The parent `zpool/root` is inheriting this property from `zpool` which will make sure that `zpool/root/archlinux-frn` essentially gets its key now from `zpool`. Both `zpool/root/archlinux-frn` and `zpool` use the same exact `keylocation` with identical content. This operation is instant.
## Finishing touches
Just to confirm that the master key has changed run this commands. It takes a moment to output data:
```
zfs send --raw zpool/root/archlinux-frn@rekey | zstream dump | sed -n -e '/crypt_keydata/,/end crypt/p; /END/q'
```
Repeat for source dataset `zpool/root/archlinux-sxu@rekey`. You're particularly interested in parameters `DSL_CRYPTO_MASTER_KEY_1` and the initialization vector `DSL_CRYPTO_IV`. Notice that they differ between old and new dataset confirming that your new dataset has a new master key.
Optionally you may want to clean up: Optionally you may want to clean up:
1. In newly keyed/reencrypted system dataset destroy its snapshot 1. In newly keyed/reencrypted system dataset destroy its snapshot