the master keys may be wrapped in userspace, e.g. as is done by the
 `fscrypt <https://github.com/google/fscrypt>`_ tool.
 
-Including the inode number in the IVs was considered.  However, it was
-rejected as it would have prevented ext4 filesystems from being
-resized, and by itself still wouldn't have been sufficient to prevent
-the same key from being directly reused for both XTS and CTS-CBC.
-
-DIRECT_KEY and per-mode keys
-----------------------------
+DIRECT_KEY policies
+-------------------
 
 The Adiantum encryption mode (see `Encryption modes and usage`_) is
 suitable for both contents and filenames encryption, and it accepts
   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 or eMMC standards, which support only 64 IV
+bits per I/O request and may have only a small number of keyslots.
+
 Key identifiers
 ---------------
 
   is encrypted with AES-256 where the AES-256 key is the SHA-256 hash
   of the file's data encryption key.
 
-- In the "direct key" configuration (FSCRYPT_POLICY_FLAG_DIRECT_KEY
-  set in the fscrypt_policy), the file's nonce is also appended to the
-  IV.  Currently this is only allowed with the Adiantum encryption
-  mode.
+- 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.
+
+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
 --------------------
 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 (for the "direct key" configuration) has the file's
-nonce included in the IVs.  Thus, IV reuse is limited to within a
-single 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
   (1) for ``contents_encryption_mode`` and FSCRYPT_MODE_AES_256_CTS
   (4) for ``filenames_encryption_mode``.
 
-- ``flags`` must contain a value from ``<linux/fscrypt.h>`` which
-  identifies the amount of NUL-padding to use when encrypting
-  filenames.  If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3).
-  Additionally, if the encryption modes are both
-  FSCRYPT_MODE_ADIANTUM, this can contain
-  FSCRYPT_POLICY_FLAG_DIRECT_KEY; see `DIRECT_KEY and per-mode keys`_.
+- ``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`_.  This is mutually exclusive with DIRECT_KEY and is not
+    supported on v1 policies.
 
 - For v2 encryption policies, ``__reserved`` must be zeroed.
 
 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 keys`_ and
-`DIRECT_KEY and per-mode keys`_.
+`DIRECT_KEY policies`_.
 
 Data path changes
 -----------------
 
 void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
                         const struct fscrypt_info *ci)
 {
+       u8 flags = fscrypt_policy_flags(&ci->ci_policy);
+
        memset(iv, 0, ci->ci_mode->ivsize);
-       iv->lblk_num = cpu_to_le64(lblk_num);
 
-       if (fscrypt_is_direct_key_policy(&ci->ci_policy))
+       if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
+               WARN_ON_ONCE((u32)lblk_num != lblk_num);
+               lblk_num |= (u64)ci->ci_inode->i_ino << 32;
+       } else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
                memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE);
+       }
+       iv->lblk_num = cpu_to_le64(lblk_num);
 }
 
 /* Encrypt or decrypt a single filesystem block of file contents */
 
        /* The actual crypto transform used for encryption and decryption */
        struct crypto_skcipher *ci_ctfm;
 
+       /* True if the key should be freed when this fscrypt_info is freed */
+       bool ci_owns_key;
+
        /*
         * Encryption mode used for this inode.  It corresponds to either the
         * contents or filenames encryption mode, depending on the inode type.
  */
 #define HKDF_CONTEXT_KEY_IDENTIFIER    1
 #define HKDF_CONTEXT_PER_FILE_KEY      2
-#define HKDF_CONTEXT_PER_MODE_KEY      3
+#define HKDF_CONTEXT_DIRECT_KEY                3
+#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY        4
 
 extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context,
                               const u8 *info, unsigned int infolen,
        struct list_head        mk_decrypted_inodes;
        spinlock_t              mk_decrypted_inodes_lock;
 
