- Add the IV_INO_LBLK_64 encryption policy flag which modifies the
   encryption to be optimized for UFS inline encryption hardware.
 
 - For AES-128-CBC, use the crypto API's implementation of ESSIV (which
   was added in 5.4) rather than doing ESSIV manually.
 
 - A few other cleanups.
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCXdtVMxQcZWJpZ2dlcnNA
 Z29vZ2xlLmNvbQAKCRDzXCl4vpKOK8MVAP44iRzj8ZXu62BhqNOYYcF60s/58QfZ
 Jo1VdmvO/8MNrAD+P/jW5sqzcB5BLdNzS7pLKGIzsC55uMyp/79xyKK8wQc=
 =XKWV
 -----END PGP SIGNATURE-----

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt

Pull fscrypt updates from Eric Biggers:

 - Add the IV_INO_LBLK_64 encryption policy flag which modifies the
   encryption to be optimized for UFS inline encryption hardware.

 - For AES-128-CBC, use the crypto API's implementation of ESSIV (which
   was added in 5.4) rather than doing ESSIV manually.

 - A few other cleanups.

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
  f2fs: add support for IV_INO_LBLK_64 encryption policies
  ext4: add support for IV_INO_LBLK_64 encryption policies
  fscrypt: add support for IV_INO_LBLK_64 policies
  fscrypt: avoid data race on fscrypt_mode::logged_impl_name
  docs: ioctl-number: document fscrypt ioctl numbers
  fscrypt: zeroize fscrypt_info before freeing
  fscrypt: remove struct fscrypt_ctx
  fscrypt: invoke crypto API for ESSIV handling
This commit is contained in:
Linus Torvalds 2019-11-25 12:19:28 -08:00
Родитель ae36607b66 0eee17e332
Коммит ea4b71bc0b
14 изменённых файлов: 208 добавлений и 328 удалений

Просмотреть файл

