Tuesday, January 12, 2016

Solaris 11.2: ZFS Encryption

Oracle Solaris 11 supports encryption on ZFS in a native way to protect critical data without depending on external programs, and it is integrated with the Oracle Solaris Cryptographic Framework, which in turn makes encryption easier and faster by providing several symmetric and asymmetric algorithms for encrypting files and entire file systems. Moreover, when ZFS encryption is enabled on a newly created file system, encryption is automatically inherited by any descendant file systems, for added flexibility, encrypted file systems can live with unencrypted file systems in the same pool.
The following are the supported symmetric algorithms and their respective mechanisms:
root@solaris11-1:~# encrypt -l
Algorithm       Keysize:  Min   Max (bits)
------------------------------------------
aes                       128   256
arcfour                     8  2048
des                        64    64
3des                      128   192

root@solaris11-1:~# cryptoadm list -m
provider=aes
aes: CKM_AES_ECB,CKM_AES_CBC,CKM_AES_CTR,CKM_AES_CCM,CKM_AES_GCM,CKM_AES_GMAC,CKM_AES_CFB128,CKM_AES_XTS,CKM_AES_XCBC_MAC
root@solaris11-1:~#

From the available options, the 128-bit AES CCM mode is the
default. In case we are using deduplication on some
file systems, be aware that a CCM mode is required when combining both
encryption and deduplication.
There are several ways to use ZFS encryption on a system running
Oracle Solaris 11. Let's explore them.
First Way
We can encrypt a single file or a whole file system using the same
algorithms. The following shows an example for a single file:
root@solaris11-2:/tmpcp /etc/hosts /tmp/
root@solaris11-2:/tmp# cd /tmp/
root@solaris11-2:/tmp# encrypt -a aes -i /tmp/hosts -o /tmp/hosts.aes
Enter passphrase:
Re-enter passphrase:

root@solaris11-2:/tmp# file hosts*
hosts:     ascii text
hosts.aes: data

I entered the password oracle123! and everything worked fine. As we can see, the file was encrypted.
If we want to decrypt the file, we can use the following command:
root@solaris11-2:/tmp# decrypt -a aes -i
/tmp/hosts.aes -o /tmp/hosts.decrypted
Enter passphrase:

root@solaris11-2:/tmp# file hosts*
hosts:           ascii text
hosts.aes:       data
hosts.decryptedascii text

root@solaris11-2:/tmp# more hosts.decrypted
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# Internet host table
#
::1 solaris11-1 localhost
127.0.0.1 solaris11-1 solaris11.example.com localhost loghost
192.168.1.105 solaris11-1.example.com solaris11-1
192.168.1.102 solaris11-2.example.com solaris11-2
192.168.1.250 freenas.example.com freenas
root@solaris11-1:/tmp#

That was easy. We could do something similar to the following to encrypt the entire file system:
root@solaris11-2:~# zpool create pool_encr c8t3d0
root@solaris11-2:~# zfs create -o encryption=on pool_encr/fs_encr_1
Enter passphrase for 'pool_encr/fs_encr_1':
Enter again:
root@solaris11-2:~#
 
The default form of ZFS encryption is to prompt for a passphrase, as indicated in the example above.
I entered the same passphrase (oracle123!). If we create a new descendant file system, the passphrase is inherited from the parent file system.
The first thing we must be aware of is that it's not possible to decrypt a file system as we did for a single file. Another difference is we had to enter the passphrase in an interactive way. There's no problem doing that for some file systems, but entering the passphrase interactively can be real problem when deploying in big environments.
A better alternative would be to store the passphrase outside of our computer:
root@solaris11-1:/# zpool destroy pool_encr         
root@solaris11-1:/# zpool create pool_encr c8t3d0
root@solaris11-1:/# echo "oracle123" >
/media/ORA_PENDRIV/oracle_encryption_key
root@solaris11-1:/# more /media/ORA_PENDRIV/oracle_encryption_key oracle123
root@solaris11-1:/# zfs create -o encryption=on \
-o keysource=passphrase,file:///media/ORA_PENDRIV/oracle_encryption_key pool_encr/fs_encr_2
 
In this case, we also need to protect our removable device (pen drive), because the passphrase is there. Note that the file system is mounted during booting only if the system has access to the removable device, but the lack of any encryption key does not prevent the system from booting.
Important: As a last reminder, Oracle Solaris 11 cannot decrypt an encrypted file system the way it can decrypt an encrypted single file.

