Native encryption in zfsonlinux (See issue #494)
The change incorporates 2 major pieces:
The first feature is a keystore that manages wrapping and encryption keys for encrypted datasets. The commands are similar to that of Solaris but with a few key enhancements to make it more predictable, more consistent, and require less manual maintenance. It is fully integrated with the existing zfs create functions and zfs clone functions. It also exposes a new set of commands via zfs key for managing the keystore. For more info on the issues with the Solaris implementation see my comments here and here. The keystore operates on a few rules.
- All wrapping keys are 32 bytes (256 bits), even for 128 and 192 bit encryption types.
- Encryption must be specified at dataset creation time.
- Specifying a keysource while creating a dataset causes the dataset to become the root of an encryption tree.
- All members of an encryption tree share the same wrapping key.
- Each dataset can have up to 1 keychain (if it is encrypted) that is not shared with anybody.
The second feature is the actual data and metadata encryption. All user data in an encrypted dataset is stored encrypted on-disk. User-provided metadata is also encrypted, but metadata structures have been left plain so that scrubbing and resilvering still works without the keys loaded. The design was originallly inspired by this article but has been changed fairly significantly since.
Implementation details that should be looked at
- Encrypting data going to disk requires creating a
key_mapping_tduringdsl_dataset_tryown(). I added a flag to this function for code that wishes to own the dataset, but that does not require encrypted data, such as the scrub functions. I did my best to confirm that all owners set this flag correctly, but someone should confirm them, just to be sure. zfs sendandzfs recvdo not currently do anything special with regards to encryption. The format of the send file has not changed and zfs send requires the keys to be loaded in order to work. At some point there should probably be a way to do raw sends.- I altered the prototype of
lzc_create() and lzc_clone()to support hidden arguments. I understand that the purpose of libzfs_core is to have a stable api interacting with the ZFS ioctls. However, these functions need to accept wrapping keys separately from the rest of their parameters because they need to use the (new) hidden_args framework to support hiding arguments from the logs. Without this, the wrapping keys would get printed to the zpool history.
EDIT 5/4/16: Updated to reflect the current state of the PR
EDIT 1/3/17: Updated to reflect the current state of the PR