@ -256,13 +256,8 @@ 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 the master keys may be wrapped in userspace, e.g. as is done by the
`fscrypt <https://github.com/google/fscrypt>`_ tool. `fscrypt <https://github.com/google/fscrypt>`_ tool.
Including the inode number in the IVs was considered. However, it was DIRECT_KEY policies
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
----------------------------
The Adiantum encryption mode (see `Encryption modes and usage`_) is The Adiantum encryption mode (see `Encryption modes and usage`_) is
suitable for both contents and filenames encryption, and it accepts suitable for both contents and filenames encryption, and it accepts
@ -285,6 +280,21 @@ IV. Moreover:
key derived using the KDF. Users may use the same master key for key derived using the KDF. Users may use the same master key for
other v2 encryption policies. 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 Key identifiers
--------------- ---------------
@ -308,8 +318,9 @@ 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 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 crypto accelerators such as CAAM or CESA that do not support XTS. To
use AES-128-CBC, CONFIG_CRYPTO_SHA256 (or another SHA-256 use AES-128-CBC, CONFIG_CRYPTO_ESSIV and CONFIG_CRYPTO_SHA256 (or
implementation) must be enabled so that ESSIV can be used. 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 Adiantum is a (primarily) stream cipher-based mode that is fast even
on CPUs without dedicated crypto instructions. It's also a true on CPUs without dedicated crypto instructions. It's also a true
@ -341,10 +352,16 @@ a little endian number, except that:
is encrypted with AES-256 where the AES-256 key is the SHA-256 hash is encrypted with AES-256 where the AES-256 key is the SHA-256 hash
of the file's data encryption key. of the file's data encryption key.
- In the "direct key" configuration (FSCRYPT_POLICY_FLAG_DIRECT_KEY - With `DIRECT_KEY policies`_, the file's nonce is appended to the IV.
set in the fscrypt_policy), the file's nonce is also appended to the Currently this is only allowed with the Adiantum encryption mode.
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 encryption
-------------------- --------------------
@ -354,10 +371,10 @@ the requirements to retain support for efficient directory lookups and
filenames of up to 255 bytes, the same IV is used for every filename filenames of up to 255 bytes, the same IV is used for every filename
in a directory. in a directory.
However, each encrypted directory still uses a unique key; or However, each encrypted directory still uses a unique key, or
alternatively (for the "direct key" configuration) has the file's alternatively has the file's nonce (for `DIRECT_KEY policies`_) or
nonce included in the IVs. Thus, IV reuse is limited to within a inode number (for `IV_INO_LBLK_64 policies`_) included in the IVs.
single directory. Thus, IV reuse is limited to within a single directory.
With CTS-CBC, the IV reuse means that when the plaintext filenames 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 share a common prefix at least as long as the cipher block size (16
@ -431,12 +448,15 @@ This structure must be initialized as follows:
(1) for ``contents_encryption_mode`` and FSCRYPT_MODE_AES_256_CTS (1) for ``contents_encryption_mode`` and FSCRYPT_MODE_AES_256_CTS
(4) for ``filenames_encryption_mode``. (4) for ``filenames_encryption_mode``.
- ``flags`` must contain a value from ``<linux/fscrypt.h>`` which - ``flags`` contains optional flags from ``<linux/fscrypt.h>``:
identifies the amount of NUL-padding to use when encrypting
filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32 (0x3). - FSCRYPT_POLICY_FLAGS_PAD_*: The amount of NUL padding to use when
Additionally, if the encryption modes are both encrypting filenames. If unsure, use FSCRYPT_POLICY_FLAGS_PAD_32
FSCRYPT_MODE_ADIANTUM, this can contain (0x3).
FSCRYPT_POLICY_FLAG_DIRECT_KEY; see `DIRECT_KEY and per-mode keys`_. - 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. - For v2 encryption policies, ``__reserved`` must be zeroed.
@ -1089,7 +1109,7 @@ policy structs (see `Setting an encryption policy`_), except that the
context structs also contain a nonce. The nonce is randomly generated 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 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 different files to be encrypted differently; see `Per-file keys`_ and
`DIRECT_KEY and per-mode keys`_. `DIRECT_KEY policies`_.
Data path changes Data path changes
----------------- -----------------

Просмотреть файл

@ -233,6 +233,7 @@ Code Seq# Include File Comments
'f' 00-0F fs/ext4/ext4.h conflict! 'f' 00-0F fs/ext4/ext4.h conflict!
'f' 00-0F linux/fs.h conflict! 'f' 00-0F linux/fs.h conflict!
'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict! 'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict!
'f' 13-27 linux/fscrypt.h
'f' 81-8F linux/fsverity.h 'f' 81-8F linux/fsverity.h
'g' 00-0F linux/usb/gadgetfs.h 'g' 00-0F linux/usb/gadgetfs.h
'g' 20-2F linux/usb/g_printer.h 'g' 20-2F linux/usb/g_printer.h

Просмотреть файл

@ -26,7 +26,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
static void __fscrypt_decrypt_bio(struct bio *bio, bool done) void fscrypt_decrypt_bio(struct bio *bio)
{ {
struct bio_vec *bv; struct bio_vec *bv;
struct bvec_iter_all iter_all; struct bvec_iter_all iter_all;
@ -37,37 +37,10 @@ static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
bv->bv_offset); bv->bv_offset);
if (ret) if (ret)
SetPageError(page); SetPageError(page);
else if (done)
SetPageUptodate(page);
if (done)
unlock_page(page);
} }
} }
void fscrypt_decrypt_bio(struct bio *bio)
{
__fscrypt_decrypt_bio(bio, false);
}
EXPORT_SYMBOL(fscrypt_decrypt_bio); EXPORT_SYMBOL(fscrypt_decrypt_bio);
static void completion_pages(struct work_struct *work)
{
struct fscrypt_ctx *ctx = container_of(work, struct fscrypt_ctx, work);
struct bio *bio = ctx->bio;
__fscrypt_decrypt_bio(bio, true);
fscrypt_release_ctx(ctx);
bio_put(bio);
}
void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
{
INIT_WORK(&ctx->work, completion_pages);
ctx->bio = bio;
fscrypt_enqueue_decrypt_work(&ctx->work);
}
EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len) sector_t pblk, unsigned int len)
{ {

Просмотреть файл

@ -27,29 +27,20 @@
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <crypto/aes.h>
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
static unsigned int num_prealloc_crypto_pages = 32; static unsigned int num_prealloc_crypto_pages = 32;
static unsigned int num_prealloc_crypto_ctxs = 128;
module_param(num_prealloc_crypto_pages, uint, 0444); module_param(num_prealloc_crypto_pages, uint, 0444);
MODULE_PARM_DESC(num_prealloc_crypto_pages, MODULE_PARM_DESC(num_prealloc_crypto_pages,
"Number of crypto pages to preallocate"); "Number of crypto pages to preallocate");
module_param(num_prealloc_crypto_ctxs, uint, 0444);
MODULE_PARM_DESC(num_prealloc_crypto_ctxs,
"Number of crypto contexts to preallocate");
static mempool_t *fscrypt_bounce_page_pool = NULL; static mempool_t *fscrypt_bounce_page_pool = NULL;
static LIST_HEAD(fscrypt_free_ctxs);
static DEFINE_SPINLOCK(fscrypt_ctx_lock);
static struct workqueue_struct *fscrypt_read_workqueue; static struct workqueue_struct *fscrypt_read_workqueue;
static DEFINE_MUTEX(fscrypt_init_mutex); static DEFINE_MUTEX(fscrypt_init_mutex);
static struct kmem_cache *fscrypt_ctx_cachep;
struct kmem_cache *fscrypt_info_cachep; struct kmem_cache *fscrypt_info_cachep;
void fscrypt_enqueue_decrypt_work(struct work_struct *work) void fscrypt_enqueue_decrypt_work(struct work_struct *work)
@ -58,62 +49,6 @@ void fscrypt_enqueue_decrypt_work(struct work_struct *work)
} }
EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
/**
* fscrypt_release_ctx() - Release a decryption context
* @ctx: The decryption context to release.
*
* If the decryption context was allocated from the pre-allocated pool, return
* it to that pool. Else, free it.
*/
void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
{
unsigned long flags;
if (ctx->flags & FS_CTX_REQUIRES_FREE_ENCRYPT_FL) {
kmem_cache_free(fscrypt_ctx_cachep, ctx);
} else {
spin_lock_irqsave(&fscrypt_ctx_lock, flags);
list_add(&ctx->free_list, &fscrypt_free_ctxs);
spin_unlock_irqrestore(&fscrypt_ctx_lock, flags);
}
}
EXPORT_SYMBOL(fscrypt_release_ctx);
/**
* fscrypt_get_ctx() - Get a decryption context
* @gfp_flags: The gfp flag for memory allocation
*
* Allocate and initialize a decryption context.
*
* Return: A new decryption context on success; an ERR_PTR() otherwise.
*/
struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
{
struct fscrypt_ctx *ctx;
unsigned long flags;
/*
* First try getting a ctx from the free list so that we don't have to
* call into the slab allocator.
*/
spin_lock_irqsave(&fscrypt_ctx_lock, flags);
ctx = list_first_entry_or_null(&fscrypt_free_ctxs,
struct fscrypt_ctx, free_list);
if (ctx)
list_del(&ctx->free_list);
spin_unlock_irqrestore(&fscrypt_ctx_lock, flags);
if (!ctx) {
ctx = kmem_cache_zalloc(fscrypt_ctx_cachep, gfp_flags);
if (!ctx)
return ERR_PTR(-ENOMEM);
ctx->flags |= FS_CTX_REQUIRES_FREE_ENCRYPT_FL;
} else {
ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL;
}
return ctx;
}
EXPORT_SYMBOL(fscrypt_get_ctx);
struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags) struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)
{ {
return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); return mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
@ -138,14 +73,17 @@ EXPORT_SYMBOL(fscrypt_free_bounce_page);
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
const struct fscrypt_info *ci) const struct fscrypt_info *ci)
{ {
u8 flags = fscrypt_policy_flags(&ci->ci_policy);
memset(iv, 0, ci->ci_mode->ivsize); 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); memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE);
}
if (ci->ci_essiv_tfm != NULL) iv->lblk_num = cpu_to_le64(lblk_num);
crypto_cipher_encrypt_one(ci->ci_essiv_tfm, iv->raw, iv->raw);
} }
/* Encrypt or decrypt a single filesystem block of file contents */ /* Encrypt or decrypt a single filesystem block of file contents */
@ -396,17 +334,6 @@ const struct dentry_operations fscrypt_d_ops = {
.d_revalidate = fscrypt_d_revalidate, .d_revalidate = fscrypt_d_revalidate,
}; };
static void fscrypt_destroy(void)
{
struct fscrypt_ctx *pos, *n;
list_for_each_entry_safe(pos, n, &fscrypt_free_ctxs, free_list)
kmem_cache_free(fscrypt_ctx_cachep, pos);
INIT_LIST_HEAD(&fscrypt_free_ctxs);
mempool_destroy(fscrypt_bounce_page_pool);
fscrypt_bounce_page_pool = NULL;
}
/** /**
* fscrypt_initialize() - allocate major buffers for fs encryption. * fscrypt_initialize() - allocate major buffers for fs encryption.
* @cop_flags: fscrypt operations flags * @cop_flags: fscrypt operations flags
@ -414,11 +341,11 @@ static void fscrypt_destroy(void)
* We only call this when we start accessing encrypted files, since it * We only call this when we start accessing encrypted files, since it
* results in memory getting allocated that wouldn't otherwise be used. * results in memory getting allocated that wouldn't otherwise be used.
* *
* Return: Zero on success, non-zero otherwise. * Return: 0 on success; -errno on failure
*/ */
int fscrypt_initialize(unsigned int cop_flags) int fscrypt_initialize(unsigned int cop_flags)
{ {
int i, res = -ENOMEM; int err = 0;
/* No need to allocate a bounce page pool if this FS won't use it. */ /* No need to allocate a bounce page pool if this FS won't use it. */
if (cop_flags & FS_CFLG_OWN_PAGES) if (cop_flags & FS_CFLG_OWN_PAGES)
@ -426,29 +353,18 @@ int fscrypt_initialize(unsigned int cop_flags)
mutex_lock(&fscrypt_init_mutex); mutex_lock(&fscrypt_init_mutex);
if (fscrypt_bounce_page_pool) if (fscrypt_bounce_page_pool)
goto already_initialized; goto out_unlock;
for (i = 0; i < num_prealloc_crypto_ctxs; i++) {
struct fscrypt_ctx *ctx;
ctx = kmem_cache_zalloc(fscrypt_ctx_cachep, GFP_NOFS);
if (!ctx)
goto fail;
list_add(&ctx->free_list, &fscrypt_free_ctxs);
}
err = -ENOMEM;
fscrypt_bounce_page_pool = fscrypt_bounce_page_pool =
mempool_create_page_pool(num_prealloc_crypto_pages, 0); mempool_create_page_pool(num_prealloc_crypto_pages, 0);
if (!fscrypt_bounce_page_pool) if (!fscrypt_bounce_page_pool)
goto fail; goto out_unlock;
already_initialized: err = 0;
out_unlock:
mutex_unlock(&fscrypt_init_mutex); mutex_unlock(&fscrypt_init_mutex);
return 0; return err;
fail:
fscrypt_destroy();
mutex_unlock(&fscrypt_init_mutex);
return res;
} }
void fscrypt_msg(const struct inode *inode, const char *level, void fscrypt_msg(const struct inode *inode, const char *level,
@ -494,13 +410,9 @@ static int __init fscrypt_init(void)
if (!fscrypt_read_workqueue) if (!fscrypt_read_workqueue)
goto fail; goto fail;
fscrypt_ctx_cachep = KMEM_CACHE(fscrypt_ctx, SLAB_RECLAIM_ACCOUNT);
if (!fscrypt_ctx_cachep)
goto fail_free_queue;
fscrypt_info_cachep = KMEM_CACHE(fscrypt_info, SLAB_RECLAIM_ACCOUNT); fscrypt_info_cachep = KMEM_CACHE(fscrypt_info, SLAB_RECLAIM_ACCOUNT);
if (!fscrypt_info_cachep) if (!fscrypt_info_cachep)
goto fail_free_ctx; goto fail_free_queue;
err = fscrypt_init_keyring(); err = fscrypt_init_keyring();
if (err) if (err)
@ -510,8 +422,6 @@ static int __init fscrypt_init(void)
fail_free_info: fail_free_info:
kmem_cache_destroy(fscrypt_info_cachep); kmem_cache_destroy(fscrypt_info_cachep);
fail_free_ctx:
kmem_cache_destroy(fscrypt_ctx_cachep);
fail_free_queue: fail_free_queue:
destroy_workqueue(fscrypt_read_workqueue); destroy_workqueue(fscrypt_read_workqueue);
fail: fail:

Просмотреть файл

@ -163,11 +163,8 @@ struct fscrypt_info {
/* The actual crypto transform used for encryption and decryption */ /* The actual crypto transform used for encryption and decryption */
struct crypto_skcipher *ci_ctfm; struct crypto_skcipher *ci_ctfm;
/* /* True if the key should be freed when this fscrypt_info is freed */
* Cipher for ESSIV IV generation. Only set for CBC contents bool ci_owns_key;
* encryption, otherwise is NULL.
*/
struct crypto_cipher *ci_essiv_tfm;
/* /*
* Encryption mode used for this inode. It corresponds to either the * Encryption mode used for this inode. It corresponds to either the
@ -209,8 +206,6 @@ typedef enum {
FS_ENCRYPT, FS_ENCRYPT,
} fscrypt_direction_t; } fscrypt_direction_t;
#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
static inline bool fscrypt_valid_enc_modes(u32 contents_mode, static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
u32 filenames_mode) u32 filenames_mode)
{ {
@ -289,7 +284,8 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
*/ */
#define HKDF_CONTEXT_KEY_IDENTIFIER 1 #define HKDF_CONTEXT_KEY_IDENTIFIER 1
#define HKDF_CONTEXT_PER_FILE_KEY 2 #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, extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context,
const u8 *info, unsigned int infolen, const u8 *info, unsigned int infolen,
@ -386,8 +382,14 @@ struct fscrypt_master_key {
struct list_head mk_decrypted_inodes; struct list_head mk_decrypted_inodes;
spinlock_t mk_decrypted_inodes_lock; spinlock_t mk_decrypted_inodes_lock;
/* Per-mode tfms for DIRECT_KEY policies, allocated on-demand */ /* Crypto API transforms for DIRECT_KEY policies, allocated on-demand */
struct crypto_skcipher *mk_mode_keys[__FSCRYPT_MODE_MAX + 1]; 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; } __randomize_layout;
@ -443,8 +445,7 @@ struct fscrypt_mode {
const char *cipher_str; const char *cipher_str;
int keysize; int keysize;
int ivsize; int ivsize;
bool logged_impl_name; int logged_impl_name;
bool needs_essiv;
}; };
static inline bool static inline bool

Просмотреть файл

@ -43,8 +43,10 @@ static void free_master_key(struct fscrypt_master_key *mk)
wipe_master_key_secret(&mk->mk_secret); wipe_master_key_secret(&mk->mk_secret);
for (i = 0; i < ARRAY_SIZE(mk->mk_mode_keys); i++) for (i = 0; i <= __FSCRYPT_MODE_MAX; i++) {
crypto_free_skcipher(mk->mk_mode_keys[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); key_put(mk->mk_users);
kzfree(mk); kzfree(mk);

Просмотреть файл

@ -8,15 +8,11 @@
* Heavily modified since then. * Heavily modified since then.
*/ */
#include <crypto/aes.h>
#include <crypto/sha.h>
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include <linux/key.h> #include <linux/key.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
static struct crypto_shash *essiv_hash_tfm;
static struct fscrypt_mode available_modes[] = { static struct fscrypt_mode available_modes[] = {
[FSCRYPT_MODE_AES_256_XTS] = { [FSCRYPT_MODE_AES_256_XTS] = {
.friendly_name = "AES-256-XTS", .friendly_name = "AES-256-XTS",
@ -31,11 +27,10 @@ static struct fscrypt_mode available_modes[] = {
.ivsize = 16, .ivsize = 16,
}, },
[FSCRYPT_MODE_AES_128_CBC] = { [FSCRYPT_MODE_AES_128_CBC] = {
.friendly_name = "AES-128-CBC", .friendly_name = "AES-128-CBC-ESSIV",
.cipher_str = "cbc(aes)", .cipher_str = "essiv(cbc(aes),sha256)",
.keysize = 16, .keysize = 16,
.ivsize = 16, .ivsize = 16,
.needs_essiv = true,
}, },
[FSCRYPT_MODE_AES_128_CTS] = { [FSCRYPT_MODE_AES_128_CTS] = {
.friendly_name = "AES-128-CTS-CBC", .friendly_name = "AES-128-CTS-CBC",
@ -86,15 +81,13 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
mode->cipher_str, PTR_ERR(tfm)); mode->cipher_str, PTR_ERR(tfm));
return tfm; return tfm;
} }
if (unlikely(!mode->logged_impl_name)) { if (!xchg(&mode->logged_impl_name, 1)) {
/* /*
* fscrypt performance can vary greatly depending on which * fscrypt performance can vary greatly depending on which
* crypto algorithm implementation is used. Help people debug * crypto algorithm implementation is used. Help people debug
* performance problems by logging the ->cra_driver_name the * performance problems by logging the ->cra_driver_name the
* first time a mode is used. Note that multiple threads can * first time a mode is used.
* race here, but it doesn't really matter.
*/ */
mode->logged_impl_name = true;
pr_info("fscrypt: %s using implementation \"%s\"\n", pr_info("fscrypt: %s using implementation \"%s\"\n",
mode->friendly_name, mode->friendly_name,
crypto_skcipher_alg(tfm)->base.cra_driver_name); crypto_skcipher_alg(tfm)->base.cra_driver_name);
@ -111,131 +104,64 @@ err_free_tfm:
return ERR_PTR(err); return ERR_PTR(err);
} }
static int derive_essiv_salt(const u8 *key, int keysize, u8 *salt) /* Given the per-file key, set up the file's crypto transform object */
{
struct crypto_shash *tfm = READ_ONCE(essiv_hash_tfm);
/* init hash transform on demand */
if (unlikely(!tfm)) {
struct crypto_shash *prev_tfm;
tfm = crypto_alloc_shash("sha256", 0, 0);
if (IS_ERR(tfm)) {
if (PTR_ERR(tfm) == -ENOENT) {
fscrypt_warn(NULL,
"Missing crypto API support for SHA-256");
return -ENOPKG;
}
fscrypt_err(NULL,
"Error allocating SHA-256 transform: %ld",
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
prev_tfm = cmpxchg(&essiv_hash_tfm, NULL, tfm);
if (prev_tfm) {
crypto_free_shash(tfm);
tfm = prev_tfm;
}
}
{
SHASH_DESC_ON_STACK(desc, tfm);
desc->tfm = tfm;
return crypto_shash_digest(desc, key, keysize, salt);
}
}
static int init_essiv_generator(struct fscrypt_info *ci, const u8 *raw_key,
int keysize)
{
int err;
struct crypto_cipher *essiv_tfm;
u8 salt[SHA256_DIGEST_SIZE];
if (WARN_ON(ci->ci_mode->ivsize != AES_BLOCK_SIZE))
return -EINVAL;
essiv_tfm = crypto_alloc_cipher("aes", 0, 0);
if (IS_ERR(essiv_tfm))
return PTR_ERR(essiv_tfm);
ci->ci_essiv_tfm = essiv_tfm;
err = derive_essiv_salt(raw_key, keysize, salt);
if (err)
goto out;
/*
* Using SHA256 to derive the salt/key will result in AES-256 being
* used for IV generation. File contents encryption will still use the
* configured keysize (AES-128) nevertheless.
*/
err = crypto_cipher_setkey(essiv_tfm, salt, sizeof(salt));
if (err)
goto out;
out:
memzero_explicit(salt, sizeof(salt));
return err;
}
/* Given the per-file key, set up the file's crypto transform object(s) */
int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key)
{ {
struct fscrypt_mode *mode = ci->ci_mode; struct crypto_skcipher *tfm;
struct crypto_skcipher *ctfm;
int err;
ctfm = fscrypt_allocate_skcipher(mode, derived_key, ci->ci_inode); tfm = fscrypt_allocate_skcipher(ci->ci_mode, derived_key, ci->ci_inode);
if (IS_ERR(ctfm)) if (IS_ERR(tfm))
return PTR_ERR(ctfm); return PTR_ERR(tfm);
ci->ci_ctfm = ctfm; ci->ci_ctfm = tfm;
ci->ci_owns_key = true;
if (mode->needs_essiv) {
err = init_essiv_generator(ci, derived_key, mode->keysize);
if (err) {
fscrypt_warn(ci->ci_inode,
"Error initializing ESSIV generator: %d",
err);
return err;
}
}
return 0; return 0;
} }
static int setup_per_mode_key(struct fscrypt_info *ci, 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; struct fscrypt_mode *mode = ci->ci_mode;
u8 mode_num = mode - available_modes; u8 mode_num = mode - available_modes;
struct crypto_skcipher *tfm, *prev_tfm; struct crypto_skcipher *tfm, *prev_tfm;
u8 mode_key[FSCRYPT_MAX_KEY_SIZE]; u8 mode_key[FSCRYPT_MAX_KEY_SIZE];
u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
unsigned int hkdf_infolen = 0;
int err; int err;
if (WARN_ON(mode_num >= ARRAY_SIZE(mk->mk_mode_keys))) if (WARN_ON(mode_num > __FSCRYPT_MODE_MAX))
return -EINVAL; return -EINVAL;
/* pairs with cmpxchg() below */ /* pairs with cmpxchg() below */
tfm = READ_ONCE(mk->mk_mode_keys[mode_num]); tfm = READ_ONCE(tfms[mode_num]);
if (likely(tfm != NULL)) if (likely(tfm != NULL))
goto done; goto done;
BUILD_BUG_ON(sizeof(mode_num) != 1); 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, err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
HKDF_CONTEXT_PER_MODE_KEY, hkdf_context, hkdf_info, hkdf_infolen,
&mode_num, sizeof(mode_num),
mode_key, mode->keysize); mode_key, mode->keysize);
if (err) if (err)
return 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); memzero_explicit(mode_key, mode->keysize);
if (IS_ERR(tfm)) if (IS_ERR(tfm))
return PTR_ERR(tfm); return PTR_ERR(tfm);
/* pairs with READ_ONCE() above */ /* 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) { if (prev_tfm != NULL) {
crypto_free_skcipher(tfm); crypto_free_skcipher(tfm);
tfm = prev_tfm; tfm = prev_tfm;
@ -266,7 +192,19 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
ci->ci_mode->friendly_name); ci->ci_mode->friendly_name);
return -EINVAL; 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, err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
@ -388,13 +326,10 @@ static void put_crypt_info(struct fscrypt_info *ci)
if (!ci) if (!ci)
return; return;
if (ci->ci_direct_key) { if (ci->ci_direct_key)
fscrypt_put_direct_key(ci->ci_direct_key); fscrypt_put_direct_key(ci->ci_direct_key);
} else if ((ci->ci_ctfm != NULL || ci->ci_essiv_tfm != NULL) && else if (ci->ci_owns_key)
!fscrypt_is_direct_key_policy(&ci->ci_policy)) {
crypto_free_skcipher(ci->ci_ctfm); crypto_free_skcipher(ci->ci_ctfm);
crypto_free_cipher(ci->ci_essiv_tfm);
}
key = ci->ci_master_key; key = ci->ci_master_key;
if (key) { if (key) {
@ -415,6 +350,7 @@ static void put_crypt_info(struct fscrypt_info *ci)
key_invalidate(key); key_invalidate(key);
key_put(key); key_put(key);
} }
memzero_explicit(ci, sizeof(*ci));
kmem_cache_free(fscrypt_info_cachep, ci); kmem_cache_free(fscrypt_info_cachep, ci);
} }

Просмотреть файл

@ -270,10 +270,6 @@ static int setup_v1_file_key_direct(struct fscrypt_info *ci,
return -EINVAL; return -EINVAL;
} }
/* ESSIV implies 16-byte IVs which implies !DIRECT_KEY */
if (WARN_ON(mode->needs_essiv))
return -EINVAL;
dk = fscrypt_get_direct_key(ci, raw_master_key); dk = fscrypt_get_direct_key(ci, raw_master_key);
if (IS_ERR(dk)) if (IS_ERR(dk))
return PTR_ERR(dk); return PTR_ERR(dk);

Просмотреть файл

@ -29,6 +29,40 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
return !memcmp(policy1, policy2, fscrypt_policy_size(policy1)); 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 * fscrypt_supported_policy - check whether an encryption policy is supported
* *
@ -55,7 +89,8 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
return false; 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, fscrypt_warn(inode,
"Unsupported encryption flags (0x%02x)", "Unsupported encryption flags (0x%02x)",
policy->flags); policy->flags);
@ -83,6 +118,10 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
return false; 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, if (memchr_inv(policy->__reserved, 0,
sizeof(policy->__reserved))) { sizeof(policy->__reserved))) {
fscrypt_warn(inode, fscrypt_warn(inode,

Просмотреть файл

@ -1678,6 +1678,7 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
#define EXT4_FEATURE_COMPAT_RESIZE_INODE 0x0010 #define EXT4_FEATURE_COMPAT_RESIZE_INODE 0x0010
#define EXT4_FEATURE_COMPAT_DIR_INDEX 0x0020 #define EXT4_FEATURE_COMPAT_DIR_INDEX 0x0020
#define EXT4_FEATURE_COMPAT_SPARSE_SUPER2 0x0200 #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2 0x0200
#define EXT4_FEATURE_COMPAT_STABLE_INODES 0x0800
#define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 #define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
@ -1779,6 +1780,7 @@ EXT4_FEATURE_COMPAT_FUNCS(xattr, EXT_ATTR)
EXT4_FEATURE_COMPAT_FUNCS(resize_inode, RESIZE_INODE) EXT4_FEATURE_COMPAT_FUNCS(resize_inode, RESIZE_INODE)
EXT4_FEATURE_COMPAT_FUNCS(dir_index, DIR_INDEX) EXT4_FEATURE_COMPAT_FUNCS(dir_index, DIR_INDEX)
EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, SPARSE_SUPER2) EXT4_FEATURE_COMPAT_FUNCS(sparse_super2, SPARSE_SUPER2)
EXT4_FEATURE_COMPAT_FUNCS(stable_inodes, STABLE_INODES)
EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, SPARSE_SUPER) EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super, SPARSE_SUPER)
EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, LARGE_FILE) EXT4_FEATURE_RO_COMPAT_FUNCS(large_file, LARGE_FILE)

Просмотреть файл

@ -1345,6 +1345,18 @@ static bool ext4_dummy_context(struct inode *inode)
return DUMMY_ENCRYPTION_ENABLED(EXT4_SB(inode->i_sb)); return DUMMY_ENCRYPTION_ENABLED(EXT4_SB(inode->i_sb));
} }
static bool ext4_has_stable_inodes(struct super_block *sb)
{
return ext4_has_feature_stable_inodes(sb);
}
static void ext4_get_ino_and_lblk_bits(struct super_block *sb,
int *ino_bits_ret, int *lblk_bits_ret)
{
*ino_bits_ret = 8 * sizeof(EXT4_SB(sb)->s_es->s_inodes_count);
*lblk_bits_ret = 8 * sizeof(ext4_lblk_t);
}
static const struct fscrypt_operations ext4_cryptops = { static const struct fscrypt_operations ext4_cryptops = {
.key_prefix = "ext4:", .key_prefix = "ext4:",
.get_context = ext4_get_context, .get_context = ext4_get_context,
@ -1352,6 +1364,8 @@ static const struct fscrypt_operations ext4_cryptops = {
.dummy_context = ext4_dummy_context, .dummy_context = ext4_dummy_context,
.empty_dir = ext4_empty_dir, .empty_dir = ext4_empty_dir,
.max_namelen = EXT4_NAME_LEN, .max_namelen = EXT4_NAME_LEN,
.has_stable_inodes = ext4_has_stable_inodes,
.get_ino_and_lblk_bits = ext4_get_ino_and_lblk_bits,
}; };
#endif #endif

Просмотреть файл

@ -2308,13 +2308,27 @@ static bool f2fs_dummy_context(struct inode *inode)
return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode)); return DUMMY_ENCRYPTION_ENABLED(F2FS_I_SB(inode));
} }
static bool f2fs_has_stable_inodes(struct super_block *sb)
{
return true;
}
static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
int *ino_bits_ret, int *lblk_bits_ret)
{
*ino_bits_ret = 8 * sizeof(nid_t);
*lblk_bits_ret = 8 * sizeof(block_t);
}
static const struct fscrypt_operations f2fs_cryptops = { static const struct fscrypt_operations f2fs_cryptops = {
.key_prefix = "f2fs:", .key_prefix = "f2fs:",
.get_context = f2fs_get_context, .get_context = f2fs_get_context,
.set_context = f2fs_set_context, .set_context = f2fs_set_context,
.dummy_context = f2fs_dummy_context, .dummy_context = f2fs_dummy_context,
.empty_dir = f2fs_empty_dir, .empty_dir = f2fs_empty_dir,
.max_namelen = F2FS_NAME_LEN, .max_namelen = F2FS_NAME_LEN,
.has_stable_inodes = f2fs_has_stable_inodes,
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
}; };
#endif #endif