Second Way
As an alternative, we can use a wrapping key. A wrapping key is used to encrypt the real (symmetric) key that we would use to perform the encryption. In other words, when using a wrapping key, we store the symmetric key in the keystore, encrypt it using the wrapping key and then—when we need the symmetric key for encrypting a file system—the key is accessed and decrypted by using the wrapping key in a noninteractive mode.
The wrapping key could be a passphrase (which is similar to a password) or a raw key, and it's necessary only when the file system is initially mounted.
Different from the first method, for providing further protection, we could store the wrapping key inside the Oracle Solaris Cryptographic Framework, which is a kind of keystore encrypted by a softtoken. This keystore is protected by an initial passphrase (changeme) that we have to alter:

root@solaris11-2:/# pktool setpin
Enter token passphrase: changeme
Create new passphrase: borges123
Re-enter new passphrase: borges123
Passphrase changed.
root@solaris11-2:/#
The available tokens can be viewed by executing the following command: 
root@solaris11-2:~# pktool tokens
Flags: L=Login required  I=Initialized  X=User PIN expired  S=SO PIN expired
Slot ID
Slot
 Name
Token Name                        Flags    
-------  ---------                    ----------                        -----    
1        Sun Crypto Softtoken         Sun
Software PKCS#11 softtoken    LI
 
 
Let's create and then list some keys:
root@solaris11-2:~# pktool genkey keytype=aes keylen=192 label=otn1
Enter PIN for Sun Software PKCS#11 softtoken: borges123

root@solaris11-2:~# pktool genkey keytype=aes keylen=256 label=otn2
Enter PIN for Sun Software PKCS#11 softtoken:

root@solaris11-2:~# pktool list objtype=key
Enter PIN for Sun Software PKCS#11 softtoken:
Found 2 symmetric keys.
Key #1 - AES:  otn1 (192 bits)
Key #2 - AES:  otn2 (256 bits)

As you can see, the first pktool genkey command created a new key named otn1 using
the AES algorithm with 192 bits, and the second 
pktool genkey command created a key named otn2 using the AES algorithm with 256 bits.
We can repeat the same procedure to encrypt a file, but using the Oracle Solaris Cryptographic Framework this time:
root@solaris11-2:~# cp /etc/hosts /tmp/
root@solaris11-2:~# cd /tmp/
root@solaris11-2:/tmp# encrypt -a aes -K otn2 -i /tmp/hosts -o /tmp/hosts.aes256
Enter PIN for Sun Software PKCS#11 softtoken: borges123


root@solaris11-2:/tmp# file /tmp/hosts*
/tmp/hosts:         ascii text
/tmp/hosts.aes256:  data
 
We've done it! Nobody knows what the real password is, only that it's stored in the Oracle Solaris 11 keystore. Encrypting the example file (a copy of /etc/hosts) was done using the passphrase (borges123).
That's the nice thing: we don’t know the symmetric key itself because we need to enter only the PIN (passphrase) of the keystore.
   
From here, we could decrypt the file using the same method:
root@solaris11-2:/tmp# decrypt -a aes -K otn2 -i /tmp/hosts.aes256 \
-o /tmp/hosts.decrypted
Enter PIN for Sun Software PKCS#11 softtoken:

root@solaris11-2:/tmp# file /tmp/host*
/tmp/hosts:            ascii text
/tmp/hosts.aes256:     data
/tmp/hosts.decrypted:  ascii text
 
 
Before proceeding with file system encryption, it's important to say that the key could be stored outside of the keystore.
In this case, the key administration is our responsibility:
root@solaris11-2:/tmppktool genkey keystore=file
outkey=/mykeys/otn3 \
keytype=aes keylen=256
root@solaris11-2:/tmpls -al /mykeys/otn3
-r--------   1 root     root          32 Dec  9 19:14 /mykeys/otn3
root@solaris11-2:/tmp# file /mykeys/otn3
/mykeys/otn3:    data
root@solaris11-2:/tmppktool list objtype=key
Enter PIN for Sun Software PKCS#11 softtoken: borges123
Found 2 symmetric keys.
Key #1 - AES:  otn1 (192 bits)
Key #2 - AES:  otn2 (256 bits)
root@solaris11-2:/tmp#
 
