How to Manage ZFS Data Encryption
How to encrypt data in a ZFS file system and how to manage data encryption for the file system or storage pool.
Oracle Solaris 11 provides transparent data encryption functionality to ZFS. All data and file system metadata (such as ownership, access control lists, quota information, and so on) are encrypted when stored persistently in the ZFS pool.
A ZFS pool can support a mix of encrypted and unencrypted ZFS data sets (file systems and ZVOLs). Data encryption is completely transparent to applications and other Oracle Solaris file services, such as NFS or CIFS. Since encryption is a first-class feature of ZFS, we are able to support compression, encryption, and deduplication together. Encryption key management for encrypted data sets can be delegated to users, Oracle Solaris Zones, or both. Oracle Solaris with ZFS encryption provides a very flexible system for securing data at rest, and it doesn't require any application changes or qualification.
ZFS makes it easy to encrypt data and manage data encryption. You can have both encrypted and unencrypted file systems in the same storage pool. You can also use different encryption keys for different systems, and you can manage encryption either locally or remotely. This article shows you how.
About ZFS Data Encryption
The encryption and key management policy for a ZFS file system is controlled via ZFS properties, and the normal ZFS inheritance rules apply. This makes it very easy to set a policy at a given point in the file system hierarchy and have it be inherited automatically. Administrators (or authorized users) manage one or more master wrapping keys for the encrypted data sets in a storage pool.
A very simple example of using ZFS encryption is as follows:
# zfs create -o encryption=on rpool/export/project Enter passphrase for 'rpool/export/project': Enter again: # zfs create rpool/export/project/A # zfs create rpool/export/project/A/design # zfs create rpool/export/project/B
In this simple case, we are using a passphrase that is interactively requested; later we will discuss other choices for managing the wrapping keys, many of which will be more appropriate for enterprise deployments. Note that file systems created below project did not prompt for a passphrase because ZFS file systems automatically inherit the wrapping key and encryption property value from the parent file system unless told otherwise.
Managing Encryption Keys
When we create an encrypted file system with ZFS, the system creates a new (randomly generated) data encryption key. The administrator never has access to the data encryption keys. Instead the administrator manages the wrapping key.
Wrapping keys are AES keys of 128,192,256 bits. They are used to decrypt the actual data encryption keys for a data set. The wrapping key can be changed at any time, even while the data set is mounted and shared.
The wrapping key can come from a number of different places depending on what type of encryption and key management policy is desired for the system. ZFS can provide for both local and centralized key management as well as the delegation of wrapping key changes and changes of the key type.
How to Manage Encryption Keys Locally
As we already saw in the first simple example of enabling encryption, if you specify no key management policy, ZFS will prompt interactively for a passphrase. This probably isn't ideal in most data center deployments, so instead we need to get the key via noninteractive means from somewhere else. The wrapping key can be either a passphrase or a raw AES key. The simplest noninteractive method is to store the wrapping key or passphrase in a file and tell ZFS what file to look in for that key. If you use this method, it is assumed that the other file system is sufficiently secure by other means, such as being on a removable disk. The wrapping key is needed only at the time the ZFS file system is initially mounted after system boot, so the removable media can be removed later if required.
# zfs create -o encryption=on -o keysource=raw,file:///media/stick/mykey tank/project/A # zfs create -o encryption=on -o keysource=passphrase,file:///media/stick/passkey tank/project/B
In the examples above, the raw key file and the passphrase file must already exist. The keysource property is how we specify the format and location of the key. Note that if we are using a file, it must be specified as a file:// style URI; the reason for that will be clearer later.
To provide some additional protection for the wrapping keys, it is also possible to store the wrapping keys in a secure keystore that is accessible from the Oracle Solaris Cryptographic Framework using the PKCS#11 API. Oracle Solaris provides a local encrypted keystore via softtoken; a hardware security module that can store AES keys can also be used.
# pktool genkey keystore=pkcs11 keytype=aes keylen=128 label=mykey Enter PIN for Sun Software PKCS#11 softtoken: # zfs create -o encryption=on -o keysource=raw,pkcs11:object=mykey tank/project/C Enter PKCS#11 token PIN for 'tank/project/C':
In the example above, we created an AES key in the default softtoken keystore for the user. This keystore requires authentication to create and use keys stored in it, so we were prompted for the keystore PIN (it is really a passphrase, but PKCS#11 terminology uses the word PIN for legacy reasons). The syntax of the PKCS#11 URI that is used with the keysource property allows for specifying a path to the PIN file. Using this method ensures that the actual wrapping key is encrypted and protected in the PKCS#11 keystore.
How to Manage Encryption Keys Remotely
In some cases, it might be more desirable to have a centralized key management system that provides for the unattended reboot of servers with ZFS-encrypted file systems and also for centralized control over a wrapping key's lifetime. ZFS provides two methods of remote key management.
The first is to use a remote key management system, such as the Oracle Key Manager system, that is made accessible to Oracle Solaris via a PKCS#11 token. In this case, the syntax looks very similar to the previous example with the local softtoken except the key material is actually stored and managed on the remote system.
The other method of providing centralized key management is via Web services. ZFS can get the wrapping key or passphrase from any Web service that supports a simple GET request on a URI, for example:
# zfs create -o encryption=on -o keysource=raw,https://keys.example.com/mykey tank/project/R
The Web service can be accessed over HTTP or HTTPS. ZFS uses libcurl and OpenSSL to access the Web service; this requires that the X.509 certificate used by the Web service for SSL/TLS be signed by one of the known CA certificates or that it be a known self-signed certificate. Oracle Solaris allows augmenting the standard list of certificates as follows:
# cp myservercert.pem /etc/certs/CA/ # svcadm refresh ca-certificates
How to Change Wrapping Keys
The wrapping key can be changed for a data set hierarchy at any time after it has initially been created or mounted. Changing the wrapping key doesn't re-encrypt any data on disk and it is done atomically for all data sets that inherit the wrapping key. It is also possible to change the format and location of the wrapping key at the same time its value is changed. This allows for online migration between local and remote key management even after there is data in the file system. Let's go back to our original simple example and change the key:
$ zfs key -c rpool/export/project Enter new passphrase for 'rpool/export/project':
Note that ZFS did not prompt for the current passphrase, because the file system is already mounted and ZFS knows the wrapping key. It also knows the user who is authorized to change the wrapping key.
How to Change Data Encryption Keys
In addition to being able to change the wrapping key (which is used only for encrypting the data encryption keys), ZFS provides the ability to start using new data encryption keys for newly written data at any point in time. This allows for managing both wrapping keys and data encryption keys in a way that is compliant with NIST SP800-57 key lifetime.
# zfs key -K tank/project/A # zfs clone -K tank/project/C@snap-1 tank/project/D
In the first example above, we change the data encryption key for all new data that is written after this point in time for the tank/project/A file system. In the second example above, we create a new file system by cloning an existing snapshot, but we explicitly request that all data that is unique to the clone be written with a new data encryption key.
The time of the last data encryption key change is stored in the read-only rekeydate property:
$ zfs get creation,rekeydate tank/project/A NAME PROPERTY VALUE SOURCE tank/project/A creation Wed Mar 23 19:53 2020 - tank/project/A rekeydate Wed May 6 10:46 2020 local
How to Delegate Key Management
The ZFS delegation system provides a mechanism for allowing users to perform certain actions on ZFS data sets. There are separate ZFS delegations for using and changing keys as well as changing the format and location of the wrapping key: key, keychange, and keysource.
Using combinations of these delegations, is it possible to build a key escrow system where certain users are authorized to know and use the wrapping key for a data set but not to change the value or location. Other users might be authorized to change the value of a wrapping key but not to use it and they might or might not be authorized to change its location (for example, between local and remote key management styles).
# zfs allow -u bob keychange tank/project/C
The example above allows the user bob to change the wrapping key value for the data set and its children but not to change the keysource property. Note also in this case that user bob can't actually mount the ZFS data set after boot nor can he force unload the data set and its keys. The root user (and the system boot itself) has all ZFS delegations.
How to Choose the Encryption Property Value
The on value for the ZFS encryption property maps to aes-128-ccm, because that is the fastest of the six available modes of encryption currently provided and it is believed to provide sufficient security for many deployments. Depending on the file system or ZVOL workload, you might not be able to notice (or you might not care, if you do notice) the difference between the AES key lengths and modes.
On Oracle's SPARC processors and on Intel processors with the AES-NI extension, all encryption for ZFS is hardware accelerated. SPARC processors also accelerate the SHA256 checksum that is always used for data and metadata when encryption is enabled on a ZFS data set.
Both AES CCM and AES GCM are provided so that if one turns out to have flaws—and modes of an encryption algorithm sometimes do have flaws independent of the base algorithm—the other will still be available for use safely. One reason you might want to select aes-128-gcm rather than aes-128-ccm is that GCM is one of the modes for AES in NSA Suite B. ZFS encryption was designed and implemented to be extensible to new algorithm/mode combinations for data encryption and key wrapping.
The other reason to choose between CCM and GCM modes is that only the CCM modes (aes-128-ccm, aes-192-ccm, and aes-256-ccm) allow for combining ZFS encryption and deduplication.
Encrypted data will be deduplicated only within a file system or a clone of that file system, and only if the data encryption keys are not changed (that is, if
zfs key -K and
zfs clone -K are not used).
Much more can be done with ZFS encryption, including combining encryption, compression, and data deduplication. ZFS encryption is fully integrated into the ZFS storage system and administration tools. It is even possible to provide completely transparent encryption for Oracle Solaris Zones.
For more information on ZFS and encryption please see the following resources:
Revision 1.0, 07/23/2012
Revision 1.1, 06/28/2020