Просмотреть файл

@ -20,7 +20,6 @@
#define FS_CRYPTO_BLOCK_SIZE 16 #define FS_CRYPTO_BLOCK_SIZE 16
struct fscrypt_ctx;
struct fscrypt_info; struct fscrypt_info;
struct fscrypt_str { struct fscrypt_str {
@ -62,18 +61,9 @@ struct fscrypt_operations {
bool (*dummy_context)(struct inode *); bool (*dummy_context)(struct inode *);
bool (*empty_dir)(struct inode *); bool (*empty_dir)(struct inode *);
unsigned int max_namelen; unsigned int max_namelen;
}; bool (*has_stable_inodes)(struct super_block *sb);
void (*get_ino_and_lblk_bits)(struct super_block *sb,
/* Decryption work */ int *ino_bits_ret, int *lblk_bits_ret);
struct fscrypt_ctx {
union {
struct {
struct bio *bio;
struct work_struct work;
};
struct list_head free_list; /* Free list */
};
u8 flags; /* Flags */
}; };
static inline bool fscrypt_has_encryption_key(const struct inode *inode) static inline bool fscrypt_has_encryption_key(const struct inode *inode)
@ -102,8 +92,6 @@ static inline void fscrypt_handle_d_move(struct dentry *dentry)
/* crypto.c */ /* crypto.c */
extern void fscrypt_enqueue_decrypt_work(struct work_struct *); extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
extern struct fscrypt_ctx *fscrypt_get_ctx(gfp_t);
extern void fscrypt_release_ctx(struct fscrypt_ctx *);
extern struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, extern struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
unsigned int len, unsigned int len,
@ -244,8 +232,6 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
/* bio.c */ /* bio.c */
extern void fscrypt_decrypt_bio(struct bio *); extern void fscrypt_decrypt_bio(struct bio *);
extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
struct bio *bio);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int); unsigned int);
@ -295,16 +281,6 @@ static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
{ {
} }
static inline struct fscrypt_ctx *fscrypt_get_ctx(gfp_t gfp_flags)
{
return ERR_PTR(-EOPNOTSUPP);
}
static inline void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
{
return;
}
static inline struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, static inline struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
unsigned int len, unsigned int len,
unsigned int offs, unsigned int offs,
@ -484,11 +460,6 @@ static inline void fscrypt_decrypt_bio(struct bio *bio)
{ {
} }
static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
struct bio *bio)
{
}
static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, static inline int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len) sector_t pblk, unsigned int len)
{ {

Просмотреть файл

@ -17,7 +17,8 @@
#define FSCRYPT_POLICY_FLAGS_PAD_32 0x03 #define FSCRYPT_POLICY_FLAGS_PAD_32 0x03
#define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03 #define FSCRYPT_POLICY_FLAGS_PAD_MASK 0x03
#define FSCRYPT_POLICY_FLAG_DIRECT_KEY 0x04 #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 */ /* Encryption algorithms */
#define FSCRYPT_MODE_AES_256_XTS 1 #define FSCRYPT_MODE_AES_256_XTS 1