The following 3 patches allow eCryptfs to use the GCM cipher mode to provide integrity protection as well as confidentiality for files. This mode of operation is optional, and CBC is still the default. Files encrypted in CBC mode by eCryptfs with the patches applied should be byte for byte compatible with files created by eCryptfs in CBC mode without these patches. Additionally, unpatched versions of eCryptfs will refuse to open files encrypted using GCM mode. The cipher mode is stored in the header, so CBC mode files and GCM mode files can be mixed in a single eCryptfs mount. A new mount option, ecryptfs_cipher_mode, has been added to allow users to specify which mode of operation to use for new files, which defaults to CBC mode. Existing files will have their mode of operation preserved. Differences from last RFC patch ------------------------------- We sorted out our problems regarding truncation, and cleaned up some of our code in the process. The test suite now shows all tests passing (on ext4), both in CBC mode and GCM mode. We updated the test suite to allow passing arbitrary options to mount so we could test this, and changes are at https://code.launchpad.net/~zmanji/ecryptfs/1270455/+merge/202197 It was pointed out to us that GCM is a stream cipher mode of operation, and that we were reusing the same key/IV across multiple encryptions. As such, we have made some changes that apply when GCM mode is in use. In CBC mode, the IV for an extent is derived from the root IV stored in the file header and the extent offset, and does not change for the lifetime of the file. Doing this with GCM would allow an attacker with access to only ciphertext to discover diffs by XORing new and old versions of an extent, because the keystream would be the same for both versions. We now store IVs for each extent using the metadata extent mechanism we are using to store auth tags. When we read an extent in GCM mode, we retrieve the IV and auth tag from the appropriate metadata extent and pass them to the decryption function. When an extent is written, we need to use a new IV, so we generate one via get_random_bytes() and store that with the auth tag we get back from the encryption function. This ensures that each new version of an extent that we write will have been encrypted with a different IV, and thus a new keystream. One important note is that this will use up some bytes from the entropy pool when get_random_bytes() is called. I could not think of a way to get unpredictable IVs safely without doing this. The reason for not doing something like newIV=hash(oldIV), or even newIV = HMAC(oldIV, secretIVGeneratingKey) is that an attacker could try inserting an old IV into the file to get a next IV that they already know, and may have seen data encrypted under. With get_random_bytes(), the next IV should be as unpredictable as /dev/urandom, and is independent of the file which the attacker may have modified. To recap: when using GCM mode, eCryptfs with our patches does not derive extent IVs from the file's root IV, but generates a new one from the entropy pool on each write, and stores it alongside the auth tag for that data extent in the metadata extents that are present when using GCM mode.
Attachment:
signature.asc
Description: OpenPGP digital signature