-       /* Per-mode tfms for DIRECT_KEY policies, allocated on-demand */
-       struct crypto_skcipher  *mk_mode_keys[__FSCRYPT_MODE_MAX + 1];
+       /* Crypto API transforms for DIRECT_KEY policies, allocated on-demand */
+       struct crypto_skcipher  *mk_direct_tfms[__FSCRYPT_MODE_MAX + 1];
+
+       /*
+        * Crypto API transforms for filesystem-layer implementation of
+        * IV_INO_LBLK_64 policies, allocated on-demand.
+        */
+       struct crypto_skcipher  *mk_iv_ino_lblk_64_tfms[__FSCRYPT_MODE_MAX + 1];
 
 } __randomize_layout;
 
 
 
        wipe_master_key_secret(&mk->mk_secret);
 
-       for (i = 0; i < ARRAY_SIZE(mk->mk_mode_keys); i++)
-               crypto_free_skcipher(mk->mk_mode_keys[i]);
+       for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) {
+               crypto_free_skcipher(mk->mk_direct_tfms[i]);
+               crypto_free_skcipher(mk->mk_iv_ino_lblk_64_tfms[i]);
+       }
 
        key_put(mk->mk_users);
        kzfree(mk);
 
                return PTR_ERR(tfm);
 
        ci->ci_ctfm = tfm;
+       ci->ci_owns_key = true;
        return 0;
 }
 
 static int setup_per_mode_key(struct fscrypt_info *ci,
-                             struct fscrypt_master_key *mk)
+                             struct fscrypt_master_key *mk,
+                             struct crypto_skcipher **tfms,
+                             u8 hkdf_context, bool include_fs_uuid)
 {
+       const struct inode *inode = ci->ci_inode;
+       const struct super_block *sb = inode->i_sb;
        struct fscrypt_mode *mode = ci->ci_mode;
        u8 mode_num = mode - available_modes;
        struct crypto_skcipher *tfm, *prev_tfm;
        u8 mode_key[FSCRYPT_MAX_KEY_SIZE];
+       u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
+       unsigned int hkdf_infolen = 0;
        int err;
 
-       if (WARN_ON(mode_num >= ARRAY_SIZE(mk->mk_mode_keys)))
+       if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX))
                return -EINVAL;
 
        /* pairs with cmpxchg() below */
-       tfm = READ_ONCE(mk->mk_mode_keys[mode_num]);
+       tfm = READ_ONCE(tfms[mode_num]);
        if (likely(tfm != NULL))
                goto done;
 
        BUILD_BUG_ON(sizeof(mode_num) != 1);
+       BUILD_BUG_ON(sizeof(sb->s_uuid) != 16);
+       BUILD_BUG_ON(sizeof(hkdf_info) != 17);
+       hkdf_info[hkdf_infolen++] = mode_num;
+       if (include_fs_uuid) {
+               memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid,
+                      sizeof(sb->s_uuid));
+               hkdf_infolen += sizeof(sb->s_uuid);
+       }
        err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
-                                 HKDF_CONTEXT_PER_MODE_KEY,
-                                 &mode_num, sizeof(mode_num),
+                                 hkdf_context, hkdf_info, hkdf_infolen,
                                  mode_key, mode->keysize);
        if (err)
                return err;
-       tfm = fscrypt_allocate_skcipher(mode, mode_key, ci->ci_inode);
+       tfm = fscrypt_allocate_skcipher(mode, mode_key, inode);
        memzero_explicit(mode_key, mode->keysize);
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
        /* pairs with READ_ONCE() above */
-       prev_tfm = cmpxchg(&mk->mk_mode_keys[mode_num], NULL, tfm);
+       prev_tfm = cmpxchg(&tfms[mode_num], NULL, tfm);
        if (prev_tfm != NULL) {
                crypto_free_skcipher(tfm);
                tfm = prev_tfm;
                                     ci->ci_mode->friendly_name);
                        return -EINVAL;
                }
