2019-10-25 06:44:29 +09:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* Inline encryption support for fscrypt
|
|
|
|
*
|
|
|
|
* Copyright 2019 Google LLC
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* With "inline encryption", the block layer handles the decryption/encryption
|
|
|
|
* as part of the bio, instead of the filesystem doing the crypto itself via
|
|
|
|
* crypto API. See Documentation/block/inline-encryption.rst. fscrypt still
|
|
|
|
* provides the key and IV to use.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/blk-crypto.h>
|
|
|
|
#include <linux/blkdev.h>
|
|
|
|
#include <linux/buffer_head.h>
|
2020-01-16 11:41:54 +09:00
|
|
|
#include <linux/keyslot-manager.h>
|
2020-06-17 06:33:37 +09:00
|
|
|
#include <linux/sched/mm.h>
|
2020-08-07 15:18:13 +09:00
|
|
|
#include <linux/slab.h>
|
2020-05-20 08:11:59 +09:00
|
|
|
#include <linux/uio.h>
|
2019-10-25 06:44:29 +09:00
|
|
|
|
|
|
|
#include "fscrypt_private.h"
|
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
struct fscrypt_blk_crypto_key {
|
|
|
|
struct blk_crypto_key base;
|
|
|
|
int num_devs;
|
|
|
|
struct request_queue *devs[];
|
|
|
|
};
|
|
|
|
|
2020-04-04 04:06:11 +09:00
|
|
|
static int fscrypt_get_num_devices(struct super_block *sb)
|
|
|
|
{
|
|
|
|
if (sb->s_cop->get_num_devices)
|
|
|
|
return sb->s_cop->get_num_devices(sb);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fscrypt_get_devices(struct super_block *sb, int num_devs,
|
|
|
|
struct request_queue **devs)
|
|
|
|
{
|
|
|
|
if (num_devs == 1)
|
|
|
|
devs[0] = bdev_get_queue(sb->s_bdev);
|
|
|
|
else
|
|
|
|
sb->s_cop->get_devices(sb, devs);
|
|
|
|
}
|
|
|
|
|
2020-05-07 06:15:06 +09:00
|
|
|
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
|
|
|
|
{
|
2020-05-07 06:15:07 +09:00
|
|
|
struct super_block *sb = ci->ci_inode->i_sb;
|
|
|
|
unsigned int flags = fscrypt_policy_flags(&ci->ci_policy);
|
|
|
|
int ino_bits = 64, lblk_bits = 64;
|
2020-05-07 06:15:06 +09:00
|
|
|
|
2020-05-07 06:15:07 +09:00
|
|
|
if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY)
|
|
|
|
return offsetofend(union fscrypt_iv, nonce);
|
2020-05-07 06:15:06 +09:00
|
|
|
|
2020-05-07 06:15:07 +09:00
|
|
|
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)
|
|
|
|
return sizeof(__le64);
|
|
|
|
|
BACKPORT: FROMLIST: fscrypt: add support for IV_INO_LBLK_32 policies
The eMMC inline crypto standard will only specify 32 DUN bits (a.k.a. IV
bits), unlike UFS's 64. IV_INO_LBLK_64 is therefore not applicable, but
an encryption format which uses one key per policy and permits the
moving of encrypted file contents (as f2fs's garbage collector requires)
is still desirable.
To support such hardware, add a new encryption format IV_INO_LBLK_32
that makes the best use of the 32 bits: the IV is set to
'SipHash-2-4(inode_number) + file_logical_block_number mod 2^32', where
the SipHash key is derived from the fscrypt master key. We hash only
the inode number and not also the block number, because we need to
maintain contiguity of DUNs to merge bios.
Unlike with IV_INO_LBLK_64, with this format IV reuse is possible; this
is unavoidable given the size of the DUN. This means this format should
only be used where the requirements of the first paragraph apply.
However, the hash spreads out the IVs in the whole usable range, and the
use of a keyed hash makes it difficult for an attacker to determine
which files use which IVs.
Besides the above differences, this flag works like IV_INO_LBLK_64 in
that on ext4 it is only allowed if the stable_inodes feature has been
enabled to prevent inode numbers and the filesystem UUID from changing.
Signed-off-by: Eric Biggers <ebiggers@google.com>
Link: https://lore.kernel.org/r/20200515204141.251098-1-ebiggers@kernel.org
(Resolved conflicts with inline encryption support. Besides the
necessary "straightforward" merge resolutions, also made
fscrypt_get_dun_bytes() aware of IV_INO_LBLK_32 and made IV_INO_LBLK_32
usable with wrapped keys.)
Test: 'atest vts_kernel_encryption_test' on Cuttlefish with
the IV_INO_LBLK_32 test added (http://aosp/1315024).
Also tested enabling this in the fstab for Cuttlefish
(using http://aosp/1315886).
Also ran 'kvm-xfstests -c ext4,f2fs -g encrypt', including my
work-in-progress xfstest for IV_INO_LBLK_32.
Bug: 144046242
Change-Id: I57df71d502bde0475efc906a0812102063ff2f2a
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-05-16 05:41:41 +09:00
|
|
|
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)
|
|
|
|
return sizeof(__le32);
|
|
|
|
|
2020-05-07 06:15:07 +09:00
|
|
|
/* Default case: IVs are just the file logical block number */
|
|
|
|
if (sb->s_cop->get_ino_and_lblk_bits)
|
|
|
|
sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
|
|
|
|
return DIV_ROUND_UP(lblk_bits, 8);
|
2020-05-07 06:15:06 +09:00
|
|
|
}
|
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
/* Enable inline encryption for this file if supported. */
|
2020-04-04 04:06:11 +09:00
|
|
|
int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
|
|
|
|
bool is_hw_wrapped_key)
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
|
|
|
const struct inode *inode = ci->ci_inode;
|
|
|
|
struct super_block *sb = inode->i_sb;
|
2020-06-17 06:33:37 +09:00
|
|
|
struct blk_crypto_config crypto_cfg;
|
2020-04-04 04:06:11 +09:00
|
|
|
int num_devs;
|
2020-06-17 06:33:37 +09:00
|
|
|
struct request_queue **devs;
|
2020-04-04 04:06:11 +09:00
|
|
|
int i;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
|
|
|
/* The file must need contents encryption, not filenames encryption */
|
2020-11-11 10:52:24 +09:00
|
|
|
if (!S_ISREG(inode->i_mode))
|
2020-04-04 04:06:11 +09:00
|
|
|
return 0;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2020-07-15 01:31:24 +09:00
|
|
|
/* The crypto mode must have a blk-crypto counterpart */
|
2020-06-17 06:33:37 +09:00
|
|
|
if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID)
|
2020-04-04 04:06:11 +09:00
|
|
|
return 0;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
|
|
|
/* The filesystem must be mounted with -o inlinecrypt */
|
2020-06-17 06:33:37 +09:00
|
|
|
if (!(sb->s_flags & SB_INLINECRYPT))
|
2020-04-04 04:06:11 +09:00
|
|
|
return 0;
|
|
|
|
|
2020-06-30 15:17:28 +09:00
|
|
|
/*
|
|
|
|
* When a page contains multiple logically contiguous filesystem blocks,
|
|
|
|
* some filesystem code only calls fscrypt_mergeable_bio() for the first
|
|
|
|
* block in the page. This is fine for most of fscrypt's IV generation
|
|
|
|
* strategies, where contiguous blocks imply contiguous IVs. But it
|
|
|
|
* doesn't work with IV_INO_LBLK_32. For now, simply exclude
|
|
|
|
* IV_INO_LBLK_32 with blocksize != PAGE_SIZE from inline encryption.
|
|
|
|
*/
|
|
|
|
if ((fscrypt_policy_flags(&ci->ci_policy) &
|
|
|
|
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) &&
|
|
|
|
sb->s_blocksize != PAGE_SIZE)
|
|
|
|
return 0;
|
|
|
|
|
2020-04-04 04:06:11 +09:00
|
|
|
/*
|
2020-07-15 01:31:24 +09:00
|
|
|
* On all the filesystem's devices, blk-crypto must support the crypto
|
|
|
|
* configuration that the file would use.
|
2020-04-04 04:06:11 +09:00
|
|
|
*/
|
2020-06-17 06:33:37 +09:00
|
|
|
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
|
|
|
|
crypto_cfg.data_unit_size = sb->s_blocksize;
|
|
|
|
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
|
|
|
|
crypto_cfg.is_hw_wrapped = is_hw_wrapped_key;
|
2020-04-04 04:06:11 +09:00
|
|
|
num_devs = fscrypt_get_num_devices(sb);
|
2020-09-17 13:11:32 +09:00
|
|
|
devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
|
2020-04-04 04:06:11 +09:00
|
|
|
if (!devs)
|
|
|
|
return -ENOMEM;
|
|
|
|
fscrypt_get_devices(sb, num_devs, devs);
|
|
|
|
|
|
|
|
for (i = 0; i < num_devs; i++) {
|
2020-06-17 06:33:37 +09:00
|
|
|
if (!blk_crypto_config_supported(devs[i], &crypto_cfg))
|
2020-04-04 04:06:11 +09:00
|
|
|
goto out_free_devs;
|
|
|
|
}
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
ci->ci_inlinecrypt = true;
|
2020-04-04 04:06:11 +09:00
|
|
|
out_free_devs:
|
|
|
|
kfree(devs);
|
2020-07-15 01:31:24 +09:00
|
|
|
|
2020-04-04 04:06:11 +09:00
|
|
|
return 0;
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|
|
|
const u8 *raw_key,
|
2020-01-16 11:41:54 +09:00
|
|
|
unsigned int raw_key_size,
|
2020-02-07 11:01:20 +09:00
|
|
|
bool is_hw_wrapped,
|
2019-12-18 07:26:29 +09:00
|
|
|
const struct fscrypt_info *ci)
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
2019-12-18 07:26:29 +09:00
|
|
|
const struct inode *inode = ci->ci_inode;
|
|
|
|
struct super_block *sb = inode->i_sb;
|
|
|
|
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
|
2020-06-17 06:33:37 +09:00
|
|
|
int num_devs = fscrypt_get_num_devices(sb);
|
2019-12-18 07:26:29 +09:00
|
|
|
int queue_refs = 0;
|
|
|
|
struct fscrypt_blk_crypto_key *blk_key;
|
2019-10-25 06:44:29 +09:00
|
|
|
int err;
|
2019-12-18 07:26:29 +09:00
|
|
|
int i;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2020-09-17 13:11:32 +09:00
|
|
|
blk_key = kzalloc(struct_size(blk_key, devs, num_devs), GFP_KERNEL);
|
2019-12-18 07:26:29 +09:00
|
|
|
if (!blk_key)
|
|
|
|
return -ENOMEM;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
blk_key->num_devs = num_devs;
|
2020-04-04 04:06:11 +09:00
|
|
|
fscrypt_get_devices(sb, num_devs, blk_key->devs);
|
2019-12-18 07:26:29 +09:00
|
|
|
|
2020-01-16 11:41:54 +09:00
|
|
|
BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE >
|
|
|
|
BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
|
|
|
|
|
|
|
|
err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size,
|
2020-06-17 06:33:37 +09:00
|
|
|
is_hw_wrapped, crypto_mode,
|
|
|
|
fscrypt_get_dun_bytes(ci), sb->s_blocksize);
|
2019-12-18 07:26:29 +09:00
|
|
|
if (err) {
|
|
|
|
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
|
|
|
|
goto fail;
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2019-12-18 07:26:29 +09:00
|
|
|
* We have to start using blk-crypto on all the filesystem's devices.
|
|
|
|
* We also have to save all the request_queue's for later so that the
|
|
|
|
* key can be evicted from them. This is needed because some keys
|
|
|
|
* aren't destroyed until after the filesystem was already unmounted
|
|
|
|
* (namely, the per-mode keys in struct fscrypt_master_key).
|
2019-10-25 06:44:29 +09:00
|
|
|
*/
|
2019-12-18 07:26:29 +09:00
|
|
|
for (i = 0; i < num_devs; i++) {
|
|
|
|
if (!blk_get_queue(blk_key->devs[i])) {
|
|
|
|
fscrypt_err(inode, "couldn't get request_queue");
|
|
|
|
err = -EAGAIN;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
queue_refs++;
|
|
|
|
|
2020-06-17 06:33:37 +09:00
|
|
|
err = blk_crypto_start_using_key(&blk_key->base,
|
|
|
|
blk_key->devs[i]);
|
2019-12-18 07:26:29 +09:00
|
|
|
if (err) {
|
|
|
|
fscrypt_err(inode,
|
|
|
|
"error %d starting to use blk-crypto", err);
|
|
|
|
goto fail;
|
|
|
|
}
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
2019-12-18 07:26:29 +09:00
|
|
|
/*
|
2020-07-22 07:59:17 +09:00
|
|
|
* Pairs with the smp_load_acquire() in fscrypt_is_key_prepared().
|
|
|
|
* I.e., here we publish ->blk_key with a RELEASE barrier so that
|
|
|
|
* concurrent tasks can ACQUIRE it. Note that this concurrency is only
|
|
|
|
* possible for per-mode keys, not for per-file keys.
|
2019-12-18 07:26:29 +09:00
|
|
|
*/
|
|
|
|
smp_store_release(&prep_key->blk_key, blk_key);
|
|
|
|
return 0;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
fail:
|
|
|
|
for (i = 0; i < queue_refs; i++)
|
|
|
|
blk_put_queue(blk_key->devs[i]);
|
2020-08-07 15:18:13 +09:00
|
|
|
kfree_sensitive(blk_key);
|
2019-10-25 06:44:29 +09:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
void fscrypt_destroy_inline_crypt_key(struct fscrypt_prepared_key *prep_key)
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
2019-12-18 07:26:29 +09:00
|
|
|
struct fscrypt_blk_crypto_key *blk_key = prep_key->blk_key;
|
|
|
|
int i;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
if (blk_key) {
|
|
|
|
for (i = 0; i < blk_key->num_devs; i++) {
|
|
|
|
blk_crypto_evict_key(blk_key->devs[i], &blk_key->base);
|
|
|
|
blk_put_queue(blk_key->devs[i]);
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
2020-08-07 15:18:13 +09:00
|
|
|
kfree_sensitive(blk_key);
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 11:41:54 +09:00
|
|
|
int fscrypt_derive_raw_secret(struct super_block *sb,
|
|
|
|
const u8 *wrapped_key,
|
|
|
|
unsigned int wrapped_key_size,
|
|
|
|
u8 *raw_secret, unsigned int raw_secret_size)
|
|
|
|
{
|
|
|
|
struct request_queue *q;
|
|
|
|
|
2020-08-07 01:58:56 +09:00
|
|
|
q = bdev_get_queue(sb->s_bdev);
|
2020-01-16 11:41:54 +09:00
|
|
|
if (!q->ksm)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
2020-06-17 06:33:37 +09:00
|
|
|
return blk_ksm_derive_raw_secret(q->ksm, wrapped_key, wrapped_key_size,
|
|
|
|
raw_secret, raw_secret_size);
|
2020-01-16 11:41:54 +09:00
|
|
|
}
|
|
|
|
|
2020-06-17 06:33:37 +09:00
|
|
|
bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
2020-06-17 06:33:37 +09:00
|
|
|
return inode->i_crypt_info->ci_inlinecrypt;
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
2020-06-17 06:33:37 +09:00
|
|
|
EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
static void fscrypt_generate_dun(const struct fscrypt_info *ci, u64 lblk_num,
|
|
|
|
u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE])
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
|
|
|
union fscrypt_iv iv;
|
2019-12-18 07:26:29 +09:00
|
|
|
int i;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
|
|
|
fscrypt_generate_iv(&iv, lblk_num, ci);
|
2019-12-18 07:26:29 +09:00
|
|
|
|
|
|
|
BUILD_BUG_ON(FSCRYPT_MAX_IV_SIZE > BLK_CRYPTO_MAX_IV_SIZE);
|
|
|
|
memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE);
|
|
|
|
for (i = 0; i < ci->ci_mode->ivsize/sizeof(dun[0]); i++)
|
|
|
|
dun[i] = le64_to_cpu(iv.dun[i]);
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-17 06:33:37 +09:00
|
|
|
* fscrypt_set_bio_crypt_ctx() - prepare a file contents bio for inline crypto
|
2019-10-25 06:44:29 +09:00
|
|
|
* @bio: a bio which will eventually be submitted to the file
|
|
|
|
* @inode: the file's inode
|
|
|
|
* @first_lblk: the first file logical block number in the I/O
|
2019-12-18 07:26:29 +09:00
|
|
|
* @gfp_mask: memory allocation flags - these must be a waiting mask so that
|
|
|
|
* bio_crypt_set_ctx can't fail.
|
2019-10-25 06:44:29 +09:00
|
|
|
*
|
|
|
|
* If the contents of the file should be encrypted (or decrypted) with inline
|
|
|
|
* encryption, then assign the appropriate encryption context to the bio.
|
|
|
|
*
|
|
|
|
* Normally the bio should be newly allocated (i.e. no pages added yet), as
|
|
|
|
* otherwise fscrypt_mergeable_bio() won't work as intended.
|
|
|
|
*
|
|
|
|
* The encryption context will be freed automatically when the bio is freed.
|
ANDROID: dm: add dm-default-key target for metadata encryption
Add a device-mapper target "dm-default-key" which assigns an encryption
key to bios that aren't for the contents of an encrypted file.
This ensures that all blocks on-disk will be encrypted with some key,
without the performance hit of file contents being encrypted twice when
fscrypt (File-Based Encryption) is used.
It is only appropriate to use dm-default-key when key configuration is
tightly controlled, like it is in Android, such that all fscrypt keys
are at least as hard to compromise as the default key.
Compared to the original version of dm-default-key, this has been
modified to use the new vendor-independent inline encryption framework
(which works even when no inline encryption hardware is present), the
table syntax has been changed to match dm-crypt, and support for
specifying Adiantum encryption has been added. These changes also mean
that dm-default-key now always explicitly specifies the DUN (the IV).
Also, to handle f2fs moving blocks of encrypted files around without the
key, and to handle ext4 and f2fs filesystems mounted without
'-o inlinecrypt', the mapping logic is no longer "set a key on the bio
if it doesn't have one already", but rather "set a key on the bio unless
the bio has the bi_skip_dm_default_key flag set". Filesystems set this
flag on *all* bios for encrypted file contents, regardless of whether
they are encrypting/decrypting the file using inline encryption or the
traditional filesystem-layer encryption, or moving the raw data.
For the bi_skip_dm_default_key flag, a new field in struct bio is used
rather than a bit in bi_opf so that fscrypt_set_bio_crypt_ctx() can set
the flag, minimizing the changes needed to filesystems. (bi_opf is
usually overwritten after fscrypt_set_bio_crypt_ctx() is called.)
Bug: 137270441
Bug: 147814592
Change-Id: I69c9cd1e968ccf990e4ad96e5115b662237f5095
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-01-22 02:27:47 +09:00
|
|
|
*
|
|
|
|
* This function also handles setting bi_skip_dm_default_key when needed.
|
2019-10-25 06:44:29 +09:00
|
|
|
*/
|
2019-12-18 07:26:29 +09:00
|
|
|
void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
|
|
|
|
u64 first_lblk, gfp_t gfp_mask)
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
2020-07-28 02:41:58 +09:00
|
|
|
const struct fscrypt_info *ci;
|
2019-12-18 07:26:29 +09:00
|
|
|
u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
|
2019-10-25 06:44:29 +09:00
|
|
|
|
ANDROID: dm: add dm-default-key target for metadata encryption
Add a device-mapper target "dm-default-key" which assigns an encryption
key to bios that aren't for the contents of an encrypted file.
This ensures that all blocks on-disk will be encrypted with some key,
without the performance hit of file contents being encrypted twice when
fscrypt (File-Based Encryption) is used.
It is only appropriate to use dm-default-key when key configuration is
tightly controlled, like it is in Android, such that all fscrypt keys
are at least as hard to compromise as the default key.
Compared to the original version of dm-default-key, this has been
modified to use the new vendor-independent inline encryption framework
(which works even when no inline encryption hardware is present), the
table syntax has been changed to match dm-crypt, and support for
specifying Adiantum encryption has been added. These changes also mean
that dm-default-key now always explicitly specifies the DUN (the IV).
Also, to handle f2fs moving blocks of encrypted files around without the
key, and to handle ext4 and f2fs filesystems mounted without
'-o inlinecrypt', the mapping logic is no longer "set a key on the bio
if it doesn't have one already", but rather "set a key on the bio unless
the bio has the bi_skip_dm_default_key flag set". Filesystems set this
flag on *all* bios for encrypted file contents, regardless of whether
they are encrypting/decrypting the file using inline encryption or the
traditional filesystem-layer encryption, or moving the raw data.
For the bi_skip_dm_default_key flag, a new field in struct bio is used
rather than a bit in bi_opf so that fscrypt_set_bio_crypt_ctx() can set
the flag, minimizing the changes needed to filesystems. (bi_opf is
usually overwritten after fscrypt_set_bio_crypt_ctx() is called.)
Bug: 137270441
Bug: 147814592
Change-Id: I69c9cd1e968ccf990e4ad96e5115b662237f5095
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-01-22 02:27:47 +09:00
|
|
|
if (fscrypt_inode_should_skip_dm_default_key(inode))
|
|
|
|
bio_set_skip_dm_default_key(bio);
|
|
|
|
|
2019-10-25 06:44:29 +09:00
|
|
|
if (!fscrypt_inode_uses_inline_crypto(inode))
|
2019-12-18 07:26:29 +09:00
|
|
|
return;
|
2020-07-28 02:41:58 +09:00
|
|
|
ci = inode->i_crypt_info;
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
fscrypt_generate_dun(ci, first_lblk, dun);
|
2020-06-17 06:33:37 +09:00
|
|
|
bio_crypt_set_ctx(bio, &ci->ci_enc_key.blk_key->base, dun, gfp_mask);
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx);
|
|
|
|
|
|
|
|
/* Extract the inode and logical block number from a buffer_head. */
|
|
|
|
static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh,
|
|
|
|
const struct inode **inode_ret,
|
|
|
|
u64 *lblk_num_ret)
|
|
|
|
{
|
|
|
|
struct page *page = bh->b_page;
|
|
|
|
const struct address_space *mapping;
|
|
|
|
const struct inode *inode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The ext4 journal (jbd2) can submit a buffer_head it directly created
|
|
|
|
* for a non-pagecache page. fscrypt doesn't care about these.
|
|
|
|
*/
|
|
|
|
mapping = page_mapping(page);
|
|
|
|
if (!mapping)
|
|
|
|
return false;
|
|
|
|
inode = mapping->host;
|
|
|
|
|
|
|
|
*inode_ret = inode;
|
|
|
|
*lblk_num_ret = ((u64)page->index << (PAGE_SHIFT - inode->i_blkbits)) +
|
|
|
|
(bh_offset(bh) >> inode->i_blkbits);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-17 06:33:37 +09:00
|
|
|
* fscrypt_set_bio_crypt_ctx_bh() - prepare a file contents bio for inline
|
|
|
|
* crypto
|
2019-10-25 06:44:29 +09:00
|
|
|
* @bio: a bio which will eventually be submitted to the file
|
|
|
|
* @first_bh: the first buffer_head for which I/O will be submitted
|
|
|
|
* @gfp_mask: memory allocation flags
|
|
|
|
*
|
|
|
|
* Same as fscrypt_set_bio_crypt_ctx(), except this takes a buffer_head instead
|
|
|
|
* of an inode and block number directly.
|
|
|
|
*/
|
2019-12-18 07:26:29 +09:00
|
|
|
void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio,
|
2020-06-17 06:33:37 +09:00
|
|
|
const struct buffer_head *first_bh,
|
|
|
|
gfp_t gfp_mask)
|
2019-10-25 06:44:29 +09:00
|
|
|
{
|
|
|
|
const struct inode *inode;
|
|
|
|
u64 first_lblk;
|
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
if (bh_get_inode_and_lblk_num(first_bh, &inode, &first_lblk))
|
|
|
|
fscrypt_set_bio_crypt_ctx(bio, inode, first_lblk, gfp_mask);
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
|
|
|
|
|
|
|
|
/**
|
2020-06-17 06:33:37 +09:00
|
|
|
* fscrypt_mergeable_bio() - test whether data can be added to a bio
|
2019-10-25 06:44:29 +09:00
|
|
|
* @bio: the bio being built up
|
|
|
|
* @inode: the inode for the next part of the I/O
|
|
|
|
* @next_lblk: the next file logical block number in the I/O
|
|
|
|
*
|
|
|
|
* When building a bio which may contain data which should undergo inline
|
|
|
|
* encryption (or decryption) via fscrypt, filesystems should call this function
|
2020-07-15 01:31:24 +09:00
|
|
|
* to ensure that the resulting bio contains only contiguous data unit numbers.
|
2019-10-25 06:44:29 +09:00
|
|
|
* This will return false if the next part of the I/O cannot be merged with the
|
|
|
|
* bio because either the encryption key would be different or the encryption
|
|
|
|
* data unit numbers would be discontiguous.
|
|
|
|
*
|
|
|
|
* fscrypt_set_bio_crypt_ctx() must have already been called on the bio.
|
|
|
|
*
|
ANDROID: dm: add dm-default-key target for metadata encryption
Add a device-mapper target "dm-default-key" which assigns an encryption
key to bios that aren't for the contents of an encrypted file.
This ensures that all blocks on-disk will be encrypted with some key,
without the performance hit of file contents being encrypted twice when
fscrypt (File-Based Encryption) is used.
It is only appropriate to use dm-default-key when key configuration is
tightly controlled, like it is in Android, such that all fscrypt keys
are at least as hard to compromise as the default key.
Compared to the original version of dm-default-key, this has been
modified to use the new vendor-independent inline encryption framework
(which works even when no inline encryption hardware is present), the
table syntax has been changed to match dm-crypt, and support for
specifying Adiantum encryption has been added. These changes also mean
that dm-default-key now always explicitly specifies the DUN (the IV).
Also, to handle f2fs moving blocks of encrypted files around without the
key, and to handle ext4 and f2fs filesystems mounted without
'-o inlinecrypt', the mapping logic is no longer "set a key on the bio
if it doesn't have one already", but rather "set a key on the bio unless
the bio has the bi_skip_dm_default_key flag set". Filesystems set this
flag on *all* bios for encrypted file contents, regardless of whether
they are encrypting/decrypting the file using inline encryption or the
traditional filesystem-layer encryption, or moving the raw data.
For the bi_skip_dm_default_key flag, a new field in struct bio is used
rather than a bit in bi_opf so that fscrypt_set_bio_crypt_ctx() can set
the flag, minimizing the changes needed to filesystems. (bi_opf is
usually overwritten after fscrypt_set_bio_crypt_ctx() is called.)
Bug: 137270441
Bug: 147814592
Change-Id: I69c9cd1e968ccf990e4ad96e5115b662237f5095
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-01-22 02:27:47 +09:00
|
|
|
* This function also returns false if the next part of the I/O would need to
|
|
|
|
* have a different value for the bi_skip_dm_default_key flag.
|
|
|
|
*
|
2019-10-25 06:44:29 +09:00
|
|
|
* Return: true iff the I/O is mergeable
|
|
|
|
*/
|
|
|
|
bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
|
|
|
|
u64 next_lblk)
|
|
|
|
{
|
2019-12-18 07:26:29 +09:00
|
|
|
const struct bio_crypt_ctx *bc = bio->bi_crypt_context;
|
|
|
|
u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
|
2019-10-25 06:44:29 +09:00
|
|
|
|
2019-12-18 07:26:29 +09:00
|
|
|
if (!!bc != fscrypt_inode_uses_inline_crypto(inode))
|
2019-10-25 06:44:29 +09:00
|
|
|
return false;
|
ANDROID: dm: add dm-default-key target for metadata encryption
Add a device-mapper target "dm-default-key" which assigns an encryption
key to bios that aren't for the contents of an encrypted file.
This ensures that all blocks on-disk will be encrypted with some key,
without the performance hit of file contents being encrypted twice when
fscrypt (File-Based Encryption) is used.
It is only appropriate to use dm-default-key when key configuration is
tightly controlled, like it is in Android, such that all fscrypt keys
are at least as hard to compromise as the default key.
Compared to the original version of dm-default-key, this has been
modified to use the new vendor-independent inline encryption framework
(which works even when no inline encryption hardware is present), the
table syntax has been changed to match dm-crypt, and support for
specifying Adiantum encryption has been added. These changes also mean
that dm-default-key now always explicitly specifies the DUN (the IV).
Also, to handle f2fs moving blocks of encrypted files around without the
key, and to handle ext4 and f2fs filesystems mounted without
'-o inlinecrypt', the mapping logic is no longer "set a key on the bio
if it doesn't have one already", but rather "set a key on the bio unless
the bio has the bi_skip_dm_default_key flag set". Filesystems set this
flag on *all* bios for encrypted file contents, regardless of whether
they are encrypting/decrypting the file using inline encryption or the
traditional filesystem-layer encryption, or moving the raw data.
For the bi_skip_dm_default_key flag, a new field in struct bio is used
rather than a bit in bi_opf so that fscrypt_set_bio_crypt_ctx() can set
the flag, minimizing the changes needed to filesystems. (bi_opf is
usually overwritten after fscrypt_set_bio_crypt_ctx() is called.)
Bug: 137270441
Bug: 147814592
Change-Id: I69c9cd1e968ccf990e4ad96e5115b662237f5095
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-01-22 02:27:47 +09:00
|
|
|
if (bio_should_skip_dm_default_key(bio) !=
|
|
|
|
fscrypt_inode_should_skip_dm_default_key(inode))
|
|
|
|
return false;
|
2019-12-18 07:26:29 +09:00
|
|
|
if (!bc)
|
2019-10-25 06:44:29 +09:00
|
|
|
return true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Comparing the key pointers is good enough, as all I/O for each key
|
|
|
|
* uses the same pointer. I.e., there's currently no need to support
|
|
|
|
* merging requests where the keys are the same but the pointers differ.
|
|
|
|
*/
|
2020-06-17 06:33:37 +09:00
|
|
|
if (bc->bc_key != &inode->i_crypt_info->ci_enc_key.blk_key->base)
|
2019-12-18 07:26:29 +09:00
|
|
|
return false;
|
|
|
|
|
|
|
|
fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
|
|
|
|
return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
|
2019-10-25 06:44:29 +09:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
|
|
|
|
|
|
|
|
/**
|
2020-06-17 06:33:37 +09:00
|
|
|
* fscrypt_mergeable_bio_bh() - test whether data can be added to a bio
|
2019-10-25 06:44:29 +09:00
|
|
|
* @bio: the bio being built up
|
|
|
|
* @next_bh: the next buffer_head for which I/O will be submitted
|
|
|
|
*
|
|
|
|
* Same as fscrypt_mergeable_bio(), except this takes a buffer_head instead of
|
|
|
|
* an inode and block number directly.
|
|
|
|
*
|
|
|
|
* Return: true iff the I/O is mergeable
|
|
|
|
*/
|
|
|
|
bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
|
|
|
const struct buffer_head *next_bh)
|
|
|
|
{
|
|
|
|
const struct inode *inode;
|
|
|
|
u64 next_lblk;
|
|
|
|
|
|
|
|
if (!bh_get_inode_and_lblk_num(next_bh, &inode, &next_lblk))
|
ANDROID: dm: add dm-default-key target for metadata encryption
Add a device-mapper target "dm-default-key" which assigns an encryption
key to bios that aren't for the contents of an encrypted file.
This ensures that all blocks on-disk will be encrypted with some key,
without the performance hit of file contents being encrypted twice when
fscrypt (File-Based Encryption) is used.
It is only appropriate to use dm-default-key when key configuration is
tightly controlled, like it is in Android, such that all fscrypt keys
are at least as hard to compromise as the default key.
Compared to the original version of dm-default-key, this has been
modified to use the new vendor-independent inline encryption framework
(which works even when no inline encryption hardware is present), the
table syntax has been changed to match dm-crypt, and support for
specifying Adiantum encryption has been added. These changes also mean
that dm-default-key now always explicitly specifies the DUN (the IV).
Also, to handle f2fs moving blocks of encrypted files around without the
key, and to handle ext4 and f2fs filesystems mounted without
'-o inlinecrypt', the mapping logic is no longer "set a key on the bio
if it doesn't have one already", but rather "set a key on the bio unless
the bio has the bi_skip_dm_default_key flag set". Filesystems set this
flag on *all* bios for encrypted file contents, regardless of whether
they are encrypting/decrypting the file using inline encryption or the
traditional filesystem-layer encryption, or moving the raw data.
For the bi_skip_dm_default_key flag, a new field in struct bio is used
rather than a bit in bi_opf so that fscrypt_set_bio_crypt_ctx() can set
the flag, minimizing the changes needed to filesystems. (bi_opf is
usually overwritten after fscrypt_set_bio_crypt_ctx() is called.)
Bug: 137270441
Bug: 147814592
Change-Id: I69c9cd1e968ccf990e4ad96e5115b662237f5095
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-01-22 02:27:47 +09:00
|
|
|
return !bio->bi_crypt_context &&
|
|
|
|
!bio_should_skip_dm_default_key(bio);
|
2019-10-25 06:44:29 +09:00
|
|
|
|
|
|
|
return fscrypt_mergeable_bio(bio, inode, next_lblk);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh);
|
2020-05-20 08:11:59 +09:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fscrypt_dio_supported() - check whether a direct I/O request is unsupported
|
|
|
|
* due to encryption constraints
|
|
|
|
* @iocb: the file and position the I/O is targeting
|
|
|
|
* @iter: the I/O data segment(s)
|
|
|
|
*
|
|
|
|
* Return: true if direct I/O is supported
|
|
|
|
*/
|
|
|
|
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter)
|
|
|
|
{
|
|
|
|
const struct inode *inode = file_inode(iocb->ki_filp);
|
|
|
|
const unsigned int blocksize = i_blocksize(inode);
|
|
|
|
|
|
|
|
/* If the file is unencrypted, no veto from us. */
|
|
|
|
if (!fscrypt_needs_contents_encryption(inode))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* We only support direct I/O with inline crypto, not fs-layer crypto */
|
|
|
|
if (!fscrypt_inode_uses_inline_crypto(inode))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since the granularity of encryption is filesystem blocks, the I/O
|
|
|
|
* must be block aligned -- not just disk sector aligned.
|
|
|
|
*/
|
|
|
|
if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* fscrypt_limit_dio_pages() - limit I/O pages to avoid discontiguous DUNs
|
|
|
|
* @inode: the file on which I/O is being done
|
|
|
|
* @pos: the file position (in bytes) at which the I/O is being done
|
|
|
|
* @nr_pages: the number of pages we want to submit starting at @pos
|
|
|
|
*
|
|
|
|
* For direct I/O: limit the number of pages that will be submitted in the bio
|
|
|
|
* targeting @pos, in order to avoid crossing a data unit number (DUN)
|
|
|
|
* discontinuity. This is only needed for certain IV generation methods.
|
|
|
|
*
|
2020-07-15 01:31:24 +09:00
|
|
|
* This assumes block_size == PAGE_SIZE; see fscrypt_dio_supported().
|
|
|
|
*
|
2020-05-20 08:11:59 +09:00
|
|
|
* Return: the actual number of pages that can be submitted
|
|
|
|
*/
|
|
|
|
int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages)
|
|
|
|
{
|
|
|
|
const struct fscrypt_info *ci = inode->i_crypt_info;
|
|
|
|
u32 dun;
|
|
|
|
|
|
|
|
if (!fscrypt_inode_uses_inline_crypto(inode))
|
|
|
|
return nr_pages;
|
|
|
|
|
|
|
|
if (nr_pages <= 1)
|
|
|
|
return nr_pages;
|
|
|
|
|
|
|
|
if (!(fscrypt_policy_flags(&ci->ci_policy) &
|
|
|
|
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
|
|
|
|
return nr_pages;
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */
|
|
|
|
|
|
|
|
dun = ci->ci_hashed_ino + (pos >> inode->i_blkbits);
|
|
|
|
|
|
|
|
return min_t(u64, nr_pages, (u64)U32_MAX + 1 - dun);
|
|
|
|
}
|