1375 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			1375 lines
		
	
	
		
			61 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| =====================================
 | |
| Filesystem-level encryption (fscrypt)
 | |
| =====================================
 | |
| 
 | |
| Introduction
 | |
| ============
 | |
| 
 | |
| fscrypt is a library which filesystems can hook into to support
 | |
| transparent encryption of files and directories.
 | |
| 
 | |
| Note: "fscrypt" in this document refers to the kernel-level portion,
 | |
| implemented in ``fs/crypto/``, as opposed to the userspace tool
 | |
| `fscrypt <https://github.com/google/fscrypt>`_.  This document only
 | |
| covers the kernel-level portion.  For command-line examples of how to
 | |
| use encryption, see the documentation for the userspace tool `fscrypt
 | |
| <https://github.com/google/fscrypt>`_.  Also, it is recommended to use
 | |
| the fscrypt userspace tool, or other existing userspace tools such as
 | |
| `fscryptctl <https://github.com/google/fscryptctl>`_ or `Android's key
 | |
| management system
 | |
| <https://source.android.com/security/encryption/file-based>`_, over
 | |
| using the kernel's API directly.  Using existing tools reduces the
 | |
| chance of introducing your own security bugs.  (Nevertheless, for
 | |
| completeness this documentation covers the kernel's API anyway.)
 | |
| 
 | |
| Unlike dm-crypt, fscrypt operates at the filesystem level rather than
 | |
| at the block device level.  This allows it to encrypt different files
 | |
| with different keys and to have unencrypted files on the same
 | |
| filesystem.  This is useful for multi-user systems where each user's
 | |
| data-at-rest needs to be cryptographically isolated from the others.
 | |
| However, except for filenames, fscrypt does not encrypt filesystem
 | |
| metadata.
 | |
| 
 | |
| Unlike eCryptfs, which is a stacked filesystem, fscrypt is integrated
 | |
| directly into supported filesystems --- currently ext4, F2FS, and
 | |
| UBIFS.  This allows encrypted files to be read and written without
 | |
| caching both the decrypted and encrypted pages in the pagecache,
 | |
| thereby nearly halving the memory used and bringing it in line with
 | |
| unencrypted files.  Similarly, half as many dentries and inodes are
 | |
| needed.  eCryptfs also limits encrypted filenames to 143 bytes,
 | |
| causing application compatibility issues; fscrypt allows the full 255
 | |
| bytes (NAME_MAX).  Finally, unlike eCryptfs, the fscrypt API can be
 | |
| used by unprivileged users, with no need to mount anything.
 | |
| 
 | |
| fscrypt does not support encrypting files in-place.  Instead, it
 | |
| supports marking an empty directory as encrypted.  Then, after
 | |
| userspace provides the key, all regular files, directories, and
 | |
| symbolic links created in that directory tree are transparently
 | |
| encrypted.
 | |
| 
 | |
| Threat model
 | |
| ============
 | |
| 
 | |
| Offline attacks
 | |
| ---------------
 | |
| 
 | |
| Provided that userspace chooses a strong encryption key, fscrypt
 | |
| protects the confidentiality of file contents and filenames in the
 | |
| event of a single point-in-time permanent offline compromise of the
 | |
| block device content.  fscrypt does not protect the confidentiality of
 | |
| non-filename metadata, e.g. file sizes, file permissions, file
 | |
| timestamps, and extended attributes.  Also, the existence and location
 | |
| of holes (unallocated blocks which logically contain all zeroes) in
 | |
| files is not protected.
 | |
| 
 | |
| fscrypt is not guaranteed to protect confidentiality or authenticity
 | |
| if an attacker is able to manipulate the filesystem offline prior to
 | |
| an authorized user later accessing the filesystem.
 | |
| 
 | |
| Online attacks
 | |
| --------------
 | |
| 
 | |
| fscrypt (and storage encryption in general) can only provide limited
 | |
| protection, if any at all, against online attacks.  In detail:
 | |
| 
 | |
| Side-channel attacks
 | |
| ~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| fscrypt is only resistant to side-channel attacks, such as timing or
 | |
| electromagnetic attacks, to the extent that the underlying Linux
 | |
| Cryptographic API algorithms or inline encryption hardware are.  If a
 | |
| vulnerable algorithm is used, such as a table-based implementation of
 | |
| AES, it may be possible for an attacker to mount a side channel attack
 | |
| against the online system.  Side channel attacks may also be mounted
 | |
| against applications consuming decrypted data.
 | |
| 
 | |
| Unauthorized file access
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| After an encryption key has been added, fscrypt does not hide the
 | |
| plaintext file contents or filenames from other users on the same
 | |
| system.  Instead, existing access control mechanisms such as file mode
 | |
| bits, POSIX ACLs, LSMs, or namespaces should be used for this purpose.
 | |
| 
 | |
| (For the reasoning behind this, understand that while the key is
 | |
| added, the confidentiality of the data, from the perspective of the
 | |
| system itself, is *not* protected by the mathematical properties of
 | |
| encryption but rather only by the correctness of the kernel.
 | |
| Therefore, any encryption-specific access control checks would merely
 | |
| be enforced by kernel *code* and therefore would be largely redundant
 | |
| with the wide variety of access control mechanisms already available.)
 | |
| 
 | |
| Kernel memory compromise
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| An attacker who compromises the system enough to read from arbitrary
 | |
| memory, e.g. by mounting a physical attack or by exploiting a kernel
 | |
| security vulnerability, can compromise all encryption keys that are
 | |
| currently in use.
 | |
| 
 | |
| However, fscrypt allows encryption keys to be removed from the kernel,
 | |
| which may protect them from later compromise.
 | |
| 
 | |
| In more detail, the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl (or the
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS ioctl) can wipe a master
 | |
| encryption key from kernel memory.  If it does so, it will also try to
 | |
| evict all cached inodes which had been "unlocked" using the key,
 | |
| thereby wiping their per-file keys and making them once again appear
 | |
| "locked", i.e. in ciphertext or encrypted form.
 | |
| 
 | |
| However, these ioctls have some limitations:
 | |
| 
 | |
| - Per-file keys for in-use files will *not* be removed or wiped.
 | |
|   Therefore, for maximum effect, userspace should close the relevant
 | |
|   encrypted files and directories before removing a master key, as
 | |
|   well as kill any processes whose working directory is in an affected
 | |
|   encrypted directory.
 | |
| 
 | |
| - The kernel cannot magically wipe copies of the master key(s) that
 | |
|   userspace might have as well.  Therefore, userspace must wipe all
 | |
|   copies of the master key(s) it makes as well; normally this should
 | |
|   be done immediately after FS_IOC_ADD_ENCRYPTION_KEY, without waiting
 | |
|   for FS_IOC_REMOVE_ENCRYPTION_KEY.  Naturally, the same also applies
 | |
|   to all higher levels in the key hierarchy.  Userspace should also
 | |
|   follow other security precautions such as mlock()ing memory
 | |
|   containing keys to prevent it from being swapped out.
 | |
| 
 | |
| - In general, decrypted contents and filenames in the kernel VFS
 | |
|   caches are freed but not wiped.  Therefore, portions thereof may be
 | |
|   recoverable from freed memory, even after the corresponding key(s)
 | |
|   were wiped.  To partially solve this, you can set
 | |
|   CONFIG_PAGE_POISONING=y in your kernel config and add page_poison=1
 | |
|   to your kernel command line.  However, this has a performance cost.
 | |
| 
 | |
| - Secret keys might still exist in CPU registers, in crypto
 | |
|   accelerator hardware (if used by the crypto API to implement any of
 | |
|   the algorithms), or in other places not explicitly considered here.
 | |
| 
 | |
| Limitations of v1 policies
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| v1 encryption policies have some weaknesses with respect to online
 | |
| attacks:
 | |
| 
 | |
| - There is no verification that the provided master key is correct.
 | |
|   Therefore, a malicious user can temporarily associate the wrong key
 | |
|   with another user's encrypted files to which they have read-only
 | |
|   access.  Because of filesystem caching, the wrong key will then be
 | |
|   used by the other user's accesses to those files, even if the other
 | |
|   user has the correct key in their own keyring.  This violates the
 | |
|   meaning of "read-only access".
 | |
| 
 | |
| - A compromise of a per-file key also compromises the master key from
 | |
|   which it was derived.
 | |
| 
 | |
| - Non-root users cannot securely remove encryption keys.
 | |
| 
 | |
| All the above problems are fixed with v2 encryption policies.  For
 | |
| this reason among others, it is recommended to use v2 encryption
 | |
| policies on all new encrypted directories.
 | |
| 
 | |
| Key hierarchy
 | |
| =============
 | |
| 
 | |
| Master Keys
 | |
| -----------
 | |
| 
 | |
| Each encrypted directory tree is protected by a *master key*.  Master
 | |
| keys can be up to 64 bytes long, and must be at least as long as the
 | |
| greater of the security strength of the contents and filenames
 | |
| encryption modes being used.  For example, if any AES-256 mode is
 | |
| used, the master key must be at least 256 bits, i.e. 32 bytes.  A
 | |
| stricter requirement applies if the key is used by a v1 encryption
 | |
| policy and AES-256-XTS is used; such keys must be 64 bytes.
 | |
| 
 | |
| To "unlock" an encrypted directory tree, userspace must provide the
 | |
| appropriate master key.  There can be any number of master keys, each
 | |
| of which protects any number of directory trees on any number of
 | |
| filesystems.
 | |
| 
 | |
| Master keys must be real cryptographic keys, i.e. indistinguishable
 | |
| from random bytestrings of the same length.  This implies that users
 | |
| **must not** directly use a password as a master key, zero-pad a
 | |
| shorter key, or repeat a shorter key.  Security cannot be guaranteed
 | |
| if userspace makes any such error, as the cryptographic proofs and
 | |
| analysis would no longer apply.
 | |
| 
 | |
| Instead, users should generate master keys either using a
 | |
| cryptographically secure random number generator, or by using a KDF
 | |
| (Key Derivation Function).  The kernel does not do any key stretching;
 | |
| therefore, if userspace derives the key from a low-entropy secret such
 | |
| as a passphrase, it is critical that a KDF designed for this purpose
 | |
| be used, such as scrypt, PBKDF2, or Argon2.
 | |
| 
 | |
| Key derivation function
 | |
| -----------------------
 | |
| 
 | |
| With one exception, fscrypt never uses the master key(s) for
 | |
| encryption directly.  Instead, they are only used as input to a KDF
 | |
| (Key Derivation Function) to derive the actual keys.
 | |
| 
 | |
| The KDF used for a particular master key differs depending on whether
 | |
| the key is used for v1 encryption policies or for v2 encryption
 | |
| policies.  Users **must not** use the same key for both v1 and v2
 | |
| encryption policies.  (No real-world attack is currently known on this
 | |
| specific case of key reuse, but its security cannot be guaranteed
 | |
| since the cryptographic proofs and analysis would no longer apply.)
 | |
| 
 | |
| For v1 encryption policies, the KDF only supports deriving per-file
 | |
| encryption keys.  It works by encrypting the master key with
 | |
| AES-128-ECB, using the file's 16-byte nonce as the AES key.  The
 | |
| resulting ciphertext is used as the derived key.  If the ciphertext is
 | |
| longer than needed, then it is truncated to the needed length.
 | |
| 
 | |
| For v2 encryption policies, the KDF is HKDF-SHA512.  The master key is
 | |
| passed as the "input keying material", no salt is used, and a distinct
 | |
| "application-specific information string" is used for each distinct
 | |
| key to be derived.  For example, when a per-file encryption key is
 | |
| derived, the application-specific information string is the file's
 | |
| nonce prefixed with "fscrypt\\0" and a context byte.  Different
 | |
| context bytes are used for other types of derived keys.
 | |
| 
 | |
| HKDF-SHA512 is preferred to the original AES-128-ECB based KDF because
 | |
| HKDF is more flexible, is nonreversible, and evenly distributes
 | |
| entropy from the master key.  HKDF is also standardized and widely
 | |
| used by other software, whereas the AES-128-ECB based KDF is ad-hoc.
 | |
| 
 | |
| Per-file encryption keys
 | |
| ------------------------
 | |
| 
 | |
| Since each master key can protect many files, it is necessary to
 | |
| "tweak" the encryption of each file so that the same plaintext in two
 | |
| files doesn't map to the same ciphertext, or vice versa.  In most
 | |
| cases, fscrypt does this by deriving per-file keys.  When a new
 | |
| encrypted inode (regular file, directory, or symlink) is created,
 | |
| fscrypt randomly generates a 16-byte nonce and stores it in the
 | |
| inode's encryption xattr.  Then, it uses a KDF (as described in `Key
 | |
| derivation function`_) to derive the file's key from the master key
 | |
| and nonce.
 | |
| 
 | |
| Key derivation was chosen over key wrapping because wrapped keys would
 | |
| require larger xattrs which would be less likely to fit in-line in the
 | |
| filesystem's inode table, and there didn't appear to be any
 | |
| significant advantages to key wrapping.  In particular, currently
 | |
| there is no requirement to support unlocking a file with multiple
 | |
| alternative master keys or to support rotating master keys.  Instead,
 | |
| the master keys may be wrapped in userspace, e.g. as is done by the
 | |
| `fscrypt <https://github.com/google/fscrypt>`_ tool.
 | |
| 
 | |
| DIRECT_KEY policies
 | |
| -------------------
 | |
| 
 | |
| The Adiantum encryption mode (see `Encryption modes and usage`_) is
 | |
| suitable for both contents and filenames encryption, and it accepts
 | |
| long IVs --- long enough to hold both an 8-byte logical block number
 | |
| and a 16-byte per-file nonce.  Also, the overhead of each Adiantum key
 | |
| is greater than that of an AES-256-XTS key.
 | |
| 
 | |
| Therefore, to improve performance and save memory, for Adiantum a
 | |
| "direct key" configuration is supported.  When the user has enabled
 | |
| this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy,
 | |
| per-file encryption keys are not used.  Instead, whenever any data
 | |
| (contents or filenames) is encrypted, the file's 16-byte nonce is
 | |
| included in the IV.  Moreover:
 | |
| 
 | |
| - For v1 encryption policies, the encryption is done directly with the
 | |
|   master key.  Because of this, users **must not** use the same master
 | |
|   key for any other purpose, even for other v1 policies.
 | |
| 
 | |
| - For v2 encryption policies, the encryption is done with a per-mode
 | |
|   key derived using the KDF.  Users may use the same master key for
 | |
|   other v2 encryption policies.
 | |
| 
 | |
| IV_INO_LBLK_64 policies
 | |
| -----------------------
 | |
| 
 | |
| When FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 is set in the fscrypt policy,
 | |
| the encryption keys are derived from the master key, encryption mode
 | |
| number, and filesystem UUID.  This normally results in all files
 | |
| protected by the same master key sharing a single contents encryption
 | |
| key and a single filenames encryption key.  To still encrypt different
 | |
| files' data differently, inode numbers are included in the IVs.
 | |
| Consequently, shrinking the filesystem may not be allowed.
 | |
| 
 | |
| This format is optimized for use with inline encryption hardware
 | |
| compliant with the UFS standard, which supports only 64 IV bits per
 | |
| I/O request and may have only a small number of keyslots.
 | |
| 
 | |
| IV_INO_LBLK_32 policies
 | |
| -----------------------
 | |
| 
 | |
| IV_INO_LBLK_32 policies work like IV_INO_LBLK_64, except that for
 | |
| IV_INO_LBLK_32, the inode number is hashed with SipHash-2-4 (where the
 | |
| SipHash key is derived from the master key) and added to the file
 | |
| logical block number mod 2^32 to produce a 32-bit IV.
 | |
| 
 | |
| This format is optimized for use with inline encryption hardware
 | |
| compliant with the eMMC v5.2 standard, which supports only 32 IV bits
 | |
| per I/O request and may have only a small number of keyslots.  This
 | |
| format results in some level of IV reuse, so it should only be used
 | |
| when necessary due to hardware limitations.
 | |
| 
 | |
| Key identifiers
 | |
| ---------------
 | |
| 
 | |
| For master keys used for v2 encryption policies, a unique 16-byte "key
 | |
| identifier" is also derived using the KDF.  This value is stored in
 | |
| the clear, since it is needed to reliably identify the key itself.
 | |
| 
 | |
| Dirhash keys
 | |
| ------------
 | |
| 
 | |
| For directories that are indexed using a secret-keyed dirhash over the
 | |
| plaintext filenames, the KDF is also used to derive a 128-bit
 | |
| SipHash-2-4 key per directory in order to hash filenames.  This works
 | |
| just like deriving a per-file encryption key, except that a different
 | |
| KDF context is used.  Currently, only casefolded ("case-insensitive")
 | |
| encrypted directories use this style of hashing.
 | |
| 
 | |
| Encryption modes and usage
 | |
| ==========================
 | |
| 
 | |
| fscrypt allows one encryption mode to be specified for file contents
 | |
| and one encryption mode to be specified for filenames.  Different
 | |
| directory trees are permitted to use different encryption modes.
 | |
| Currently, the following pairs of encryption modes are supported:
 | |
| 
 | |
| - AES-256-XTS for contents and AES-256-CTS-CBC for filenames
 | |
| - AES-128-CBC for contents and AES-128-CTS-CBC for filenames
 | |
| - Adiantum for both contents and filenames
 | |
| - AES-256-XTS for contents and AES-256-HCTR2 for filenames (v2 policies only)
 | |
| - SM4-XTS for contents and SM4-CTS-CBC for filenames (v2 policies only)
 | |
| 
 | |
| If unsure, you should use the (AES-256-XTS, AES-256-CTS-CBC) pair.
 | |
| 
 | |
| AES-128-CBC was added only for low-powered embedded devices with
 | |
| crypto accelerators such as CAAM or CESA that do not support XTS.  To
 | |
| use AES-128-CBC, CONFIG_CRYPTO_ESSIV and CONFIG_CRYPTO_SHA256 (or
 | |
| another SHA-256 implementation) must be enabled so that ESSIV can be
 | |
| used.
 | |
| 
 | |
| Adiantum is a (primarily) stream cipher-based mode that is fast even
 | |
| on CPUs without dedicated crypto instructions.  It's also a true
 | |
| wide-block mode, unlike XTS.  It can also eliminate the need to derive
 | |
| per-file encryption keys.  However, it depends on the security of two
 | |
| primitives, XChaCha12 and AES-256, rather than just one.  See the
 | |
| paper "Adiantum: length-preserving encryption for entry-level
 | |
| processors" (https://eprint.iacr.org/2018/720.pdf) for more details.
 | |
| To use Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled.  Also, fast
 | |
| implementations of ChaCha and NHPoly1305 should be enabled, e.g.
 | |
| CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM.
 | |
| 
 | |
| AES-256-HCTR2 is another true wide-block encryption mode that is intended for
 | |
| use on CPUs with dedicated crypto instructions.  AES-256-HCTR2 has the property
 | |
| that a bitflip in the plaintext changes the entire ciphertext.  This property
 | |
| makes it desirable for filename encryption since initialization vectors are
 | |
| reused within a directory.  For more details on AES-256-HCTR2, see the paper
 | |
| "Length-preserving encryption with HCTR2"
 | |
| (https://eprint.iacr.org/2021/1441.pdf).  To use AES-256-HCTR2,
 | |
| CONFIG_CRYPTO_HCTR2 must be enabled.  Also, fast implementations of XCTR and
 | |
| POLYVAL should be enabled, e.g. CRYPTO_POLYVAL_ARM64_CE and
 | |
| CRYPTO_AES_ARM64_CE_BLK for ARM64.
 | |
| 
 | |
| SM4 is a Chinese block cipher that is an alternative to AES.  It has
 | |
| not seen as much security review as AES, and it only has a 128-bit key
 | |
| size.  It may be useful in cases where its use is mandated.
 | |
| Otherwise, it should not be used.  For SM4 support to be available, it
 | |
| also needs to be enabled in the kernel crypto API.
 | |
| 
 | |
| New encryption modes can be added relatively easily, without changes
 | |
| to individual filesystems.  However, authenticated encryption (AE)
 | |
| modes are not currently supported because of the difficulty of dealing
 | |
| with ciphertext expansion.
 | |
| 
 | |
| Contents encryption
 | |
| -------------------
 | |
| 
 | |
| For file contents, each filesystem block is encrypted independently.
 | |
| Starting from Linux kernel 5.5, encryption of filesystems with block
 | |
| size less than system's page size is supported.
 | |
| 
 | |
| Each block's IV is set to the logical block number within the file as
 | |
| a little endian number, except that:
 | |
| 
 | |
| - With CBC mode encryption, ESSIV is also used.  Specifically, each IV
 | |
|   is encrypted with AES-256 where the AES-256 key is the SHA-256 hash
 | |
|   of the file's data encryption key.
 | |
| 
 | |
| - With `DIRECT_KEY policies`_, the file's nonce is appended to the IV.
 | |
|   Currently this is only allowed with the Adiantum encryption mode.
 | |
| 
 | |
| - With `IV_INO_LBLK_64 policies`_, the logical block number is limited
 | |
|   to 32 bits and is placed in bits 0-31 of the IV.  The inode number
 | |
|   (which is also limited to 32 bits) is placed in bits 32-63.
 | |
| 
 | |
| - With `IV_INO_LBLK_32 policies`_, the logical block number is limited
 | |
|   to 32 bits and is placed in bits 0-31 of the IV.  The inode number
 | |
|   is then hashed and added mod 2^32.
 | |
| 
 | |
| Note that because file logical block numbers are included in the IVs,
 | |
| filesystems must enforce that blocks are never shifted around within
 | |
| encrypted files, e.g. via "collapse range" or "insert range".
 | |
| 
 | |
| Filenames encryption
 | |
| --------------------
 | |
| 
 | |
| For filenames, each full filename is encrypted at once.  Because of
 | |
| the requirements to retain support for efficient directory lookups and
 | |
| filenames of up to 255 bytes, the same IV is used for every filename
 | |
| in a directory.
 | |
| 
 | |
| However, each encrypted directory still uses a unique key, or
 | |
| alternatively has the file's nonce (for `DIRECT_KEY policies`_) or
 | |
| inode number (for `IV_INO_LBLK_64 policies`_) included in the IVs.
 | |
| Thus, IV reuse is limited to within a single directory.
 | |
| 
 | |
| With CTS-CBC, the IV reuse means that when the plaintext filenames share a
 | |
| common prefix at least as long as the cipher block size (16 bytes for AES), the
 | |
| corresponding encrypted filenames will also share a common prefix.  This is
 | |
| undesirable.  Adiantum and HCTR2 do not have this weakness, as they are
 | |
| wide-block encryption modes.
 | |
| 
 | |
| All supported filenames encryption modes accept any plaintext length
 | |
| >= 16 bytes; cipher block alignment is not required.  However,
 | |
| filenames shorter than 16 bytes are NUL-padded to 16 bytes before
 | |
| being encrypted.  In addition, to reduce leakage of filename lengths
 | |
| via their ciphertexts, all filenames are NUL-padded to the next 4, 8,
 | |
| 16, or 32-byte boundary (configurable).  32 is recommended since this
 | |
| provides the best confidentiality, at the cost of making directory
 | |
| entries consume slightly more space.  Note that since NUL (``\0``) is
 | |
| not otherwise a valid character in filenames, the padding will never
 | |
| produce duplicate plaintexts.
 | |
| 
 | |
| Symbolic link targets are considered a type of filename and are
 | |
| encrypted in the same way as filenames in directory entries, except
 | |
| that IV reuse is not a problem as each symlink has its own inode.
 | |
| 
 | |
| User API
 | |
| ========
 | |
| 
 | |
| Setting an encryption policy
 | |
| ----------------------------
 | |
| 
 | |
| FS_IOC_SET_ENCRYPTION_POLICY
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The FS_IOC_SET_ENCRYPTION_POLICY ioctl sets an encryption policy on an
 | |
| empty directory or verifies that a directory or regular file already
 | |
| has the specified encryption policy.  It takes in a pointer to
 | |
| struct fscrypt_policy_v1 or struct fscrypt_policy_v2, defined as
 | |
| follows::
 | |
| 
 | |
|     #define FSCRYPT_POLICY_V1               0
 | |
|     #define FSCRYPT_KEY_DESCRIPTOR_SIZE     8
 | |
|     struct fscrypt_policy_v1 {
 | |
|             __u8 version;
 | |
|             __u8 contents_encryption_mode;
 | |
|             __u8 filenames_encryption_mode;
 | |
|             __u8 flags;
 | |
|             __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
 | |
|     };
 | |
|     #define fscrypt_policy  fscrypt_policy_v1
 | |
| 
 | |
|     #define FSCRYPT_POLICY_V2               2
 | |
|     #define FSCRYPT_KEY_IDENTIFIER_SIZE     16
 | |
|     struct fscrypt_policy_v2 {
 | |
|             __u8 version;
 | |
|             __u8 contents_encryption_mode;
 | |
|             __u8 filenames_encryption_mode;
 | |
|             __u8 flags;
 | |
|             __u8 __reserved[4];
 | |
|             __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
 | |
|     };
 | |
| 
 | |
| This structure must be initialized as follows:
 | |
| 
 | |
| - ``version`` must be FSCRYPT_POLICY_V1 (0) if
 | |
|   struct fscrypt_policy_v1 is used or FSCRYPT_POLICY_V2 (2) if
 | |
|   struct fscrypt_policy_v2 is used. (Note: we refer to the original
 | |
|   policy version as "v1", though its version code is really 0.)
 | |
|   For new encrypted directories, use v2 policies.
 | |
| 
 | |
| - ``contents_encryption_mode`` and ``filenames_encryption_mode`` must
 | |
|   be set to constants from ``<linux/fscrypt.h>`` which identify the
 | |
|   encryption modes to use.  If unsure, use FSCRYPT_MODE_AES_256_XTS
 | |
|   (1) for ``contents_encryption_mode`` and FSCRYPT_MODE_AES_256_CTS
 | |
|   (4) for ``filenames_encryption_mode``.
 | |
| 
 | |
| - ``flags`` contains optional flags from ``<linux/fscrypt.h>``:
 | |
| 
 | |
|   - FSCRYPT_POLICY_FLAGS_PAD_*: The amount of NUL padding to use when
 | |
|     encrypting filenames.  If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32
 | |
|     (0x3).
 | |
|   - FSCRYPT_POLICY_FLAG_DIRECT_KEY: See `DIRECT_KEY policies`_.
 | |
|   - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64: See `IV_INO_LBLK_64
 | |
|     policies`_.
 | |
|   - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32: See `IV_INO_LBLK_32
 | |
|     policies`_.
 | |
| 
 | |
|   v1 encryption policies only support the PAD_* and DIRECT_KEY flags.
 | |
|   The other flags are only supported by v2 encryption policies.
 | |
| 
 | |
|   The DIRECT_KEY, IV_INO_LBLK_64, and IV_INO_LBLK_32 flags are
 | |
|   mutually exclusive.
 | |
| 
 | |
| - For v2 encryption policies, ``__reserved`` must be zeroed.
 | |
| 
 | |
| - For v1 encryption policies, ``master_key_descriptor`` specifies how
 | |
|   to find the master key in a keyring; see `Adding keys`_.  It is up
 | |
|   to userspace to choose a unique ``master_key_descriptor`` for each
 | |
|   master key.  The e4crypt and fscrypt tools use the first 8 bytes of
 | |
|   ``SHA-512(SHA-512(master_key))``, but this particular scheme is not
 | |
|   required.  Also, the master key need not be in the keyring yet when
 | |
|   FS_IOC_SET_ENCRYPTION_POLICY is executed.  However, it must be added
 | |
|   before any files can be created in the encrypted directory.
 | |
| 
 | |
|   For v2 encryption policies, ``master_key_descriptor`` has been
 | |
|   replaced with ``master_key_identifier``, which is longer and cannot
 | |
|   be arbitrarily chosen.  Instead, the key must first be added using
 | |
|   `FS_IOC_ADD_ENCRYPTION_KEY`_.  Then, the ``key_spec.u.identifier``
 | |
|   the kernel returned in the struct fscrypt_add_key_arg must
 | |
|   be used as the ``master_key_identifier`` in
 | |
|   struct fscrypt_policy_v2.
 | |
| 
 | |
| If the file is not yet encrypted, then FS_IOC_SET_ENCRYPTION_POLICY
 | |
| verifies that the file is an empty directory.  If so, the specified
 | |
| encryption policy is assigned to the directory, turning it into an
 | |
| encrypted directory.  After that, and after providing the
 | |
| corresponding master key as described in `Adding keys`_, all regular
 | |
| files, directories (recursively), and symlinks created in the
 | |
| directory will be encrypted, inheriting the same encryption policy.
 | |
| The filenames in the directory's entries will be encrypted as well.
 | |
| 
 | |
| Alternatively, if the file is already encrypted, then
 | |
| FS_IOC_SET_ENCRYPTION_POLICY validates that the specified encryption
 | |
| policy exactly matches the actual one.  If they match, then the ioctl
 | |
| returns 0.  Otherwise, it fails with EEXIST.  This works on both
 | |
| regular files and directories, including nonempty directories.
 | |
| 
 | |
| When a v2 encryption policy is assigned to a directory, it is also
 | |
| required that either the specified key has been added by the current
 | |
| user or that the caller has CAP_FOWNER in the initial user namespace.
 | |
| (This is needed to prevent a user from encrypting their data with
 | |
| another user's key.)  The key must remain added while
 | |
| FS_IOC_SET_ENCRYPTION_POLICY is executing.  However, if the new
 | |
| encrypted directory does not need to be accessed immediately, then the
 | |
| key can be removed right away afterwards.
 | |
| 
 | |
| Note that the ext4 filesystem does not allow the root directory to be
 | |
| encrypted, even if it is empty.  Users who want to encrypt an entire
 | |
| filesystem with one key should consider using dm-crypt instead.
 | |
| 
 | |
| FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors:
 | |
| 
 | |
| - ``EACCES``: the file is not owned by the process's uid, nor does the
 | |
|   process have the CAP_FOWNER capability in a namespace with the file
 | |
|   owner's uid mapped
 | |
| - ``EEXIST``: the file is already encrypted with an encryption policy
 | |
|   different from the one specified
 | |
| - ``EINVAL``: an invalid encryption policy was specified (invalid
 | |
|   version, mode(s), or flags; or reserved bits were set); or a v1
 | |
|   encryption policy was specified but the directory has the casefold
 | |
|   flag enabled (casefolding is incompatible with v1 policies).
 | |
| - ``ENOKEY``: a v2 encryption policy was specified, but the key with
 | |
|   the specified ``master_key_identifier`` has not been added, nor does
 | |
|   the process have the CAP_FOWNER capability in the initial user
 | |
|   namespace
 | |
| - ``ENOTDIR``: the file is unencrypted and is a regular file, not a
 | |
|   directory
 | |
| - ``ENOTEMPTY``: the file is unencrypted and is a nonempty directory
 | |
| - ``ENOTTY``: this type of filesystem does not implement encryption
 | |
| - ``EOPNOTSUPP``: the kernel was not configured with encryption
 | |
|   support for filesystems, or the filesystem superblock has not
 | |
|   had encryption enabled on it.  (For example, to use encryption on an
 | |
|   ext4 filesystem, CONFIG_FS_ENCRYPTION must be enabled in the
 | |
|   kernel config, and the superblock must have had the "encrypt"
 | |
|   feature flag enabled using ``tune2fs -O encrypt`` or ``mkfs.ext4 -O
 | |
|   encrypt``.)
 | |
| - ``EPERM``: this directory may not be encrypted, e.g. because it is
 | |
|   the root directory of an ext4 filesystem
 | |
| - ``EROFS``: the filesystem is readonly
 | |
| 
 | |
| Getting an encryption policy
 | |
| ----------------------------
 | |
| 
 | |
| Two ioctls are available to get a file's encryption policy:
 | |
| 
 | |
| - `FS_IOC_GET_ENCRYPTION_POLICY_EX`_
 | |
| - `FS_IOC_GET_ENCRYPTION_POLICY`_
 | |
| 
 | |
| The extended (_EX) version of the ioctl is more general and is
 | |
| recommended to use when possible.  However, on older kernels only the
 | |
| original ioctl is available.  Applications should try the extended
 | |
| version, and if it fails with ENOTTY fall back to the original
 | |
| version.
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_POLICY_EX
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The FS_IOC_GET_ENCRYPTION_POLICY_EX ioctl retrieves the encryption
 | |
| policy, if any, for a directory or regular file.  No additional
 | |
| permissions are required beyond the ability to open the file.  It
 | |
| takes in a pointer to struct fscrypt_get_policy_ex_arg,
 | |
| defined as follows::
 | |
| 
 | |
|     struct fscrypt_get_policy_ex_arg {
 | |
|             __u64 policy_size; /* input/output */
 | |
|             union {
 | |
|                     __u8 version;
 | |
|                     struct fscrypt_policy_v1 v1;
 | |
|                     struct fscrypt_policy_v2 v2;
 | |
|             } policy; /* output */
 | |
|     };
 | |
| 
 | |
| The caller must initialize ``policy_size`` to the size available for
 | |
| the policy struct, i.e. ``sizeof(arg.policy)``.
 | |
| 
 | |
| On success, the policy struct is returned in ``policy``, and its
 | |
| actual size is returned in ``policy_size``.  ``policy.version`` should
 | |
| be checked to determine the version of policy returned.  Note that the
 | |
| version code for the "v1" policy is actually 0 (FSCRYPT_POLICY_V1).
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_POLICY_EX can fail with the following errors:
 | |
| 
 | |
| - ``EINVAL``: the file is encrypted, but it uses an unrecognized
 | |
|   encryption policy version
 | |
| - ``ENODATA``: the file is not encrypted
 | |
| - ``ENOTTY``: this type of filesystem does not implement encryption,
 | |
|   or this kernel is too old to support FS_IOC_GET_ENCRYPTION_POLICY_EX
 | |
|   (try FS_IOC_GET_ENCRYPTION_POLICY instead)
 | |
| - ``EOPNOTSUPP``: the kernel was not configured with encryption
 | |
|   support for this filesystem, or the filesystem superblock has not
 | |
|   had encryption enabled on it
 | |
| - ``EOVERFLOW``: the file is encrypted and uses a recognized
 | |
|   encryption policy version, but the policy struct does not fit into
 | |
|   the provided buffer
 | |
| 
 | |
| Note: if you only need to know whether a file is encrypted or not, on
 | |
| most filesystems it is also possible to use the FS_IOC_GETFLAGS ioctl
 | |
| and check for FS_ENCRYPT_FL, or to use the statx() system call and
 | |
| check for STATX_ATTR_ENCRYPTED in stx_attributes.
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_POLICY
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The FS_IOC_GET_ENCRYPTION_POLICY ioctl can also retrieve the
 | |
| encryption policy, if any, for a directory or regular file.  However,
 | |
| unlike `FS_IOC_GET_ENCRYPTION_POLICY_EX`_,
 | |
| FS_IOC_GET_ENCRYPTION_POLICY only supports the original policy
 | |
| version.  It takes in a pointer directly to struct fscrypt_policy_v1
 | |
| rather than struct fscrypt_get_policy_ex_arg.
 | |
| 
 | |
| The error codes for FS_IOC_GET_ENCRYPTION_POLICY are the same as those
 | |
| for FS_IOC_GET_ENCRYPTION_POLICY_EX, except that
 | |
| FS_IOC_GET_ENCRYPTION_POLICY also returns ``EINVAL`` if the file is
 | |
| encrypted using a newer encryption policy version.
 | |
| 
 | |
| Getting the per-filesystem salt
 | |
| -------------------------------
 | |
| 
 | |
| Some filesystems, such as ext4 and F2FS, also support the deprecated
 | |
| ioctl FS_IOC_GET_ENCRYPTION_PWSALT.  This ioctl retrieves a randomly
 | |
| generated 16-byte value stored in the filesystem superblock.  This
 | |
| value is intended to used as a salt when deriving an encryption key
 | |
| from a passphrase or other low-entropy user credential.
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_PWSALT is deprecated.  Instead, prefer to
 | |
| generate and manage any needed salt(s) in userspace.
 | |
| 
 | |
| Getting a file's encryption nonce
 | |
| ---------------------------------
 | |
| 
 | |
| Since Linux v5.7, the ioctl FS_IOC_GET_ENCRYPTION_NONCE is supported.
 | |
| On encrypted files and directories it gets the inode's 16-byte nonce.
 | |
| On unencrypted files and directories, it fails with ENODATA.
 | |
| 
 | |
| This ioctl can be useful for automated tests which verify that the
 | |
| encryption is being done correctly.  It is not needed for normal use
 | |
| of fscrypt.
 | |
| 
 | |
| Adding keys
 | |
| -----------
 | |
| 
 | |
| FS_IOC_ADD_ENCRYPTION_KEY
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The FS_IOC_ADD_ENCRYPTION_KEY ioctl adds a master encryption key to
 | |
| the filesystem, making all files on the filesystem which were
 | |
| encrypted using that key appear "unlocked", i.e. in plaintext form.
 | |
| It can be executed on any file or directory on the target filesystem,
 | |
| but using the filesystem's root directory is recommended.  It takes in
 | |
| a pointer to struct fscrypt_add_key_arg, defined as follows::
 | |
| 
 | |
|     struct fscrypt_add_key_arg {
 | |
|             struct fscrypt_key_specifier key_spec;
 | |
|             __u32 raw_size;
 | |
|             __u32 key_id;
 | |
|             __u32 __reserved[8];
 | |
|             __u8 raw[];
 | |
|     };
 | |
| 
 | |
|     #define FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR        1
 | |
|     #define FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER        2
 | |
| 
 | |
|     struct fscrypt_key_specifier {
 | |
|             __u32 type;     /* one of FSCRYPT_KEY_SPEC_TYPE_* */
 | |
|             __u32 __reserved;
 | |
|             union {
 | |
|                     __u8 __reserved[32]; /* reserve some extra space */
 | |
|                     __u8 descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
 | |
|                     __u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
 | |
|             } u;
 | |
|     };
 | |
| 
 | |
|     struct fscrypt_provisioning_key_payload {
 | |
|             __u32 type;
 | |
|             __u32 __reserved;
 | |
|             __u8 raw[];
 | |
|     };
 | |
| 
 | |
| struct fscrypt_add_key_arg must be zeroed, then initialized
 | |
| as follows:
 | |
| 
 | |
| - If the key is being added for use by v1 encryption policies, then
 | |
|   ``key_spec.type`` must contain FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR, and
 | |
|   ``key_spec.u.descriptor`` must contain the descriptor of the key
 | |
|   being added, corresponding to the value in the
 | |
|   ``master_key_descriptor`` field of struct fscrypt_policy_v1.
 | |
|   To add this type of key, the calling process must have the
 | |
|   CAP_SYS_ADMIN capability in the initial user namespace.
 | |
| 
 | |
|   Alternatively, if the key is being added for use by v2 encryption
 | |
|   policies, then ``key_spec.type`` must contain
 | |
|   FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER, and ``key_spec.u.identifier`` is
 | |
|   an *output* field which the kernel fills in with a cryptographic
 | |
|   hash of the key.  To add this type of key, the calling process does
 | |
|   not need any privileges.  However, the number of keys that can be
 | |
|   added is limited by the user's quota for the keyrings service (see
 | |
|   ``Documentation/security/keys/core.rst``).
 | |
| 
 | |
| - ``raw_size`` must be the size of the ``raw`` key provided, in bytes.
 | |
|   Alternatively, if ``key_id`` is nonzero, this field must be 0, since
 | |
|   in that case the size is implied by the specified Linux keyring key.
 | |
| 
 | |
| - ``key_id`` is 0 if the raw key is given directly in the ``raw``
 | |
|   field.  Otherwise ``key_id`` is the ID of a Linux keyring key of
 | |
|   type "fscrypt-provisioning" whose payload is
 | |
|   struct fscrypt_provisioning_key_payload whose ``raw`` field contains
 | |
|   the raw key and whose ``type`` field matches ``key_spec.type``.
 | |
|   Since ``raw`` is variable-length, the total size of this key's
 | |
|   payload must be ``sizeof(struct fscrypt_provisioning_key_payload)``
 | |
|   plus the raw key size.  The process must have Search permission on
 | |
|   this key.
 | |
| 
 | |
|   Most users should leave this 0 and specify the raw key directly.
 | |
|   The support for specifying a Linux keyring key is intended mainly to
 | |
|   allow re-adding keys after a filesystem is unmounted and re-mounted,
 | |
|   without having to store the raw keys in userspace memory.
 | |
| 
 | |
| - ``raw`` is a variable-length field which must contain the actual
 | |
|   key, ``raw_size`` bytes long.  Alternatively, if ``key_id`` is
 | |
|   nonzero, then this field is unused.
 | |
| 
 | |
| For v2 policy keys, the kernel keeps track of which user (identified
 | |
| by effective user ID) added the key, and only allows the key to be
 | |
| removed by that user --- or by "root", if they use
 | |
| `FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS`_.
 | |
| 
 | |
| However, if another user has added the key, it may be desirable to
 | |
| prevent that other user from unexpectedly removing it.  Therefore,
 | |
| FS_IOC_ADD_ENCRYPTION_KEY may also be used to add a v2 policy key
 | |
| *again*, even if it's already added by other user(s).  In this case,
 | |
| FS_IOC_ADD_ENCRYPTION_KEY will just install a claim to the key for the
 | |
| current user, rather than actually add the key again (but the raw key
 | |
| must still be provided, as a proof of knowledge).
 | |
| 
 | |
| FS_IOC_ADD_ENCRYPTION_KEY returns 0 if either the key or a claim to
 | |
| the key was either added or already exists.
 | |
| 
 | |
| FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors:
 | |
| 
 | |
| - ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the
 | |
|   caller does not have the CAP_SYS_ADMIN capability in the initial
 | |
|   user namespace; or the raw key was specified by Linux key ID but the
 | |
|   process lacks Search permission on the key.
 | |
| - ``EDQUOT``: the key quota for this user would be exceeded by adding
 | |
|   the key
 | |
| - ``EINVAL``: invalid key size or key specifier type, or reserved bits
 | |
|   were set
 | |
| - ``EKEYREJECTED``: the raw key was specified by Linux key ID, but the
 | |
|   key has the wrong type
 | |
| - ``ENOKEY``: the raw key was specified by Linux key ID, but no key
 | |
|   exists with that ID
 | |
| - ``ENOTTY``: this type of filesystem does not implement encryption
 | |
| - ``EOPNOTSUPP``: the kernel was not configured with encryption
 | |
|   support for this filesystem, or the filesystem superblock has not
 | |
|   had encryption enabled on it
 | |
| 
 | |
| Legacy method
 | |
| ~~~~~~~~~~~~~
 | |
| 
 | |
| For v1 encryption policies, a master encryption key can also be
 | |
| provided by adding it to a process-subscribed keyring, e.g. to a
 | |
| session keyring, or to a user keyring if the user keyring is linked
 | |
| into the session keyring.
 | |
| 
 | |
| This method is deprecated (and not supported for v2 encryption
 | |
| policies) for several reasons.  First, it cannot be used in
 | |
| combination with FS_IOC_REMOVE_ENCRYPTION_KEY (see `Removing keys`_),
 | |
| so for removing a key a workaround such as keyctl_unlink() in
 | |
| combination with ``sync; echo 2 > /proc/sys/vm/drop_caches`` would
 | |
| have to be used.  Second, it doesn't match the fact that the
 | |
| locked/unlocked status of encrypted files (i.e. whether they appear to
 | |
| be in plaintext form or in ciphertext form) is global.  This mismatch
 | |
| has caused much confusion as well as real problems when processes
 | |
| running under different UIDs, such as a ``sudo`` command, need to
 | |
| access encrypted files.
 | |
| 
 | |
| Nevertheless, to add a key to one of the process-subscribed keyrings,
 | |
| the add_key() system call can be used (see:
 | |
| ``Documentation/security/keys/core.rst``).  The key type must be
 | |
| "logon"; keys of this type are kept in kernel memory and cannot be
 | |
| read back by userspace.  The key description must be "fscrypt:"
 | |
| followed by the 16-character lower case hex representation of the
 | |
| ``master_key_descriptor`` that was set in the encryption policy.  The
 | |
| key payload must conform to the following structure::
 | |
| 
 | |
|     #define FSCRYPT_MAX_KEY_SIZE            64
 | |
| 
 | |
|     struct fscrypt_key {
 | |
|             __u32 mode;
 | |
|             __u8 raw[FSCRYPT_MAX_KEY_SIZE];
 | |
|             __u32 size;
 | |
|     };
 | |
| 
 | |
| ``mode`` is ignored; just set it to 0.  The actual key is provided in
 | |
| ``raw`` with ``size`` indicating its size in bytes.  That is, the
 | |
| bytes ``raw[0..size-1]`` (inclusive) are the actual key.
 | |
| 
 | |
| The key description prefix "fscrypt:" may alternatively be replaced
 | |
| with a filesystem-specific prefix such as "ext4:".  However, the
 | |
| filesystem-specific prefixes are deprecated and should not be used in
 | |
| new programs.
 | |
| 
 | |
| Removing keys
 | |
| -------------
 | |
| 
 | |
| Two ioctls are available for removing a key that was added by
 | |
| `FS_IOC_ADD_ENCRYPTION_KEY`_:
 | |
| 
 | |
| - `FS_IOC_REMOVE_ENCRYPTION_KEY`_
 | |
| - `FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS`_
 | |
| 
 | |
| These two ioctls differ only in cases where v2 policy keys are added
 | |
| or removed by non-root users.
 | |
| 
 | |
| These ioctls don't work on keys that were added via the legacy
 | |
| process-subscribed keyrings mechanism.
 | |
| 
 | |
| Before using these ioctls, read the `Kernel memory compromise`_
 | |
| section for a discussion of the security goals and limitations of
 | |
| these ioctls.
 | |
| 
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The FS_IOC_REMOVE_ENCRYPTION_KEY ioctl removes a claim to a master
 | |
| encryption key from the filesystem, and possibly removes the key
 | |
| itself.  It can be executed on any file or directory on the target
 | |
| filesystem, but using the filesystem's root directory is recommended.
 | |
| It takes in a pointer to struct fscrypt_remove_key_arg, defined
 | |
| as follows::
 | |
| 
 | |
|     struct fscrypt_remove_key_arg {
 | |
|             struct fscrypt_key_specifier key_spec;
 | |
|     #define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY      0x00000001
 | |
|     #define FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS     0x00000002
 | |
|             __u32 removal_status_flags;     /* output */
 | |
|             __u32 __reserved[5];
 | |
|     };
 | |
| 
 | |
| This structure must be zeroed, then initialized as follows:
 | |
| 
 | |
| - The key to remove is specified by ``key_spec``:
 | |
| 
 | |
|     - To remove a key used by v1 encryption policies, set
 | |
|       ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR and fill
 | |
|       in ``key_spec.u.descriptor``.  To remove this type of key, the
 | |
|       calling process must have the CAP_SYS_ADMIN capability in the
 | |
|       initial user namespace.
 | |
| 
 | |
|     - To remove a key used by v2 encryption policies, set
 | |
|       ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER and fill
 | |
|       in ``key_spec.u.identifier``.
 | |
| 
 | |
| For v2 policy keys, this ioctl is usable by non-root users.  However,
 | |
| to make this possible, it actually just removes the current user's
 | |
| claim to the key, undoing a single call to FS_IOC_ADD_ENCRYPTION_KEY.
 | |
| Only after all claims are removed is the key really removed.
 | |
| 
 | |
| For example, if FS_IOC_ADD_ENCRYPTION_KEY was called with uid 1000,
 | |
| then the key will be "claimed" by uid 1000, and
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY will only succeed as uid 1000.  Or, if
 | |
| both uids 1000 and 2000 added the key, then for each uid
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY will only remove their own claim.  Only
 | |
| once *both* are removed is the key really removed.  (Think of it like
 | |
| unlinking a file that may have hard links.)
 | |
| 
 | |
| If FS_IOC_REMOVE_ENCRYPTION_KEY really removes the key, it will also
 | |
| try to "lock" all files that had been unlocked with the key.  It won't
 | |
| lock files that are still in-use, so this ioctl is expected to be used
 | |
| in cooperation with userspace ensuring that none of the files are
 | |
| still open.  However, if necessary, this ioctl can be executed again
 | |
| later to retry locking any remaining files.
 | |
| 
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY returns 0 if either the key was removed
 | |
| (but may still have files remaining to be locked), the user's claim to
 | |
| the key was removed, or the key was already removed but had files
 | |
| remaining to be the locked so the ioctl retried locking them.  In any
 | |
| of these cases, ``removal_status_flags`` is filled in with the
 | |
| following informational status flags:
 | |
| 
 | |
| - ``FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY``: set if some file(s)
 | |
|   are still in-use.  Not guaranteed to be set in the case where only
 | |
|   the user's claim to the key was removed.
 | |
| - ``FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS``: set if only the
 | |
|   user's claim to the key was removed, not the key itself
 | |
| 
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY can fail with the following errors:
 | |
| 
 | |
| - ``EACCES``: The FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR key specifier type
 | |
|   was specified, but the caller does not have the CAP_SYS_ADMIN
 | |
|   capability in the initial user namespace
 | |
| - ``EINVAL``: invalid key specifier type, or reserved bits were set
 | |
| - ``ENOKEY``: the key object was not found at all, i.e. it was never
 | |
|   added in the first place or was already fully removed including all
 | |
|   files locked; or, the user does not have a claim to the key (but
 | |
|   someone else does).
 | |
| - ``ENOTTY``: this type of filesystem does not implement encryption
 | |
| - ``EOPNOTSUPP``: the kernel was not configured with encryption
 | |
|   support for this filesystem, or the filesystem superblock has not
 | |
|   had encryption enabled on it
 | |
| 
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS is exactly the same as
 | |
| `FS_IOC_REMOVE_ENCRYPTION_KEY`_, except that for v2 policy keys, the
 | |
| ALL_USERS version of the ioctl will remove all users' claims to the
 | |
| key, not just the current user's.  I.e., the key itself will always be
 | |
| removed, no matter how many users have added it.  This difference is
 | |
| only meaningful if non-root users are adding and removing keys.
 | |
| 
 | |
| Because of this, FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS also requires
 | |
| "root", namely the CAP_SYS_ADMIN capability in the initial user
 | |
| namespace.  Otherwise it will fail with EACCES.
 | |
| 
 | |
| Getting key status
 | |
| ------------------
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_KEY_STATUS
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The FS_IOC_GET_ENCRYPTION_KEY_STATUS ioctl retrieves the status of a
 | |
| master encryption key.  It can be executed on any file or directory on
 | |
| the target filesystem, but using the filesystem's root directory is
 | |
| recommended.  It takes in a pointer to
 | |
| struct fscrypt_get_key_status_arg, defined as follows::
 | |
| 
 | |
|     struct fscrypt_get_key_status_arg {
 | |
|             /* input */
 | |
|             struct fscrypt_key_specifier key_spec;
 | |
|             __u32 __reserved[6];
 | |
| 
 | |
|             /* output */
 | |
|     #define FSCRYPT_KEY_STATUS_ABSENT               1
 | |
|     #define FSCRYPT_KEY_STATUS_PRESENT              2
 | |
|     #define FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED 3
 | |
|             __u32 status;
 | |
|     #define FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF   0x00000001
 | |
|             __u32 status_flags;
 | |
|             __u32 user_count;
 | |
|             __u32 __out_reserved[13];
 | |
|     };
 | |
| 
 | |
| The caller must zero all input fields, then fill in ``key_spec``:
 | |
| 
 | |
|     - To get the status of a key for v1 encryption policies, set
 | |
|       ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR and fill
 | |
|       in ``key_spec.u.descriptor``.
 | |
| 
 | |
|     - To get the status of a key for v2 encryption policies, set
 | |
|       ``key_spec.type`` to FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER and fill
 | |
|       in ``key_spec.u.identifier``.
 | |
| 
 | |
| On success, 0 is returned and the kernel fills in the output fields:
 | |
| 
 | |
| - ``status`` indicates whether the key is absent, present, or
 | |
|   incompletely removed.  Incompletely removed means that the master
 | |
|   secret has been removed, but some files are still in use; i.e.,
 | |
|   `FS_IOC_REMOVE_ENCRYPTION_KEY`_ returned 0 but set the informational
 | |
|   status flag FSCRYPT_KEY_REMOVAL_STATUS_FLAG_FILES_BUSY.
 | |
| 
 | |
| - ``status_flags`` can contain the following flags:
 | |
| 
 | |
|     - ``FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF`` indicates that the key
 | |
|       has added by the current user.  This is only set for keys
 | |
|       identified by ``identifier`` rather than by ``descriptor``.
 | |
| 
 | |
| - ``user_count`` specifies the number of users who have added the key.
 | |
|   This is only set for keys identified by ``identifier`` rather than
 | |
|   by ``descriptor``.
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_KEY_STATUS can fail with the following errors:
 | |
| 
 | |
| - ``EINVAL``: invalid key specifier type, or reserved bits were set
 | |
| - ``ENOTTY``: this type of filesystem does not implement encryption
 | |
| - ``EOPNOTSUPP``: the kernel was not configured with encryption
 | |
|   support for this filesystem, or the filesystem superblock has not
 | |
|   had encryption enabled on it
 | |
| 
 | |
| Among other use cases, FS_IOC_GET_ENCRYPTION_KEY_STATUS can be useful
 | |
| for determining whether the key for a given encrypted directory needs
 | |
| to be added before prompting the user for the passphrase needed to
 | |
| derive the key.
 | |
| 
 | |
| FS_IOC_GET_ENCRYPTION_KEY_STATUS can only get the status of keys in
 | |
| the filesystem-level keyring, i.e. the keyring managed by
 | |
| `FS_IOC_ADD_ENCRYPTION_KEY`_ and `FS_IOC_REMOVE_ENCRYPTION_KEY`_.  It
 | |
| cannot get the status of a key that has only been added for use by v1
 | |
| encryption policies using the legacy mechanism involving
 | |
| process-subscribed keyrings.
 | |
| 
 | |
| Access semantics
 | |
| ================
 | |
| 
 | |
| With the key
 | |
| ------------
 | |
| 
 | |
| With the encryption key, encrypted regular files, directories, and
 | |
| symlinks behave very similarly to their unencrypted counterparts ---
 | |
| after all, the encryption is intended to be transparent.  However,
 | |
| astute users may notice some differences in behavior:
 | |
| 
 | |
| - Unencrypted files, or files encrypted with a different encryption
 | |
|   policy (i.e. different key, modes, or flags), cannot be renamed or
 | |
|   linked into an encrypted directory; see `Encryption policy
 | |
|   enforcement`_.  Attempts to do so will fail with EXDEV.  However,
 | |
|   encrypted files can be renamed within an encrypted directory, or
 | |
|   into an unencrypted directory.
 | |
| 
 | |
|   Note: "moving" an unencrypted file into an encrypted directory, e.g.
 | |
|   with the `mv` program, is implemented in userspace by a copy
 | |
|   followed by a delete.  Be aware that the original unencrypted data
 | |
|   may remain recoverable from free space on the disk; prefer to keep
 | |
|   all files encrypted from the very beginning.  The `shred` program
 | |
|   may be used to overwrite the source files but isn't guaranteed to be
 | |
|   effective on all filesystems and storage devices.
 | |
| 
 | |
| - Direct I/O is supported on encrypted files only under some
 | |
|   circumstances.  For details, see `Direct I/O support`_.
 | |
| 
 | |
| - The fallocate operations FALLOC_FL_COLLAPSE_RANGE and
 | |
|   FALLOC_FL_INSERT_RANGE are not supported on encrypted files and will
 | |
|   fail with EOPNOTSUPP.
 | |
| 
 | |
| - Online defragmentation of encrypted files is not supported.  The
 | |
|   EXT4_IOC_MOVE_EXT and F2FS_IOC_MOVE_RANGE ioctls will fail with
 | |
|   EOPNOTSUPP.
 | |
| 
 | |
| - The ext4 filesystem does not support data journaling with encrypted
 | |
|   regular files.  It will fall back to ordered data mode instead.
 | |
| 
 | |
| - DAX (Direct Access) is not supported on encrypted files.
 | |
| 
 | |
| - The maximum length of an encrypted symlink is 2 bytes shorter than
 | |
|   the maximum length of an unencrypted symlink.  For example, on an
 | |
|   EXT4 filesystem with a 4K block size, unencrypted symlinks can be up
 | |
|   to 4095 bytes long, while encrypted symlinks can only be up to 4093
 | |
|   bytes long (both lengths excluding the terminating null).
 | |
| 
 | |
| Note that mmap *is* supported.  This is possible because the pagecache
 | |
| for an encrypted file contains the plaintext, not the ciphertext.
 | |
| 
 | |
| Without the key
 | |
| ---------------
 | |
| 
 | |
| Some filesystem operations may be performed on encrypted regular
 | |
| files, directories, and symlinks even before their encryption key has
 | |
| been added, or after their encryption key has been removed:
 | |
| 
 | |
| - File metadata may be read, e.g. using stat().
 | |
| 
 | |
| - Directories may be listed, in which case the filenames will be
 | |
|   listed in an encoded form derived from their ciphertext.  The
 | |
|   current encoding algorithm is described in `Filename hashing and
 | |
|   encoding`_.  The algorithm is subject to change, but it is
 | |
|   guaranteed that the presented filenames will be no longer than
 | |
|   NAME_MAX bytes, will not contain the ``/`` or ``\0`` characters, and
 | |
|   will uniquely identify directory entries.
 | |
| 
 | |
|   The ``.`` and ``..`` directory entries are special.  They are always
 | |
|   present and are not encrypted or encoded.
 | |
| 
 | |
| - Files may be deleted.  That is, nondirectory files may be deleted
 | |
|   with unlink() as usual, and empty directories may be deleted with
 | |
|   rmdir() as usual.  Therefore, ``rm`` and ``rm -r`` will work as
 | |
|   expected.
 | |
| 
 | |
| - Symlink targets may be read and followed, but they will be presented
 | |
|   in encrypted form, similar to filenames in directories.  Hence, they
 | |
|   are unlikely to point to anywhere useful.
 | |
| 
 | |
| Without the key, regular files cannot be opened or truncated.
 | |
| Attempts to do so will fail with ENOKEY.  This implies that any
 | |
| regular file operations that require a file descriptor, such as
 | |
| read(), write(), mmap(), fallocate(), and ioctl(), are also forbidden.
 | |
| 
 | |
| Also without the key, files of any type (including directories) cannot
 | |
| be created or linked into an encrypted directory, nor can a name in an
 | |
| encrypted directory be the source or target of a rename, nor can an
 | |
| O_TMPFILE temporary file be created in an encrypted directory.  All
 | |
| such operations will fail with ENOKEY.
 | |
| 
 | |
| It is not currently possible to backup and restore encrypted files
 | |
| without the encryption key.  This would require special APIs which
 | |
| have not yet been implemented.
 | |
| 
 | |
| Encryption policy enforcement
 | |
| =============================
 | |
| 
 | |
| After an encryption policy has been set on a directory, all regular
 | |
| files, directories, and symbolic links created in that directory
 | |
| (recursively) will inherit that encryption policy.  Special files ---
 | |
| that is, named pipes, device nodes, and UNIX domain sockets --- will
 | |
| not be encrypted.
 | |
| 
 | |
| Except for those special files, it is forbidden to have unencrypted
 | |
| files, or files encrypted with a different encryption policy, in an
 | |
| encrypted directory tree.  Attempts to link or rename such a file into
 | |
| an encrypted directory will fail with EXDEV.  This is also enforced
 | |
| during ->lookup() to provide limited protection against offline
 | |
| attacks that try to disable or downgrade encryption in known locations
 | |
| where applications may later write sensitive data.  It is recommended
 | |
| that systems implementing a form of "verified boot" take advantage of
 | |
| this by validating all top-level encryption policies prior to access.
 | |
| 
 | |
| Inline encryption support
 | |
| =========================
 | |
| 
 | |
| By default, fscrypt uses the kernel crypto API for all cryptographic
 | |
| operations (other than HKDF, which fscrypt partially implements
 | |
| itself).  The kernel crypto API supports hardware crypto accelerators,
 | |
| but only ones that work in the traditional way where all inputs and
 | |
| outputs (e.g. plaintexts and ciphertexts) are in memory.  fscrypt can
 | |
| take advantage of such hardware, but the traditional acceleration
 | |
| model isn't particularly efficient and fscrypt hasn't been optimized
 | |
| for it.
 | |
| 
 | |
| Instead, many newer systems (especially mobile SoCs) have *inline
 | |
| encryption hardware* that can encrypt/decrypt data while it is on its
 | |
| way to/from the storage device.  Linux supports inline encryption
 | |
| through a set of extensions to the block layer called *blk-crypto*.
 | |
| blk-crypto allows filesystems to attach encryption contexts to bios
 | |
| (I/O requests) to specify how the data will be encrypted or decrypted
 | |
| in-line.  For more information about blk-crypto, see
 | |
| :ref:`Documentation/block/inline-encryption.rst <inline_encryption>`.
 | |
| 
 | |
| On supported filesystems (currently ext4 and f2fs), fscrypt can use
 | |
| blk-crypto instead of the kernel crypto API to encrypt/decrypt file
 | |
| contents.  To enable this, set CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y in
 | |
| the kernel configuration, and specify the "inlinecrypt" mount option
 | |
| when mounting the filesystem.
 | |
| 
 | |
| Note that the "inlinecrypt" mount option just specifies to use inline
 | |
| encryption when possible; it doesn't force its use.  fscrypt will
 | |
| still fall back to using the kernel crypto API on files where the
 | |
| inline encryption hardware doesn't have the needed crypto capabilities
 | |
| (e.g. support for the needed encryption algorithm and data unit size)
 | |
| and where blk-crypto-fallback is unusable.  (For blk-crypto-fallback
 | |
| to be usable, it must be enabled in the kernel configuration with
 | |
| CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y.)
 | |
| 
 | |
| Currently fscrypt always uses the filesystem block size (which is
 | |
| usually 4096 bytes) as the data unit size.  Therefore, it can only use
 | |
| inline encryption hardware that supports that data unit size.
 | |
| 
 | |
| Inline encryption doesn't affect the ciphertext or other aspects of
 | |
| the on-disk format, so users may freely switch back and forth between
 | |
| using "inlinecrypt" and not using "inlinecrypt".
 | |
| 
 | |
| Direct I/O support
 | |
| ==================
 | |
| 
 | |
| For direct I/O on an encrypted file to work, the following conditions
 | |
| must be met (in addition to the conditions for direct I/O on an
 | |
| unencrypted file):
 | |
| 
 | |
| * The file must be using inline encryption.  Usually this means that
 | |
|   the filesystem must be mounted with ``-o inlinecrypt`` and inline
 | |
|   encryption hardware must be present.  However, a software fallback
 | |
|   is also available.  For details, see `Inline encryption support`_.
 | |
| 
 | |
| * The I/O request must be fully aligned to the filesystem block size.
 | |
|   This means that the file position the I/O is targeting, the lengths
 | |
|   of all I/O segments, and the memory addresses of all I/O buffers
 | |
|   must be multiples of this value.  Note that the filesystem block
 | |
|   size may be greater than the logical block size of the block device.
 | |
| 
 | |
| If either of the above conditions is not met, then direct I/O on the
 | |
| encrypted file will fall back to buffered I/O.
 | |
| 
 | |
| Implementation details
 | |
| ======================
 | |
| 
 | |
| Encryption context
 | |
| ------------------
 | |
| 
 | |
| An encryption policy is represented on-disk by
 | |
| struct fscrypt_context_v1 or struct fscrypt_context_v2.  It is up to
 | |
| individual filesystems to decide where to store it, but normally it
 | |
| would be stored in a hidden extended attribute.  It should *not* be
 | |
| exposed by the xattr-related system calls such as getxattr() and
 | |
| setxattr() because of the special semantics of the encryption xattr.
 | |
| (In particular, there would be much confusion if an encryption policy
 | |
| were to be added to or removed from anything other than an empty
 | |
| directory.)  These structs are defined as follows::
 | |
| 
 | |
|     #define FSCRYPT_FILE_NONCE_SIZE 16
 | |
| 
 | |
|     #define FSCRYPT_KEY_DESCRIPTOR_SIZE  8
 | |
|     struct fscrypt_context_v1 {
 | |
|             u8 version;
 | |
|             u8 contents_encryption_mode;
 | |
|             u8 filenames_encryption_mode;
 | |
|             u8 flags;
 | |
|             u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
 | |
|             u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
 | |
|     };
 | |
| 
 | |
|     #define FSCRYPT_KEY_IDENTIFIER_SIZE  16
 | |
|     struct fscrypt_context_v2 {
 | |
|             u8 version;
 | |
|             u8 contents_encryption_mode;
 | |
|             u8 filenames_encryption_mode;
 | |
|             u8 flags;
 | |
|             u8 __reserved[4];
 | |
|             u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
 | |
|             u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
 | |
|     };
 | |
| 
 | |
| The context structs contain the same information as the corresponding
 | |
| policy structs (see `Setting an encryption policy`_), except that the
 | |
| context structs also contain a nonce.  The nonce is randomly generated
 | |
| by the kernel and is used as KDF input or as a tweak to cause
 | |
| different files to be encrypted differently; see `Per-file encryption
 | |
| keys`_ and `DIRECT_KEY policies`_.
 | |
| 
 | |
| Data path changes
 | |
| -----------------
 | |
| 
 | |
| When inline encryption is used, filesystems just need to associate
 | |
| encryption contexts with bios to specify how the block layer or the
 | |
| inline encryption hardware will encrypt/decrypt the file contents.
 | |
| 
 | |
| When inline encryption isn't used, filesystems must encrypt/decrypt
 | |
| the file contents themselves, as described below:
 | |
| 
 | |
| For the read path (->read_folio()) of regular files, filesystems can
 | |
| read the ciphertext into the page cache and decrypt it in-place.  The
 | |
| folio lock must be held until decryption has finished, to prevent the
 | |
| folio from becoming visible to userspace prematurely.
 | |
| 
 | |
| For the write path (->writepage()) of regular files, filesystems
 | |
| cannot encrypt data in-place in the page cache, since the cached
 | |
| plaintext must be preserved.  Instead, filesystems must encrypt into a
 | |
| temporary buffer or "bounce page", then write out the temporary
 | |
| buffer.  Some filesystems, such as UBIFS, already use temporary
 | |
| buffers regardless of encryption.  Other filesystems, such as ext4 and
 | |
| F2FS, have to allocate bounce pages specially for encryption.
 | |
| 
 | |
| Filename hashing and encoding
 | |
| -----------------------------
 | |
| 
 | |
| Modern filesystems accelerate directory lookups by using indexed
 | |
| directories.  An indexed directory is organized as a tree keyed by
 | |
| filename hashes.  When a ->lookup() is requested, the filesystem
 | |
| normally hashes the filename being looked up so that it can quickly
 | |
| find the corresponding directory entry, if any.
 | |
| 
 | |
| With encryption, lookups must be supported and efficient both with and
 | |
| without the encryption key.  Clearly, it would not work to hash the
 | |
| plaintext filenames, since the plaintext filenames are unavailable
 | |
| without the key.  (Hashing the plaintext filenames would also make it
 | |
| impossible for the filesystem's fsck tool to optimize encrypted
 | |
| directories.)  Instead, filesystems hash the ciphertext filenames,
 | |
| i.e. the bytes actually stored on-disk in the directory entries.  When
 | |
| asked to do a ->lookup() with the key, the filesystem just encrypts
 | |
| the user-supplied name to get the ciphertext.
 | |
| 
 | |
| Lookups without the key are more complicated.  The raw ciphertext may
 | |
| contain the ``\0`` and ``/`` characters, which are illegal in
 | |
| filenames.  Therefore, readdir() must base64url-encode the ciphertext
 | |
| for presentation.  For most filenames, this works fine; on ->lookup(),
 | |
| the filesystem just base64url-decodes the user-supplied name to get
 | |
| back to the raw ciphertext.
 | |
| 
 | |
| However, for very long filenames, base64url encoding would cause the
 | |
| filename length to exceed NAME_MAX.  To prevent this, readdir()
 | |
| actually presents long filenames in an abbreviated form which encodes
 | |
| a strong "hash" of the ciphertext filename, along with the optional
 | |
| filesystem-specific hash(es) needed for directory lookups.  This
 | |
| allows the filesystem to still, with a high degree of confidence, map
 | |
| the filename given in ->lookup() back to a particular directory entry
 | |
| that was previously listed by readdir().  See
 | |
| struct fscrypt_nokey_name in the source for more details.
 | |
| 
 | |
| Note that the precise way that filenames are presented to userspace
 | |
| without the key is subject to change in the future.  It is only meant
 | |
| as a way to temporarily present valid filenames so that commands like
 | |
| ``rm -r`` work as expected on encrypted directories.
 | |
| 
 | |
| Tests
 | |
| =====
 | |
| 
 | |
| To test fscrypt, use xfstests, which is Linux's de facto standard
 | |
| filesystem test suite.  First, run all the tests in the "encrypt"
 | |
| group on the relevant filesystem(s).  One can also run the tests
 | |
| with the 'inlinecrypt' mount option to test the implementation for
 | |
| inline encryption support.  For example, to test ext4 and
 | |
| f2fs encryption using `kvm-xfstests
 | |
| <https://github.com/tytso/xfstests-bld/blob/master/Documentation/kvm-quickstart.md>`_::
 | |
| 
 | |
|     kvm-xfstests -c ext4,f2fs -g encrypt
 | |
|     kvm-xfstests -c ext4,f2fs -g encrypt -m inlinecrypt
 | |
| 
 | |
| UBIFS encryption can also be tested this way, but it should be done in
 | |
| a separate command, and it takes some time for kvm-xfstests to set up
 | |
| emulated UBI volumes::
 | |
| 
 | |
|     kvm-xfstests -c ubifs -g encrypt
 | |
| 
 | |
| No tests should fail.  However, tests that use non-default encryption
 | |
| modes (e.g. generic/549 and generic/550) will be skipped if the needed
 | |
| algorithms were not built into the kernel's crypto API.  Also, tests
 | |
| that access the raw block device (e.g. generic/399, generic/548,
 | |
| generic/549, generic/550) will be skipped on UBIFS.
 | |
| 
 | |
| Besides running the "encrypt" group tests, for ext4 and f2fs it's also
 | |
| possible to run most xfstests with the "test_dummy_encryption" mount
 | |
| option.  This option causes all new files to be automatically
 | |
| encrypted with a dummy key, without having to make any API calls.
 | |
| This tests the encrypted I/O paths more thoroughly.  To do this with
 | |
| kvm-xfstests, use the "encrypt" filesystem configuration::
 | |
| 
 | |
|     kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto
 | |
|     kvm-xfstests -c ext4/encrypt,f2fs/encrypt -g auto -m inlinecrypt
 | |
| 
 | |
| Because this runs many more tests than "-g encrypt" does, it takes
 | |
| much longer to run; so also consider using `gce-xfstests
 | |
| <https://github.com/tytso/xfstests-bld/blob/master/Documentation/gce-xfstests.md>`_
 | |
| instead of kvm-xfstests::
 | |
| 
 | |
|     gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto
 | |
|     gce-xfstests -c ext4/encrypt,f2fs/encrypt -g auto -m inlinecrypt
 |