-               return setup_per_mode_key(ci, mk);
+               return setup_per_mode_key(ci, mk, mk->mk_direct_tfms,
+                                         HKDF_CONTEXT_DIRECT_KEY, false);
+       } else if (ci->ci_policy.v2.flags &
+                  FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
+               /*
+                * IV_INO_LBLK_64: encryption keys are derived from (master_key,
+                * mode_num, filesystem_uuid), and inode number is included in
+                * the IVs.  This format is optimized for use with inline
+                * encryption hardware compliant with the UFS or eMMC standards.
+                */
+               return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms,
+                                         HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
+                                         true);
        }
 
        err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
 
        if (ci->ci_direct_key)
                fscrypt_put_direct_key(ci->ci_direct_key);
-       else if (ci->ci_ctfm != NULL &&
-                !fscrypt_is_direct_key_policy(&ci->ci_policy))
+       else if (ci->ci_owns_key)
                crypto_free_skcipher(ci->ci_ctfm);
 
        key = ci->ci_master_key;
 
        return !memcmp(policy1, policy2, fscrypt_policy_size(policy1));
 }
 
+static bool supported_iv_ino_lblk_64_policy(
+                                       const struct fscrypt_policy_v2 *policy,
+                                       const struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+       int ino_bits = 64, lblk_bits = 64;
+
+       if (policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
+               fscrypt_warn(inode,
+                            "The DIRECT_KEY and IV_INO_LBLK_64 flags are mutually exclusive");
+               return false;
+       }
+       /*
+        * It's unsafe to include inode numbers in the IVs if the filesystem can
+        * potentially renumber inodes, e.g. via filesystem shrinking.
+        */
+       if (!sb->s_cop->has_stable_inodes ||
+           !sb->s_cop->has_stable_inodes(sb)) {
+               fscrypt_warn(inode,
+                            "Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't have stable inode numbers",
+                            sb->s_id);
+               return false;
+       }
+       if (sb->s_cop->get_ino_and_lblk_bits)
+               sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
+       if (ino_bits > 32 || lblk_bits > 32) {
+               fscrypt_warn(inode,
+                            "Can't use IV_INO_LBLK_64 policy on filesystem '%s' because it doesn't use 32-bit inode and block numbers",
+                            sb->s_id);
+               return false;
+       }
+       return true;
+}
+
 /**
  * fscrypt_supported_policy - check whether an encryption policy is supported
  *
                        return false;
                }
 
-               if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) {
+               if (policy->flags & ~(FSCRYPT_POLICY_FLAGS_PAD_MASK |
+                                     FSCRYPT_POLICY_FLAG_DIRECT_KEY)) {
                        fscrypt_warn(inode,
                                     "Unsupported encryption flags (0x%02x)",
                                     policy->flags);
                        return false;
                }
 
+               if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) &&
+                   !supported_iv_ino_lblk_64_policy(policy, inode))
+                       return false;
+
                if (memchr_inv(policy->__reserved, 0,
                               sizeof(policy->__reserved))) {
                        fscrypt_warn(inode,
 
        bool (*dummy_context)(struct inode *);
        bool (*empty_dir)(struct inode *);
        unsigned int max_namelen;
+       bool (*has_stable_inodes)(struct super_block *sb);
+       void (*get_ino_and_lblk_bits)(struct super_block *sb,
+                                     int *ino_bits_ret, int *lblk_bits_ret);
 };
 
 static inline bool fscrypt_has_encryption_key(const struct inode *inode)
 
 #define FSCRYPT_POLICY_FLAGS_PAD_32            0x03
 #define FSCRYPT_POLICY_FLAGS_PAD_MASK          0x03
 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY         0x04
-#define FSCRYPT_POLICY_FLAGS_VALID             0x07
+#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64     0x08
+#define FSCRYPT_POLICY_FLAGS_VALID             0x0F
 
 /* Encryption algorithms */
 #define FSCRYPT_MODE_AES_256_XTS               1