As we can see from the output, the key isn't stored in the Oracle Solaris 11 keystore (softtoken).
To encrypt an entire file system using the PKCS#11 method (softtoken), do the following:
root@solaris11-2:~# zpool create softtoken_pool c8t4d0

root@solaris11-2:~# zfs create -o encryption=aes-256-ccm \
-o keysource=raw,pkcs11:object=otn2 softtoken_pool/fs_softtoken_1
Enter PKCS#11 token PIN for 'softtoken_pool/fs_softtoken_1':
borges123

root@solaris11-2:~# zfs list -r softtoken_pool
NAME USED  AVAIL  REFER MOUNTPOINT
softtoken_pool                 140K  3.91G
32K  /softtoken_pool 
softtoken_pool/fs_softtoken_1 33K  3.91G    33K /softtoken_pool/fs_softtoken_1
Cool. The symmetric key is stored inside the PKCS#11 keystore. Then, the zfs create command used it to create and encrypt thesofttoken_pool/fs_softtoken_1 filesystem.
It's a nice exercise to collect further information about the file system encryption:
root@solaris11-2:~# zfs get encryption softtoken_pool/fs_softtoken_1
NAME PROPERTY   VALUE        SOURCE
softtoken_pool/fs_softtoken_1  encryption  aes-256-ccm local

root@solaris11-2:~# zfs get keysource softtoken_pool/fs_softtoken_1
NAME PROPERTY  VALUE                   SOURCE
softtoken_pool/fs_softtoken_1  keysource  raw,pkcs11:object=otn2  local

To make a new file system, but using another key, is
straightforward:
root@solaris11-2:~# zfs create -o encryption=aes-192-ccm \
-o keysource=raw,pkcs11:object=otn1
softtoken_pool/fs_softtoken_2
Enter PKCS#11 token PIN for 'softtoken_pool/fs_softtoken_2':
borges123

root@solaris11-2:~# zfs get encryption softtoken_pool/fs_softtoken_2
NAME      PROPERTY   VALUE        SOURCE
softtoken_pool/fs_softtoken_2  encryption  aes-192-ccm local

root@solaris11-2:~# zfs get keysource softtoken_pool/fs_softtoken_2
NAME      PROPERTY  VALUE                   SOURCE
softtoken_pool/fs_softtoken_2  keysource raw,pkcs11:object=otn1  local

root@solaris11-2:~# zfs list -r softtoken_pool
NAME USED  AVAIL  REFER MOUNTPOINT
softtoken_pool 194K  3.91G 33K  /softtoken_pool
softtoken_pool/fs_softtoken_1
33K  3.91G    33K /softtoken_pool/fs_softtoken_1
softtoken_pool/fs_softtoken_2
33K  3.91G    33K /softtoken_pool/fs_softtoken_2

Finally, it's possible to encrypt the entire pool (not just some of the file systems):
root@solaris11-2:~# zpool create -o encryption=on \
-o keysource=raw,pkcs11:object=otn1 softtoken_pool_2 c8t5d0
Enter PKCS#11 token PIN for 'softtoken_pool_2': borges123

root@solaris11-2:~# zfs create softtoken_pool_2/fs_softtoken_3
root@solaris11-2:~# zfs create softtoken_pool_2/fs_softtoken_4

This is very interesting: the encrypted pool was created and the pin number (that is, the passphrase for the keystore) was required, but when we created the descendant
file systems (
fs_softtoken_3 and fs_softtoken_4) no passphrase is prompted for because descendant file systems inherit the parent file system’s encryption key. To verify this, run the following command:

root@solaris11-2:~# zfs get encryption,keysource softtoken_pool_2/fs_softtoken_3 softtoken_pool_2/fs_softtoken_3
NAME PROPERTY    VALUE                   SOURCE
softtoken_pool_2/fs_softtoken_3  encryption on             inherited from softtoken_pool_2
softtoken_pool_2/fs_softtoken_3  keysource   raw,pkcs11:object=otn1  inherited from softtoken_pool_2
softtoken_pool_2/fs_softtoken_3  encryption on                inherited from softtoken_pool_2
softtoken_pool_2/fs_softtoken_3  keysource   raw,pkcs11:object=otn1  inherited from softtoken_pool_2

Amazing. Exactly as we had predicted.

No comments:

Post a Comment