Commit f0d87441 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull fscrypt updates from Eric Biggers:

 - Extend the FS_IOC_ADD_ENCRYPTION_KEY ioctl to allow the raw key to be
   provided via a keyring key.

 - Prepare for the new dirhash method (SipHash of plaintext name) that
   will be used by directories that are both encrypted and casefolded.

 - Switch to a new format for "no-key names" that prepares for the new
   dirhash method, and also fixes a longstanding bug where multiple
   filenames could map to the same no-key name.

 - Allow the crypto algorithms used by fscrypt to be built as loadable
   modules when the fscrypt-capable filesystems are.

 - Optimize fscrypt_zeroout_range().

 - Various cleanups.

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: (26 commits)
  fscrypt: improve format of no-key names
  ubifs: allow both hash and disk name to be provided in no-key names
  ubifs: don't trigger assertion on invalid no-key filename
  fscrypt: clarify what is meant by a per-file key
  fscrypt: derive dirhash key for casefolded directories
  fscrypt: don't allow v1 policies with casefolding
  fscrypt: add "fscrypt_" prefix to fname_encrypt()
  fscrypt: don't print name of busy file when removing key
  ubifs: use IS_ENCRYPTED() instead of ubifs_crypt_is_encrypted()
  fscrypt: document gfp_flags for bounce page allocation
  fscrypt: optimize fscrypt_zeroout_range()
  fscrypt: remove redundant bi_status check
  fscrypt: Allow modular crypto algorithms
  fscrypt: include <linux/ioctl.h> in UAPI header
  fscrypt: don't check for ENOKEY from fscrypt_get_encryption_info()
  fscrypt: remove fscrypt_is_direct_key_policy()
  fscrypt: move fscrypt_valid_enc_modes() to policy.c
  fscrypt: check for appropriate use of DIRECT_KEY flag earlier
  fscrypt: split up fscrypt_supported_policy() by policy version
  fscrypt: introduce fscrypt_needs_contents_encryption()
  ...
parents b5f7ab6b edc440e3
...@@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes ...@@ -234,8 +234,8 @@ HKDF is more flexible, is nonreversible, and evenly distributes
entropy from the master key. HKDF is also standardized and widely 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. used by other software, whereas the AES-128-ECB based KDF is ad-hoc.
Per-file keys Per-file encryption keys
------------- ------------------------
Since each master key can protect many files, it is necessary to 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 "tweak" the encryption of each file so that the same plaintext in two
...@@ -268,9 +268,9 @@ is greater than that of an AES-256-XTS key. ...@@ -268,9 +268,9 @@ is greater than that of an AES-256-XTS key.
Therefore, to improve performance and save memory, for Adiantum a Therefore, to improve performance and save memory, for Adiantum a
"direct key" configuration is supported. When the user has enabled "direct key" configuration is supported. When the user has enabled
this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy, this by setting FSCRYPT_POLICY_FLAG_DIRECT_KEY in the fscrypt policy,
per-file keys are not used. Instead, whenever any data (contents or per-file encryption keys are not used. Instead, whenever any data
filenames) is encrypted, the file's 16-byte nonce is included in the (contents or filenames) is encrypted, the file's 16-byte nonce is
IV. Moreover: included in the IV. Moreover:
- For v1 encryption policies, the encryption is done directly with the - For v1 encryption policies, the encryption is done directly with the
master key. Because of this, users **must not** use the same master master key. Because of this, users **must not** use the same master
...@@ -302,6 +302,16 @@ For master keys used for v2 encryption policies, a unique 16-byte "key ...@@ -302,6 +302,16 @@ 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 identifier" is also derived using the KDF. This value is stored in
the clear, since it is needed to reliably identify the key itself. 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 Encryption modes and usage
========================== ==========================
...@@ -325,11 +335,11 @@ used. ...@@ -325,11 +335,11 @@ 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
wide-block mode, unlike XTS. It can also eliminate the need to derive wide-block mode, unlike XTS. It can also eliminate the need to derive
per-file keys. However, it depends on the security of two primitives, per-file encryption keys. However, it depends on the security of two
XChaCha12 and AES-256, rather than just one. See the paper primitives, XChaCha12 and AES-256, rather than just one. See the
"Adiantum: length-preserving encryption for entry-level processors" paper "Adiantum: length-preserving encryption for entry-level
(https://eprint.iacr.org/2018/720.pdf) for more details. To use processors" (https://eprint.iacr.org/2018/720.pdf) for more details.
Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled. Also, fast To use Adiantum, CONFIG_CRYPTO_ADIANTUM must be enabled. Also, fast
implementations of ChaCha and NHPoly1305 should be enabled, e.g. implementations of ChaCha and NHPoly1305 should be enabled, e.g.
CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM. CONFIG_CRYPTO_CHACHA20_NEON and CONFIG_CRYPTO_NHPOLY1305_NEON for ARM.
...@@ -513,7 +523,9 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors: ...@@ -513,7 +523,9 @@ FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors:
- ``EEXIST``: the file is already encrypted with an encryption policy - ``EEXIST``: the file is already encrypted with an encryption policy
different from the one specified different from the one specified
- ``EINVAL``: an invalid encryption policy was specified (invalid - ``EINVAL``: an invalid encryption policy was specified (invalid
version, mode(s), or flags; or reserved bits were set) 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 - ``ENOKEY``: a v2 encryption policy was specified, but the key with
the specified ``master_key_identifier`` has not been added, nor does the specified ``master_key_identifier`` has not been added, nor does
the process have the CAP_FOWNER capability in the initial user the process have the CAP_FOWNER capability in the initial user
...@@ -638,7 +650,8 @@ follows:: ...@@ -638,7 +650,8 @@ follows::
struct fscrypt_add_key_arg { struct fscrypt_add_key_arg {
struct fscrypt_key_specifier key_spec; struct fscrypt_key_specifier key_spec;
__u32 raw_size; __u32 raw_size;
__u32 __reserved[9]; __u32 key_id;
__u32 __reserved[8];
__u8 raw[]; __u8 raw[];
}; };
...@@ -655,6 +668,12 @@ follows:: ...@@ -655,6 +668,12 @@ follows::
} u; } u;
}; };
struct fscrypt_provisioning_key_payload {
__u32 type;
__u32 __reserved;
__u8 raw[];
};
:c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized :c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized
as follows: as follows:
...@@ -677,9 +696,26 @@ as follows: ...@@ -677,9 +696,26 @@ as follows:
``Documentation/security/keys/core.rst``). ``Documentation/security/keys/core.rst``).
- ``raw_size`` must be the size of the ``raw`` key provided, in bytes. - ``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 a :c:type:`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 - ``raw`` is a variable-length field which must contain the actual
key, ``raw_size`` bytes long. 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 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 by effective user ID) added the key, and only allows the key to be
...@@ -701,11 +737,16 @@ FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors: ...@@ -701,11 +737,16 @@ FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors:
- ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the - ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the
caller does not have the CAP_SYS_ADMIN capability in the initial caller does not have the CAP_SYS_ADMIN capability in the initial
user namespace 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 - ``EDQUOT``: the key quota for this user would be exceeded by adding
the key the key
- ``EINVAL``: invalid key size or key specifier type, or reserved bits - ``EINVAL``: invalid key size or key specifier type, or reserved bits
were set 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 - ``ENOTTY``: this type of filesystem does not implement encryption
- ``EOPNOTSUPP``: the kernel was not configured with encryption - ``EOPNOTSUPP``: the kernel was not configured with encryption
support for this filesystem, or the filesystem superblock has not support for this filesystem, or the filesystem superblock has not
...@@ -1108,8 +1149,8 @@ The context structs contain the same information as the corresponding ...@@ -1108,8 +1149,8 @@ The context structs contain the same information as the corresponding
policy structs (see `Setting an encryption policy`_), except that the 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 encryption
`DIRECT_KEY policies`_. keys`_ and `DIRECT_KEY policies`_.
Data path changes Data path changes
----------------- -----------------
...@@ -1161,7 +1202,7 @@ filesystem-specific hash(es) needed for directory lookups. This ...@@ -1161,7 +1202,7 @@ filesystem-specific hash(es) needed for directory lookups. This
allows the filesystem to still, with a high degree of confidence, map allows the filesystem to still, with a high degree of confidence, map
the filename given in ->lookup() back to a particular directory entry the filename given in ->lookup() back to a particular directory entry
that was previously listed by readdir(). See :c:type:`struct that was previously listed by readdir(). See :c:type:`struct
fscrypt_digested_name` in the source for more details. fscrypt_nokey_name` in the source for more details.
Note that the precise way that filenames are presented to userspace 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 without the key is subject to change in the future. It is only meant
......
...@@ -2,13 +2,8 @@ ...@@ -2,13 +2,8 @@
config FS_ENCRYPTION config FS_ENCRYPTION
bool "FS Encryption (Per-file encryption)" bool "FS Encryption (Per-file encryption)"
select CRYPTO select CRYPTO
select CRYPTO_AES select CRYPTO_HASH
select CRYPTO_CBC select CRYPTO_SKCIPHER
select CRYPTO_ECB
select CRYPTO_XTS
select CRYPTO_CTS
select CRYPTO_SHA512
select CRYPTO_HMAC
select KEYS select KEYS
help help
Enable encryption of files and directories. This Enable encryption of files and directories. This
...@@ -16,3 +11,16 @@ config FS_ENCRYPTION ...@@ -16,3 +11,16 @@ config FS_ENCRYPTION
efficient since it avoids caching the encrypted and efficient since it avoids caching the encrypted and
decrypted pages in the page cache. Currently Ext4, decrypted pages in the page cache. Currently Ext4,
F2FS and UBIFS make use of this feature. F2FS and UBIFS make use of this feature.
# Filesystems supporting encryption must select this if FS_ENCRYPTION. This
# allows the algorithms to be built as modules when all the filesystems are.
config FS_ENCRYPTION_ALGS
tristate
select CRYPTO_AES
select CRYPTO_CBC
select CRYPTO_CTS
select CRYPTO_ECB
select CRYPTO_HMAC
select CRYPTO_SHA256
select CRYPTO_SHA512
select CRYPTO_XTS
...@@ -41,53 +41,101 @@ void fscrypt_decrypt_bio(struct bio *bio) ...@@ -41,53 +41,101 @@ void fscrypt_decrypt_bio(struct bio *bio)
} }
EXPORT_SYMBOL(fscrypt_decrypt_bio); EXPORT_SYMBOL(fscrypt_decrypt_bio);
/**
* fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file
* @inode: the file's inode
* @lblk: the first file logical block to zero out
* @pblk: the first filesystem physical block to zero out
* @len: number of blocks to zero out
*
* Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write
* ciphertext blocks which decrypt to the all-zeroes block. The blocks must be
* both logically and physically contiguous. It's also assumed that the
* filesystem only uses a single block device, ->s_bdev.
*
* Note that since each block uses a different IV, this involves writing a
* different ciphertext to each block; we can't simply reuse the same one.
*
* Return: 0 on success; -errno on failure.
*/
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)
{ {
const unsigned int blockbits = inode->i_blkbits; const unsigned int blockbits = inode->i_blkbits;
const unsigned int blocksize = 1 << blockbits; const unsigned int blocksize = 1 << blockbits;
struct page *ciphertext_page; const unsigned int blocks_per_page_bits = PAGE_SHIFT - blockbits;
const unsigned int blocks_per_page = 1 << blocks_per_page_bits;
struct page *pages[16]; /* write up to 16 pages at a time */
unsigned int nr_pages;
unsigned int i;
unsigned int offset;
struct bio *bio; struct bio *bio;
int ret, err = 0; int ret, err;
ciphertext_page = fscrypt_alloc_bounce_page(GFP_NOWAIT); if (len == 0)
if (!ciphertext_page) return 0;
return -ENOMEM;
while (len--) { BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_PAGES);
err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk, nr_pages = min_t(unsigned int, ARRAY_SIZE(pages),
ZERO_PAGE(0), ciphertext_page, (len + blocks_per_page - 1) >> blocks_per_page_bits);
blocksize, 0, GFP_NOFS);
if (err)
goto errout;
bio = bio_alloc(GFP_NOWAIT, 1); /*
if (!bio) { * We need at least one page for ciphertext. Allocate the first one
err = -ENOMEM; * from a mempool, with __GFP_DIRECT_RECLAIM set so that it can't fail.
goto errout; *
} * Any additional page allocations are allowed to fail, as they only
* help performance, and waiting on the mempool for them could deadlock.
*/
for (i = 0; i < nr_pages; i++) {
pages[i] = fscrypt_alloc_bounce_page(i == 0 ? GFP_NOFS :
GFP_NOWAIT | __GFP_NOWARN);
if (!pages[i])
break;
}
nr_pages = i;
if (WARN_ON(nr_pages <= 0))
return -EINVAL;
/* This always succeeds since __GFP_DIRECT_RECLAIM is set. */
bio = bio_alloc(GFP_NOFS, nr_pages);
do {
bio_set_dev(bio, inode->i_sb->s_bdev); bio_set_dev(bio, inode->i_sb->s_bdev);
bio->bi_iter.bi_sector = pblk << (blockbits - 9); bio->bi_iter.bi_sector = pblk << (blockbits - 9);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
ret = bio_add_page(bio, ciphertext_page, blocksize, 0);
if (WARN_ON(ret != blocksize)) { i = 0;
/* should never happen! */ offset = 0;
bio_put(bio); do {
err = -EIO; err = fscrypt_crypt_block(inode, FS_ENCRYPT, lblk,
goto errout; ZERO_PAGE(0), pages[i],
} blocksize, offset, GFP_NOFS);
if (err)
goto out;
lblk++;
pblk++;
len--;
offset += blocksize;
if (offset == PAGE_SIZE || len == 0) {
ret = bio_add_page(bio, pages[i++], offset, 0);
if (WARN_ON(ret != offset)) {
err = -EIO;
goto out;
}
offset = 0;
}
} while (i != nr_pages && len != 0);
err = submit_bio_wait(bio); err = submit_bio_wait(bio);
if (err == 0 && bio->bi_status)
err = -EIO;
bio_put(bio);
if (err) if (err)
goto errout; goto out;
lblk++; bio_reset(bio);
pblk++; } while (len != 0);
}
err = 0; err = 0;
errout: out:
fscrypt_free_bounce_page(ciphertext_page); bio_put(bio);
for (i = 0; i < nr_pages; i++)
fscrypt_free_bounce_page(pages[i]);
return err; return err;
} }
EXPORT_SYMBOL(fscrypt_zeroout_range); EXPORT_SYMBOL(fscrypt_zeroout_range);
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
...@@ -140,7 +138,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, ...@@ -140,7 +138,7 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
* multiple of the filesystem's block size. * multiple of the filesystem's block size.
* @offs: Byte offset within @page of the first block to encrypt. Must be * @offs: Byte offset within @page of the first block to encrypt. Must be
* a multiple of the filesystem's block size. * a multiple of the filesystem's block size.
* @gfp_flags: Memory allocation flags * @gfp_flags: Memory allocation flags. See details below.
* *
* A new bounce page is allocated, and the specified block(s) are encrypted into * A new bounce page is allocated, and the specified block(s) are encrypted into
* it. In the bounce page, the ciphertext block(s) will be located at the same * it. In the bounce page, the ciphertext block(s) will be located at the same
...@@ -150,6 +148,11 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw, ...@@ -150,6 +148,11 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
* *
* This is for use by the filesystem's ->writepages() method. * This is for use by the filesystem's ->writepages() method.
* *
* The bounce page allocation is mempool-backed, so it will always succeed when
* @gfp_flags includes __GFP_DIRECT_RECLAIM, e.g. when it's GFP_NOFS. However,
* only the first page of each bio can be allocated this way. To prevent
* deadlocks, for any additional pages a mask like GFP_NOWAIT must be used.
*
* Return: the new encrypted bounce page on success; an ERR_PTR() on failure * Return: the new encrypted bounce page on success; an ERR_PTR() on failure
*/ */
struct page *fscrypt_encrypt_pagecache_blocks(struct page *page, struct page *fscrypt_encrypt_pagecache_blocks(struct page *page,
...@@ -286,54 +289,6 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page, ...@@ -286,54 +289,6 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
} }
EXPORT_SYMBOL(fscrypt_decrypt_block_inplace); EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
/*
* Validate dentries in encrypted directories to make sure we aren't potentially
* caching stale dentries after a key has been added.
*/
static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
{
struct dentry *dir;
int err;
int valid;
/*
* Plaintext names are always valid, since fscrypt doesn't support
* reverting to ciphertext names without evicting the directory's inode
* -- which implies eviction of the dentries in the directory.
*/
if (!(dentry->d_flags & DCACHE_ENCRYPTED_NAME))
return 1;
/*
* Ciphertext name; valid if the directory's key is still unavailable.
*
* Although fscrypt forbids rename() on ciphertext names, we still must
* use dget_parent() here rather than use ->d_parent directly. That's
* because a corrupted fs image may contain directory hard links, which
* the VFS handles by moving the directory's dentry tree in the dcache
* each time ->lookup() finds the directory and it already has a dentry
* elsewhere. Thus ->d_parent can be changing, and we must safely grab
* a reference to some ->d_parent to prevent it from being freed.
*/
if (flags & LOOKUP_RCU)
return -ECHILD;
dir = dget_parent(dentry);
err = fscrypt_get_encryption_info(d_inode(dir));
valid = !fscrypt_has_encryption_key(d_inode(dir));
dput(dir);
if (err < 0)
return err;
return valid;
}
const struct dentry_operations fscrypt_d_ops = {
.d_revalidate = fscrypt_d_revalidate,
};
/** /**
* 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
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define _FSCRYPT_PRIVATE_H #define _FSCRYPT_PRIVATE_H
#include <linux/fscrypt.h> #include <linux/fscrypt.h>
#include <linux/siphash.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#define CONST_STRLEN(str) (sizeof(str) - 1) #define CONST_STRLEN(str) (sizeof(str) - 1)
...@@ -136,12 +137,6 @@ fscrypt_policy_flags(const union fscrypt_policy *policy) ...@@ -136,12 +137,6 @@ fscrypt_policy_flags(const union fscrypt_policy *policy)
BUG(); BUG();
} }
static inline bool
fscrypt_is_direct_key_policy(const union fscrypt_policy *policy)
{
return fscrypt_policy_flags(policy) & FSCRYPT_POLICY_FLAG_DIRECT_KEY;
}
/** /**
* For encrypted symlinks, the ciphertext length is stored at the beginning * For encrypted symlinks, the ciphertext length is stored at the beginning
* of the string in little-endian format. * of the string in little-endian format.
...@@ -194,6 +189,14 @@ struct fscrypt_info { ...@@ -194,6 +189,14 @@ struct fscrypt_info {
*/ */
struct fscrypt_direct_key *ci_direct_key; struct fscrypt_direct_key *ci_direct_key;
/*
* This inode's hash key for filenames. This is a 128-bit SipHash-2-4
* key. This is only set for directories that use a keyed dirhash over
* the plaintext filenames -- currently just casefolded directories.
*/
siphash_key_t ci_dirhash_key;
bool ci_dirhash_key_initialized;
/* The encryption policy used by this inode */ /* The encryption policy used by this inode */
union fscrypt_policy ci_policy; union fscrypt_policy ci_policy;
...@@ -206,24 +209,6 @@ typedef enum { ...@@ -206,24 +209,6 @@ typedef enum {
FS_ENCRYPT, FS_ENCRYPT,
} fscrypt_direction_t; } fscrypt_direction_t;
static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
u32 filenames_mode)
{
if (contents_mode == FSCRYPT_MODE_AES_128_CBC &&
filenames_mode == FSCRYPT_MODE_AES_128_CTS)
return true;
if (contents_mode == FSCRYPT_MODE_AES_256_XTS &&
filenames_mode == FSCRYPT_MODE_AES_256_CTS)
return true;
if (contents_mode == FSCRYPT_MODE_ADIANTUM &&
filenames_mode == FSCRYPT_MODE_ADIANTUM)
return true;
return false;
}
/* crypto.c */ /* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep; extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags); extern int fscrypt_initialize(unsigned int cop_flags);
...@@ -233,7 +218,6 @@ extern int fscrypt_crypt_block(const struct inode *inode, ...@@ -233,7 +218,6 @@ extern int fscrypt_crypt_block(const struct inode *inode,
unsigned int len, unsigned int offs, unsigned int len, unsigned int offs,
gfp_t gfp_flags); gfp_t gfp_flags);
extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags); extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);
extern const struct dentry_operations fscrypt_d_ops;
extern void __printf(3, 4) __cold extern void __printf(3, 4) __cold
fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...); fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...);
...@@ -260,11 +244,13 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num, ...@@ -260,11 +244,13 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
const struct fscrypt_info *ci); const struct fscrypt_info *ci);
/* fname.c */ /* fname.c */
extern int fname_encrypt(struct inode *inode, const struct qstr *iname, extern int fscrypt_fname_encrypt(const struct inode *inode,
u8 *out, unsigned int olen); const struct qstr *iname,
u8 *out, unsigned int olen);
extern bool fscrypt_fname_encrypted_size(const struct inode *inode, extern bool fscrypt_fname_encrypted_size(const struct inode *inode,
u32 orig_len, u32 max_len, u32 orig_len, u32 max_len,
u32 *encrypted_len_ret); u32 *encrypted_len_ret);
extern const struct dentry_operations fscrypt_d_ops;
/* hkdf.c */ /* hkdf.c */
...@@ -283,11 +269,12 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, ...@@ -283,11 +269,12 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
* output doesn't reveal another. * output doesn't reveal another.
*/ */
#define HKDF_CONTEXT_KEY_IDENTIFIER 1 #define HKDF_CONTEXT_KEY_IDENTIFIER 1
#define HKDF_CONTEXT_PER_FILE_KEY 2 #define HKDF_CONTEXT_PER_FILE_ENC_KEY 2
#define HKDF_CONTEXT_DIRECT_KEY 3 #define HKDF_CONTEXT_DIRECT_KEY 3
#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 #define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4
#define HKDF_CONTEXT_DIRHASH_KEY 5
extern int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, extern int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
const u8 *info, unsigned int infolen, const u8 *info, unsigned int infolen,
u8 *okm, unsigned int okmlen); u8 *okm, unsigned int okmlen);
...@@ -448,18 +435,17 @@ struct fscrypt_mode { ...@@ -448,18 +435,17 @@ struct fscrypt_mode {
int logged_impl_name; int logged_impl_name;
}; };
static inline bool extern struct fscrypt_mode fscrypt_modes[];
fscrypt_mode_supports_direct_key(const struct fscrypt_mode *mode)
{
return mode->ivsize >= offsetofend(union fscrypt_iv, nonce);
}
extern struct crypto_skcipher * extern struct crypto_skcipher *
fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key, fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
const struct inode *inode); const struct inode *inode);
extern int fscrypt_set_derived_key(struct fscrypt_info *ci, extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci,
const u8 *derived_key); const u8 *raw_key);
extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk);
/* keysetup_v1.c */ /* keysetup_v1.c */
......
...@@ -112,7 +112,7 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, ...@@ -112,7 +112,7 @@ int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
* adds to its application-specific info strings to guarantee that it doesn't * adds to its application-specific info strings to guarantee that it doesn't
* accidentally repeat an info string when using HKDF for different purposes.) * accidentally repeat an info string when using HKDF for different purposes.)
*/ */
int fscrypt_hkdf_expand(struct fscrypt_hkdf *hkdf, u8 context, int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
const u8 *info, unsigned int infolen, const u8 *info, unsigned int infolen,
u8 *okm, unsigned int okmlen) u8 *okm, unsigned int okmlen)
{ {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* Encryption hooks for higher-level filesystem operations. * Encryption hooks for higher-level filesystem operations.
*/ */
#include <linux/key.h>
#include "fscrypt_private.h" #include "fscrypt_private.h"
/** /**
...@@ -122,6 +124,48 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, ...@@ -122,6 +124,48 @@ int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
} }
EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup); EXPORT_SYMBOL_GPL(__fscrypt_prepare_lookup);
/**
* fscrypt_prepare_setflags() - prepare to change flags with FS_IOC_SETFLAGS
* @inode: the inode on which flags are being changed
* @oldflags: the old flags
* @flags: the new flags
*
* The caller should be holding i_rwsem for write.
*
* Return: 0 on success; -errno if the flags change isn't allowed or if
* another error occurs.
*/
int fscrypt_prepare_setflags(struct inode *inode,
unsigned int oldflags, unsigned int flags)
{
struct fscrypt_info *ci;
struct fscrypt_master_key *mk;
int err;
/*
* When the CASEFOLD flag is set on an encrypted directory, we must
* derive the secret key needed for the dirhash. This is only possible
* if the directory uses a v2 encryption policy.
*/
if (IS_ENCRYPTED(inode) && (flags & ~oldflags & FS_CASEFOLD_FL)) {
err = fscrypt_require_key(inode);
if (err)
return err;
ci = inode->i_crypt_info;
if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
return -EINVAL;
mk = ci->ci_master_key->payload.data[0];
down_read(&mk->mk_secret_sem);
if (is_master_key_secret_present(&mk->mk_secret))
err = fscrypt_derive_dirhash_key(ci, mk);
else
err = -ENOKEY;
up_read(&mk->mk_secret_sem);
return err;
}
return 0;
}
int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
unsigned int max_len, unsigned int max_len,
struct fscrypt_str *disk_link) struct fscrypt_str *disk_link)
...@@ -188,7 +232,8 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target, ...@@ -188,7 +232,8 @@ int __fscrypt_encrypt_symlink(struct inode *inode, const char *target,
ciphertext_len = disk_link->len - sizeof(*sd); ciphertext_len = disk_link->len - sizeof(*sd);
sd->len = cpu_to_le16(ciphertext_len); sd->len = cpu_to_le16(ciphertext_len);
err = fname_encrypt(inode, &iname, sd->encrypted_path, ciphertext_len); err = fscrypt_fname_encrypt(inode, &iname, sd->encrypted_path,
ciphertext_len);
if (err) if (err)
goto err_free_sd; goto err_free_sd;
......
...@@ -465,6 +465,109 @@ static int add_master_key(struct super_block *sb, ...@@ -465,6 +465,109 @@ static int add_master_key(struct super_block *sb,
return err; return err;
} }
static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep)
{
const struct fscrypt_provisioning_key_payload *payload = prep->data;
if (prep->datalen < sizeof(*payload) + FSCRYPT_MIN_KEY_SIZE ||
prep->datalen > sizeof(*payload) + FSCRYPT_MAX_KEY_SIZE)
return -EINVAL;
if (payload->type != FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
payload->type != FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER)
return -EINVAL;
if (payload->__reserved)
return -EINVAL;
prep->payload.data[0] = kmemdup(payload, prep->datalen, GFP_KERNEL);
if (!prep->payload.data[0])
return -ENOMEM;
prep->quotalen = prep->datalen;
return 0;
}
static void fscrypt_provisioning_key_free_preparse(
struct key_preparsed_payload *prep)
{
kzfree(prep->payload.data[0]);
}
static void fscrypt_provisioning_key_describe(const struct key *key,
struct seq_file *m)
{
seq_puts(m, key->description);
if (key_is_positive(key)) {
const struct fscrypt_provisioning_key_payload *payload =
key->payload.data[0];
seq_printf(m, ": %u [%u]", key->datalen, payload->type);
}
}
static void fscrypt_provisioning_key_destroy(struct key *key)
{
kzfree(key->payload.data[0]);
}
static struct key_type key_type_fscrypt_provisioning = {
.name = "fscrypt-provisioning",
.preparse = fscrypt_provisioning_key_preparse,
.free_preparse = fscrypt_provisioning_key_free_preparse,
.instantiate = generic_key_instantiate,
.describe = fscrypt_provisioning_key_describe,
.destroy = fscrypt_provisioning_key_destroy,
};
/*
* Retrieve the raw key from the Linux keyring key specified by 'key_id', and
* store it into 'secret'.
*
* The key must be of type "fscrypt-provisioning" and must have the field
* fscrypt_provisioning_key_payload::type set to 'type', indicating that it's
* only usable with fscrypt with the particular KDF version identified by
* 'type'. We don't use the "logon" key type because there's no way to
* completely restrict the use of such keys; they can be used by any kernel API
* that accepts "logon" keys and doesn't require a specific service prefix.
*
* The ability to specify the key via Linux keyring key is intended for cases
* where userspace needs to re-add keys after the filesystem is unmounted and
* re-mounted. Most users should just provide the raw key directly instead.
*/
static int get_keyring_key(u32 key_id, u32 type,
struct fscrypt_master_key_secret *secret)
{
key_ref_t ref;
struct key *key;
const struct fscrypt_provisioning_key_payload *payload;
int err;
ref = lookup_user_key(key_id, 0, KEY_NEED_SEARCH);
if (IS_ERR(ref))
return PTR_ERR(ref);
key = key_ref_to_ptr(ref);
if (key->type != &key_type_fscrypt_provisioning)
goto bad_key;
payload = key->payload.data[0];
/* Don't allow fscrypt v1 keys to be used as v2 keys and vice versa. */
if (payload->type != type)
goto bad_key;
secret->size = key->datalen - sizeof(*payload);
memcpy(secret->raw, payload->raw, secret->size);
err = 0;
goto out_put;
bad_key:
err = -EKEYREJECTED;
out_put:
key_ref_put(ref);
return err;
}
/* /*
* Add a master encryption key to the filesystem, causing all files which were * Add a master encryption key to the filesystem, causing all files which were
* encrypted with it to appear "unlocked" (decrypted) when accessed. * encrypted with it to appear "unlocked" (decrypted) when accessed.
...@@ -503,18 +606,25 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) ...@@ -503,18 +606,25 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg)
if (!valid_key_spec(&arg.key_spec)) if (!valid_key_spec(&arg.key_spec))
return -EINVAL; return -EINVAL;
if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE ||
arg.raw_size > FSCRYPT_MAX_KEY_SIZE)
return -EINVAL;
if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved)))
return -EINVAL; return -EINVAL;
memset(&secret, 0, sizeof(secret)); memset(&secret, 0, sizeof(secret));
secret.size = arg.raw_size; if (arg.key_id) {
err = -EFAULT; if (arg.raw_size != 0)
if (copy_from_user(secret.raw, uarg->raw, secret.size)) return -EINVAL;
goto out_wipe_secret; err = get_keyring_key(arg.key_id, arg.key_spec.type, &secret);
if (err)
goto out_wipe_secret;
} else {
if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE ||
arg.raw_size > FSCRYPT_MAX_KEY_SIZE)
return -EINVAL;
secret.size = arg.raw_size;
err = -EFAULT;
if (copy_from_user(secret.raw, uarg->raw, secret.size))
goto out_wipe_secret;
}
switch (arg.key_spec.type) { switch (arg.key_spec.type) {
case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
...@@ -666,9 +776,6 @@ static int check_for_busy_inodes(struct super_block *sb, ...@@ -666,9 +776,6 @@ static int check_for_busy_inodes(struct super_block *sb,
struct list_head *pos; struct list_head *pos;
size_t busy_count = 0; size_t busy_count = 0;
unsigned long ino; unsigned long ino;
struct dentry *dentry;
char _path[256];
char *path = NULL;
spin_lock(&mk->mk_decrypted_inodes_lock); spin_lock(&mk->mk_decrypted_inodes_lock);
...@@ -687,22 +794,14 @@ static int check_for_busy_inodes(struct super_block *sb, ...@@ -687,22 +794,14 @@ static int check_for_busy_inodes(struct super_block *sb,
struct fscrypt_info, struct fscrypt_info,
ci_master_key_link)->ci_inode; ci_master_key_link)->ci_inode;
ino = inode->i_ino; ino = inode->i_ino;
dentry = d_find_alias(inode);
} }
spin_unlock(&mk->mk_decrypted_inodes_lock); spin_unlock(&mk->mk_decrypted_inodes_lock);
if (dentry) {
path = dentry_path(dentry, _path, sizeof(_path));
dput(dentry);
}
if (IS_ERR_OR_NULL(path))
path = "(unknown)";
fscrypt_warn(NULL, fscrypt_warn(NULL,
"%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu (%s)", "%s: %zu inode(s) still busy after removing key with %s %*phN, including ino %lu",
sb->s_id, busy_count, master_key_spec_type(&mk->mk_spec), sb->s_id, busy_count, master_key_spec_type(&mk->mk_spec),
master_key_spec_len(&mk->mk_spec), (u8 *)&mk->mk_spec.u, master_key_spec_len(&mk->mk_spec), (u8 *)&mk->mk_spec.u,
ino, path); ino);
return -EBUSY; return -EBUSY;
} }
...@@ -978,8 +1077,14 @@ int __init fscrypt_init_keyring(void) ...@@ -978,8 +1077,14 @@ int __init fscrypt_init_keyring(void)
if (err) if (err)
goto err_unregister_fscrypt; goto err_unregister_fscrypt;
err = register_key_type(&key_type_fscrypt_provisioning);
if (err)
goto err_unregister_fscrypt_user;
return 0; return 0;
err_unregister_fscrypt_user:
unregister_key_type(&key_type_fscrypt_user);
err_unregister_fscrypt: err_unregister_fscrypt:
unregister_key_type(&key_type_fscrypt); unregister_key_type(&key_type_fscrypt);
return err; return err;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "fscrypt_private.h" #include "fscrypt_private.h"
static struct fscrypt_mode available_modes[] = { struct fscrypt_mode fscrypt_modes[] = {
[FSCRYPT_MODE_AES_256_XTS] = { [FSCRYPT_MODE_AES_256_XTS] = {
.friendly_name = "AES-256-XTS", .friendly_name = "AES-256-XTS",
.cipher_str = "xts(aes)", .cipher_str = "xts(aes)",
...@@ -51,10 +51,10 @@ select_encryption_mode(const union fscrypt_policy *policy, ...@@ -51,10 +51,10 @@ select_encryption_mode(const union fscrypt_policy *policy,
const struct inode *inode) const struct inode *inode)
{ {
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
return &available_modes[fscrypt_policy_contents_mode(policy)]; return &fscrypt_modes[fscrypt_policy_contents_mode(policy)];
if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
return &available_modes[fscrypt_policy_fnames_mode(policy)]; return &fscrypt_modes[fscrypt_policy_fnames_mode(policy)];
WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n",
inode->i_ino, (inode->i_mode & S_IFMT)); inode->i_ino, (inode->i_mode & S_IFMT));
...@@ -89,8 +89,11 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, ...@@ -89,8 +89,11 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
* first time a mode is used. * first time a mode is used.
*/ */
pr_info("fscrypt: %s using implementation \"%s\"\n", pr_info("fscrypt: %s using implementation \"%s\"\n",
mode->friendly_name, mode->friendly_name, crypto_skcipher_driver_name(tfm));
crypto_skcipher_alg(tfm)->base.cra_driver_name); }
if (WARN_ON(crypto_skcipher_ivsize(tfm) != mode->ivsize)) {
err = -EINVAL;
goto err_free_tfm;
} }
crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS);
err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize); err = crypto_skcipher_setkey(tfm, raw_key, mode->keysize);
...@@ -104,12 +107,12 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode, ...@@ -104,12 +107,12 @@ struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
return ERR_PTR(err); return ERR_PTR(err);
} }
/* Given the per-file key, set up the file's crypto transform object */ /* Given a per-file encryption key, set up the file's crypto transform object */
int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key)
{ {
struct crypto_skcipher *tfm; struct crypto_skcipher *tfm;
tfm = fscrypt_allocate_skcipher(ci->ci_mode, derived_key, ci->ci_inode); tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode);
if (IS_ERR(tfm)) if (IS_ERR(tfm))
return PTR_ERR(tfm); return PTR_ERR(tfm);
...@@ -118,15 +121,15 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key) ...@@ -118,15 +121,15 @@ int fscrypt_set_derived_key(struct fscrypt_info *ci, const u8 *derived_key)
return 0; return 0;
} }
static int setup_per_mode_key(struct fscrypt_info *ci, static int setup_per_mode_enc_key(struct fscrypt_info *ci,
struct fscrypt_master_key *mk, struct fscrypt_master_key *mk,
struct crypto_skcipher **tfms, struct crypto_skcipher **tfms,
u8 hkdf_context, bool include_fs_uuid) u8 hkdf_context, bool include_fs_uuid)
{ {
const struct inode *inode = ci->ci_inode; const struct inode *inode = ci->ci_inode;
const struct super_block *sb = inode->i_sb; 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; const u8 mode_num = mode - fscrypt_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)]; u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)];
...@@ -171,29 +174,37 @@ static int setup_per_mode_key(struct fscrypt_info *ci, ...@@ -171,29 +174,37 @@ static int setup_per_mode_key(struct fscrypt_info *ci,
return 0; return 0;
} }
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
const struct fscrypt_master_key *mk)
{
int err;
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY,
ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE,
(u8 *)&ci->ci_dirhash_key,
sizeof(ci->ci_dirhash_key));
if (err)
return err;
ci->ci_dirhash_key_initialized = true;
return 0;
}
static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
struct fscrypt_master_key *mk) struct fscrypt_master_key *mk)
{ {
u8 derived_key[FSCRYPT_MAX_KEY_SIZE];
int err; int err;
if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) { if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
/* /*
* DIRECT_KEY: instead of deriving per-file keys, the per-file * DIRECT_KEY: instead of deriving per-file encryption keys, the
* nonce will be included in all the IVs. But unlike v1 * per-file nonce will be included in all the IVs. But unlike
* policies, for v2 policies in this case we don't encrypt with * v1 policies, for v2 policies in this case we don't encrypt
* the master key directly but rather derive a per-mode key. * with the master key directly but rather derive a per-mode
* This ensures that the master key is consistently used only * encryption key. This ensures that the master key is
* for HKDF, avoiding key reuse issues. * consistently used only for HKDF, avoiding key reuse issues.
*/ */
if (!fscrypt_mode_supports_direct_key(ci->ci_mode)) { err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_tfms,
fscrypt_warn(ci->ci_inode, HKDF_CONTEXT_DIRECT_KEY, false);
"Direct key flag not allowed with %s",
ci->ci_mode->friendly_name);
return -EINVAL;
}
return setup_per_mode_key(ci, mk, mk->mk_direct_tfms,
HKDF_CONTEXT_DIRECT_KEY, false);
} else if (ci->ci_policy.v2.flags & } else if (ci->ci_policy.v2.flags &
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
/* /*
...@@ -202,21 +213,34 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, ...@@ -202,21 +213,34 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
* the IVs. This format is optimized for use with inline * the IVs. This format is optimized for use with inline
* encryption hardware compliant with the UFS or eMMC standards. * encryption hardware compliant with the UFS or eMMC standards.
*/ */
return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms, err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms,
HKDF_CONTEXT_IV_INO_LBLK_64_KEY, HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
true); true);
} else {
u8 derived_key[FSCRYPT_MAX_KEY_SIZE];
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
HKDF_CONTEXT_PER_FILE_ENC_KEY,
ci->ci_nonce,
FS_KEY_DERIVATION_NONCE_SIZE,
derived_key, ci->ci_mode->keysize);
if (err)
return err;
err = fscrypt_set_per_file_enc_key(ci, derived_key);
memzero_explicit(derived_key, ci->ci_mode->keysize);
} }
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
HKDF_CONTEXT_PER_FILE_KEY,
ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE,
derived_key, ci->ci_mode->keysize);
if (err) if (err)
return err; return err;
err = fscrypt_set_derived_key(ci, derived_key); /* Derive a secret dirhash key for directories that need it. */
memzero_explicit(derived_key, ci->ci_mode->keysize); if (S_ISDIR(ci->ci_inode->i_mode) && IS_CASEFOLDED(ci->ci_inode)) {
return err; err = fscrypt_derive_dirhash_key(ci, mk);
if (err)
return err;
}
return 0;
} }
/* /*
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* This file implements compatibility functions for the original encryption * This file implements compatibility functions for the original encryption
* policy version ("v1"), including: * policy version ("v1"), including:
* *
* - Deriving per-file keys using the AES-128-ECB based KDF * - Deriving per-file encryption keys using the AES-128-ECB based KDF
* (rather than the new method of using HKDF-SHA512) * (rather than the new method of using HKDF-SHA512)
* *
* - Retrieving fscrypt master keys from process-subscribed keyrings * - Retrieving fscrypt master keys from process-subscribed keyrings
...@@ -253,23 +253,8 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key) ...@@ -253,23 +253,8 @@ fscrypt_get_direct_key(const struct fscrypt_info *ci, const u8 *raw_key)
static int setup_v1_file_key_direct(struct fscrypt_info *ci, static int setup_v1_file_key_direct(struct fscrypt_info *ci,
const u8 *raw_master_key) const u8 *raw_master_key)
{ {
const struct fscrypt_mode *mode = ci->ci_mode;
struct fscrypt_direct_key *dk; struct fscrypt_direct_key *dk;
if (!fscrypt_mode_supports_direct_key(mode)) {
fscrypt_warn(ci->ci_inode,
"Direct key mode not allowed with %s",
mode->friendly_name);
return -EINVAL;
}
if (ci->ci_policy.v1.contents_encryption_mode !=
ci->ci_policy.v1.filenames_encryption_mode) {
fscrypt_warn(ci->ci_inode,
"Direct key mode not allowed with different contents and filenames modes");
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);
...@@ -298,7 +283,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci, ...@@ -298,7 +283,7 @@ static int setup_v1_file_key_derived(struct fscrypt_info *ci,
if (err) if (err)
goto out; goto out;
err = fscrypt_set_derived_key(ci, derived_key); err = fscrypt_set_per_file_enc_key(ci, derived_key);
out: out:
kzfree(derived_key); kzfree(derived_key);
return err; return err;
......
...@@ -29,6 +29,43 @@ bool fscrypt_policies_equal(const union fscrypt_policy *policy1, ...@@ -29,6 +29,43 @@ 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 fscrypt_valid_enc_modes(u32 contents_mode, u32 filenames_mode)
{
if (contents_mode == FSCRYPT_MODE_AES_256_XTS &&
filenames_mode == FSCRYPT_MODE_AES_256_CTS)
return true;
if (contents_mode == FSCRYPT_MODE_AES_128_CBC &&
filenames_mode == FSCRYPT_MODE_AES_128_CTS)
return true;
if (contents_mode == FSCRYPT_MODE_ADIANTUM &&
filenames_mode == FSCRYPT_MODE_ADIANTUM)
return true;
return false;
}
static bool supported_direct_key_modes(const struct inode *inode,
u32 contents_mode, u32 filenames_mode)
{
const struct fscrypt_mode *mode;
if (contents_mode != filenames_mode) {
fscrypt_warn(inode,
"Direct key flag not allowed with different contents and filenames modes");
return false;
}
mode = &fscrypt_modes[contents_mode];
if (mode->ivsize < offsetofend(union fscrypt_iv, nonce)) {
fscrypt_warn(inode, "Direct key flag not allowed with %s",
mode->friendly_name);
return false;
}
return true;
}
static bool supported_iv_ino_lblk_64_policy( static bool supported_iv_ino_lblk_64_policy(
const struct fscrypt_policy_v2 *policy, const struct fscrypt_policy_v2 *policy,
const struct inode *inode) const struct inode *inode)
...@@ -63,13 +100,82 @@ static bool supported_iv_ino_lblk_64_policy( ...@@ -63,13 +100,82 @@ static bool supported_iv_ino_lblk_64_policy(
return true; return true;
} }
static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy,
const struct inode *inode)
{
if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode,
policy->filenames_encryption_mode)) {
fscrypt_warn(inode,
"Unsupported encryption modes (contents %d, filenames %d)",
policy->contents_encryption_mode,
policy->filenames_encryption_mode);
return false;
}
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_DIRECT_KEY) &&
!supported_direct_key_modes(inode, policy->contents_encryption_mode,
policy->filenames_encryption_mode))
return false;
if (IS_CASEFOLDED(inode)) {
/* With v1, there's no way to derive dirhash keys. */
fscrypt_warn(inode,
"v1 policies can't be used on casefolded directories");
return false;
}
return true;
}
static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy,
const struct inode *inode)
{
if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode,
policy->filenames_encryption_mode)) {
fscrypt_warn(inode,
"Unsupported encryption modes (contents %d, filenames %d)",
policy->contents_encryption_mode,
policy->filenames_encryption_mode);
return false;
}
if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) {
fscrypt_warn(inode, "Unsupported encryption flags (0x%02x)",
policy->flags);
return false;
}
if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) &&
!supported_direct_key_modes(inode, policy->contents_encryption_mode,
policy->filenames_encryption_mode))
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, "Reserved bits set in encryption policy");
return false;
}
return true;
}
/** /**
* fscrypt_supported_policy - check whether an encryption policy is supported * fscrypt_supported_policy - check whether an encryption policy is supported
* *
* Given an encryption policy, check whether all its encryption modes and other * Given an encryption policy, check whether all its encryption modes and other
* settings are supported by this kernel. (But we don't currently don't check * settings are supported by this kernel on the given inode. (But we don't
* for crypto API support here, so attempting to use an algorithm not configured * currently don't check for crypto API support here, so attempting to use an
* into the crypto API will still fail later.) * algorithm not configured into the crypto API will still fail later.)
* *
* Return: %true if supported, else %false * Return: %true if supported, else %false
*/ */
...@@ -77,60 +183,10 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u, ...@@ -77,60 +183,10 @@ bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
const struct inode *inode) const struct inode *inode)
{ {
switch (policy_u->version) { switch (policy_u->version) {
case FSCRYPT_POLICY_V1: { case FSCRYPT_POLICY_V1:
const struct fscrypt_policy_v1 *policy = &policy_u->v1; return fscrypt_supported_v1_policy(&policy_u->v1, inode);
case FSCRYPT_POLICY_V2:
if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode, return fscrypt_supported_v2_policy(&policy_u->v2, inode);
policy->filenames_encryption_mode)) {
fscrypt_warn(inode,
"Unsupported encryption modes (contents %d, filenames %d)",
policy->contents_encryption_mode,
policy->filenames_encryption_mode);
return false;
}
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;
}
return true;
}
case FSCRYPT_POLICY_V2: {
const struct fscrypt_policy_v2 *policy = &policy_u->v2;
if (!fscrypt_valid_enc_modes(policy->contents_encryption_mode,
policy->filenames_encryption_mode)) {
fscrypt_warn(inode,
"Unsupported encryption modes (contents %d, filenames %d)",
policy->contents_encryption_mode,
policy->filenames_encryption_mode);
return false;
}
if (policy->flags & ~FSCRYPT_POLICY_FLAGS_VALID) {
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,
"Reserved bits set in encryption policy");
return false;
}
return true;
}
} }
return false; return false;
} }
......
...@@ -39,6 +39,7 @@ config EXT4_FS ...@@ -39,6 +39,7 @@ config EXT4_FS
select CRYPTO select CRYPTO
select CRYPTO_CRC32C select CRYPTO_CRC32C
select FS_IOMAP select FS_IOMAP
select FS_ENCRYPTION_ALGS if FS_ENCRYPTION
help help
This is the next generation of the ext3 filesystem. This is the next generation of the ext3 filesystem.
......
...@@ -120,7 +120,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx) ...@@ -120,7 +120,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
if (IS_ENCRYPTED(inode)) { if (IS_ENCRYPTED(inode)) {
err = fscrypt_get_encryption_info(inode); err = fscrypt_get_encryption_info(inode);
if (err && err != -ENOKEY) if (err)
return err; return err;
} }
......
...@@ -6,6 +6,7 @@ config F2FS_FS ...@@ -6,6 +6,7 @@ config F2FS_FS
select CRYPTO select CRYPTO
select CRYPTO_CRC32 select CRYPTO_CRC32
select F2FS_FS_XATTR if FS_ENCRYPTION select F2FS_FS_XATTR if FS_ENCRYPTION
select FS_ENCRYPTION_ALGS if FS_ENCRYPTION
help help
F2FS is based on Log-structured File System (LFS), which supports F2FS is based on Log-structured File System (LFS), which supports
versatile "flash-friendly" features. The design has been focused on versatile "flash-friendly" features. The design has been focused on
......
...@@ -987,7 +987,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx) ...@@ -987,7 +987,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
if (IS_ENCRYPTED(inode)) { if (IS_ENCRYPTED(inode)) {
err = fscrypt_get_encryption_info(inode); err = fscrypt_get_encryption_info(inode);
if (err && err != -ENOKEY) if (err)
goto out; goto out;
err = fscrypt_fname_alloc_buffer(inode, F2FS_NAME_LEN, &fstr); err = fscrypt_fname_alloc_buffer(inode, F2FS_NAME_LEN, &fstr);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/fscrypt.h>
#include <linux/fsnotify.h> #include <linux/fsnotify.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/posix_acl.h> #include <linux/posix_acl.h>
...@@ -2252,7 +2253,7 @@ int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags, ...@@ -2252,7 +2253,7 @@ int vfs_ioc_setflags_prepare(struct inode *inode, unsigned int oldflags,
!capable(CAP_LINUX_IMMUTABLE)) !capable(CAP_LINUX_IMMUTABLE))
return -EPERM; return -EPERM;
return 0; return fscrypt_prepare_setflags(inode, oldflags, flags);
} }
EXPORT_SYMBOL(vfs_ioc_setflags_prepare); EXPORT_SYMBOL(vfs_ioc_setflags_prepare);
......
...@@ -12,6 +12,7 @@ config UBIFS_FS ...@@ -12,6 +12,7 @@ config UBIFS_FS
select CRYPTO_ZSTD if UBIFS_FS_ZSTD select CRYPTO_ZSTD if UBIFS_FS_ZSTD
select CRYPTO_HASH_INFO select CRYPTO_HASH_INFO
select UBIFS_FS_XATTR if FS_ENCRYPTION select UBIFS_FS_XATTR if FS_ENCRYPTION
select FS_ENCRYPTION_ALGS if FS_ENCRYPTION
depends on MTD_UBI depends on MTD_UBI
help help
UBIFS is a file system for flash devices which works on top of UBI. UBIFS is a file system for flash devices which works on top of UBI.
......
...@@ -81,7 +81,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir, ...@@ -81,7 +81,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
struct ubifs_inode *ui; struct ubifs_inode *ui;
bool encrypted = false; bool encrypted = false;
if (ubifs_crypt_is_encrypted(dir)) { if (IS_ENCRYPTED(dir)) {
err = fscrypt_get_encryption_info(dir); err = fscrypt_get_encryption_info(dir);
if (err) { if (err) {
ubifs_err(c, "fscrypt_get_encryption_info failed: %i", err); ubifs_err(c, "fscrypt_get_encryption_info failed: %i", err);
...@@ -225,9 +225,9 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -225,9 +225,9 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
goto done; goto done;
} }
if (nm.hash) { if (fname_name(&nm) == NULL) {
ubifs_assert(c, fname_len(&nm) == 0); if (nm.hash & ~UBIFS_S_KEY_HASH_MASK)
ubifs_assert(c, fname_name(&nm) == NULL); goto done; /* ENOENT */
dent_key_init_hash(c, &key, dir->i_ino, nm.hash); dent_key_init_hash(c, &key, dir->i_ino, nm.hash);
err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash); err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash);
} else { } else {
...@@ -261,7 +261,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -261,7 +261,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
goto done; goto done;
} }
if (ubifs_crypt_is_encrypted(dir) && if (IS_ENCRYPTED(dir) &&
(S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) && (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
!fscrypt_has_permitted_context(dir, inode)) { !fscrypt_has_permitted_context(dir, inode)) {
ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu", ubifs_warn(c, "Inconsistent encryption contexts: %lu/%lu",
...@@ -499,7 +499,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx) ...@@ -499,7 +499,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
struct ubifs_dent_node *dent; struct ubifs_dent_node *dent;
struct inode *dir = file_inode(file); struct inode *dir = file_inode(file);
struct ubifs_info *c = dir->i_sb->s_fs_info; struct ubifs_info *c = dir->i_sb->s_fs_info;
bool encrypted = ubifs_crypt_is_encrypted(dir); bool encrypted = IS_ENCRYPTED(dir);
dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos); dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, ctx->pos);
...@@ -512,7 +512,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx) ...@@ -512,7 +512,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
if (encrypted) { if (encrypted) {
err = fscrypt_get_encryption_info(dir); err = fscrypt_get_encryption_info(dir);
if (err && err != -ENOKEY) if (err)
return err; return err;
err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr); err = fscrypt_fname_alloc_buffer(dir, UBIFS_MAX_NLEN, &fstr);
...@@ -1618,7 +1618,7 @@ int ubifs_getattr(const struct path *path, struct kstat *stat, ...@@ -1618,7 +1618,7 @@ int ubifs_getattr(const struct path *path, struct kstat *stat,
static int ubifs_dir_open(struct inode *dir, struct file *file) static int ubifs_dir_open(struct inode *dir, struct file *file)
{ {
if (ubifs_crypt_is_encrypted(dir)) if (IS_ENCRYPTED(dir))
return fscrypt_get_encryption_info(dir) ? -EACCES : 0; return fscrypt_get_encryption_info(dir) ? -EACCES : 0;
return 0; return 0;
......
...@@ -67,7 +67,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block, ...@@ -67,7 +67,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
if (ubifs_crypt_is_encrypted(inode)) { if (IS_ENCRYPTED(inode)) {
err = ubifs_decrypt(inode, dn, &dlen, block); err = ubifs_decrypt(inode, dn, &dlen, block);
if (err) if (err)
goto dump; goto dump;
...@@ -647,7 +647,7 @@ static int populate_page(struct ubifs_info *c, struct page *page, ...@@ -647,7 +647,7 @@ static int populate_page(struct ubifs_info *c, struct page *page,
dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
out_len = UBIFS_BLOCK_SIZE; out_len = UBIFS_BLOCK_SIZE;
if (ubifs_crypt_is_encrypted(inode)) { if (IS_ENCRYPTED(inode)) {
err = ubifs_decrypt(inode, dn, &dlen, page_block); err = ubifs_decrypt(inode, dn, &dlen, page_block);
if (err) if (err)
goto out_err; goto out_err;
......
...@@ -588,7 +588,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -588,7 +588,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
if (!xent) { if (!xent) {
dent->ch.node_type = UBIFS_DENT_NODE; dent->ch.node_type = UBIFS_DENT_NODE;
if (nm->hash) if (fname_name(nm) == NULL)
dent_key_init_hash(c, &dent_key, dir->i_ino, nm->hash); dent_key_init_hash(c, &dent_key, dir->i_ino, nm->hash);
else else
dent_key_init(c, &dent_key, dir->i_ino, nm); dent_key_init(c, &dent_key, dir->i_ino, nm);
...@@ -646,7 +646,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ...@@ -646,7 +646,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
ubifs_add_auth_dirt(c, lnum); ubifs_add_auth_dirt(c, lnum);
if (deletion) { if (deletion) {
if (nm->hash) if (fname_name(nm) == NULL)
err = ubifs_tnc_remove_dh(c, &dent_key, nm->minor_hash); err = ubifs_tnc_remove_dh(c, &dent_key, nm->minor_hash);
else else
err = ubifs_tnc_remove_nm(c, &dent_key, nm); err = ubifs_tnc_remove_nm(c, &dent_key, nm);
...@@ -727,7 +727,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode, ...@@ -727,7 +727,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1; int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
int write_len; int write_len;
struct ubifs_inode *ui = ubifs_inode(inode); struct ubifs_inode *ui = ubifs_inode(inode);
bool encrypted = ubifs_crypt_is_encrypted(inode); bool encrypted = IS_ENCRYPTED(inode);
u8 hash[UBIFS_HASH_ARR_SZ]; u8 hash[UBIFS_HASH_ARR_SZ];
dbg_jnlk(key, "ino %lu, blk %u, len %d, key ", dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
...@@ -1449,7 +1449,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in ...@@ -1449,7 +1449,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
dlen = old_dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; dlen = old_dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
compr_type = le16_to_cpu(dn->compr_type); compr_type = le16_to_cpu(dn->compr_type);
if (ubifs_crypt_is_encrypted(inode)) { if (IS_ENCRYPTED(inode)) {
err = ubifs_decrypt(inode, dn, &dlen, block); err = ubifs_decrypt(inode, dn, &dlen, block);
if (err) if (err)
goto out; goto out;
...@@ -1465,7 +1465,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in ...@@ -1465,7 +1465,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type); ubifs_compress(c, buf, *new_len, &dn->data, &out_len, &compr_type);
} }
if (ubifs_crypt_is_encrypted(inode)) { if (IS_ENCRYPTED(inode)) {
err = ubifs_encrypt(inode, dn, out_len, &old_dlen, block); err = ubifs_encrypt(inode, dn, out_len, &old_dlen, block);
if (err) if (err)
goto out; goto out;
......
...@@ -150,7 +150,6 @@ static inline void dent_key_init(const struct ubifs_info *c, ...@@ -150,7 +150,6 @@ static inline void dent_key_init(const struct ubifs_info *c,
uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm)); uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm));
ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK)); ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK));
ubifs_assert(c, !nm->hash && !nm->minor_hash);
key->u32[0] = inum; key->u32[0] = inum;
key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS); key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
} }
......
...@@ -2095,13 +2095,6 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn, ...@@ -2095,13 +2095,6 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
extern const struct fscrypt_operations ubifs_crypt_operations; extern const struct fscrypt_operations ubifs_crypt_operations;
static inline bool ubifs_crypt_is_encrypted(const struct inode *inode)
{
const struct ubifs_inode *ui = ubifs_inode(inode);
return ui->flags & UBIFS_CRYPT_FL;
}
/* Normal UBIFS messages */ /* Normal UBIFS messages */
__printf(2, 3) __printf(2, 3)
void ubifs_msg(const struct ubifs_info *c, const char *fmt, ...); void ubifs_msg(const struct ubifs_info *c, const char *fmt, ...);
......
...@@ -72,6 +72,21 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode) ...@@ -72,6 +72,21 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
return READ_ONCE(inode->i_crypt_info) != NULL; return READ_ONCE(inode->i_crypt_info) != NULL;
} }
/**
* fscrypt_needs_contents_encryption() - check whether an inode needs
* contents encryption
*
* Return: %true iff the inode is an encrypted regular file and the kernel was
* built with fscrypt support.
*
* If you need to know whether the encrypt bit is set even when the kernel was
* built without fscrypt support, you must use IS_ENCRYPTED() directly instead.
*/
static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
{
return IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode);
}
static inline bool fscrypt_dummy_context_enabled(struct inode *inode) static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
{ {
return inode->i_sb->s_cop->dummy_context && return inode->i_sb->s_cop->dummy_context &&
...@@ -153,82 +168,14 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname) ...@@ -153,82 +168,14 @@ static inline void fscrypt_free_filename(struct fscrypt_name *fname)
extern int fscrypt_fname_alloc_buffer(const struct inode *, u32, extern int fscrypt_fname_alloc_buffer(const struct inode *, u32,
struct fscrypt_str *); struct fscrypt_str *);
extern void fscrypt_fname_free_buffer(struct fscrypt_str *); extern void fscrypt_fname_free_buffer(struct fscrypt_str *);
extern int fscrypt_fname_disk_to_usr(struct inode *, u32, u32, extern int fscrypt_fname_disk_to_usr(const struct inode *inode,
const struct fscrypt_str *, struct fscrypt_str *); u32 hash, u32 minor_hash,
const struct fscrypt_str *iname,
#define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32 struct fscrypt_str *oname);
extern bool fscrypt_match_name(const struct fscrypt_name *fname,
/* Extracts the second-to-last ciphertext block; see explanation below */ const u8 *de_name, u32 de_name_len);
#define FSCRYPT_FNAME_DIGEST(name, len) \ extern u64 fscrypt_fname_siphash(const struct inode *dir,
((name) + round_down((len) - FS_CRYPTO_BLOCK_SIZE - 1, \ const struct qstr *name);
FS_CRYPTO_BLOCK_SIZE))
#define FSCRYPT_FNAME_DIGEST_SIZE FS_CRYPTO_BLOCK_SIZE
/**
* fscrypt_digested_name - alternate identifier for an on-disk filename
*
* When userspace lists an encrypted directory without access to the key,
* filenames whose ciphertext is longer than FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE
* bytes are shown in this abbreviated form (base64-encoded) rather than as the
* full ciphertext (base64-encoded). This is necessary to allow supporting
* filenames up to NAME_MAX bytes, since base64 encoding expands the length.
*
* To make it possible for filesystems to still find the correct directory entry
* despite not knowing the full on-disk name, we encode any filesystem-specific
* 'hash' and/or 'minor_hash' which the filesystem may need for its lookups,
* followed by the second-to-last ciphertext block of the filename. Due to the
* use of the CBC-CTS encryption mode, the second-to-last ciphertext block
* depends on the full plaintext. (Note that ciphertext stealing causes the
* last two blocks to appear "flipped".) This makes accidental collisions very
* unlikely: just a 1 in 2^128 chance for two filenames to collide even if they
* share the same filesystem-specific hashes.
*
* However, this scheme isn't immune to intentional collisions, which can be
* created by anyone able to create arbitrary plaintext filenames and view them
* without the key. Making the "digest" be a real cryptographic hash like
* SHA-256 over the full ciphertext would prevent this, although it would be
* less efficient and harder to implement, especially since the filesystem would
* need to calculate it for each directory entry examined during a search.
*/
struct fscrypt_digested_name {
u32 hash;
u32 minor_hash;
u8 digest[FSCRYPT_FNAME_DIGEST_SIZE];
};
/**
* fscrypt_match_name() - test whether the given name matches a directory entry
* @fname: the name being searched for
* @de_name: the name from the directory entry
* @de_name_len: the length of @de_name in bytes
*
* Normally @fname->disk_name will be set, and in that case we simply compare
* that to the name stored in the directory entry. The only exception is that
* if we don't have the key for an encrypted directory and a filename in it is
* very long, then we won't have the full disk_name and we'll instead need to
* match against the fscrypt_digested_name.
*
* Return: %true if the name matches, otherwise %false.
*/
static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
const u8 *de_name, u32 de_name_len)
{
if (unlikely(!fname->disk_name.name)) {
const struct fscrypt_digested_name *n =
(const void *)fname->crypto_buf.name;
if (WARN_ON_ONCE(fname->usr_fname->name[0] != '_'))
return false;
if (de_name_len <= FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE)
return false;
return !memcmp(FSCRYPT_FNAME_DIGEST(de_name, de_name_len),
n->digest, FSCRYPT_FNAME_DIGEST_SIZE);
}
if (de_name_len != fname->disk_name.len)
return false;
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
}
/* bio.c */ /* bio.c */
extern void fscrypt_decrypt_bio(struct bio *); extern void fscrypt_decrypt_bio(struct bio *);
...@@ -246,6 +193,8 @@ extern int __fscrypt_prepare_rename(struct inode *old_dir, ...@@ -246,6 +193,8 @@ extern int __fscrypt_prepare_rename(struct inode *old_dir,
unsigned int flags); unsigned int flags);
extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry, extern int __fscrypt_prepare_lookup(struct inode *dir, struct dentry *dentry,
struct fscrypt_name *fname); struct fscrypt_name *fname);
extern int fscrypt_prepare_setflags(struct inode *inode,
unsigned int oldflags, unsigned int flags);
extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len, extern int __fscrypt_prepare_symlink(struct inode *dir, unsigned int len,
unsigned int max_len, unsigned int max_len,
struct fscrypt_str *disk_link); struct fscrypt_str *disk_link);
...@@ -267,6 +216,11 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode) ...@@ -267,6 +216,11 @@ static inline bool fscrypt_has_encryption_key(const struct inode *inode)
return false; return false;
} }
static inline bool fscrypt_needs_contents_encryption(const struct inode *inode)
{
return false;
}
static inline bool fscrypt_dummy_context_enabled(struct inode *inode) static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
{ {
return false; return false;
...@@ -438,7 +392,7 @@ static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str) ...@@ -438,7 +392,7 @@ static inline void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
return; return;
} }
static inline int fscrypt_fname_disk_to_usr(struct inode *inode, static inline int fscrypt_fname_disk_to_usr(const struct inode *inode,
u32 hash, u32 minor_hash, u32 hash, u32 minor_hash,
const struct fscrypt_str *iname, const struct fscrypt_str *iname,
struct fscrypt_str *oname) struct fscrypt_str *oname)
...@@ -455,6 +409,13 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, ...@@ -455,6 +409,13 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len); return !memcmp(de_name, fname->disk_name.name, fname->disk_name.len);
} }
static inline u64 fscrypt_fname_siphash(const struct inode *dir,
const struct qstr *name)
{
WARN_ON_ONCE(1);
return 0;
}
/* bio.c */ /* bio.c */
static inline void fscrypt_decrypt_bio(struct bio *bio) static inline void fscrypt_decrypt_bio(struct bio *bio)
{ {
...@@ -497,6 +458,13 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir, ...@@ -497,6 +458,13 @@ static inline int __fscrypt_prepare_lookup(struct inode *dir,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int fscrypt_prepare_setflags(struct inode *inode,
unsigned int oldflags,
unsigned int flags)
{
return 0;
}
static inline int __fscrypt_prepare_symlink(struct inode *dir, static inline int __fscrypt_prepare_symlink(struct inode *dir,
unsigned int len, unsigned int len,
unsigned int max_len, unsigned int max_len,
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#ifndef _UAPI_LINUX_FSCRYPT_H #ifndef _UAPI_LINUX_FSCRYPT_H
#define _UAPI_LINUX_FSCRYPT_H #define _UAPI_LINUX_FSCRYPT_H
#include <linux/ioctl.h>
#include <linux/types.h> #include <linux/types.h>
/* Encryption policy flags */ /* Encryption policy flags */
...@@ -109,11 +110,22 @@ struct fscrypt_key_specifier { ...@@ -109,11 +110,22 @@ struct fscrypt_key_specifier {
} u; } u;
}; };
/*
* Payload of Linux keyring key of type "fscrypt-provisioning", referenced by
* fscrypt_add_key_arg::key_id as an alternative to fscrypt_add_key_arg::raw.
*/
struct fscrypt_provisioning_key_payload {
__u32 type;
__u32 __reserved;
__u8 raw[];
};
/* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */ /* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */
struct fscrypt_add_key_arg { struct fscrypt_add_key_arg {
struct fscrypt_key_specifier key_spec; struct fscrypt_key_specifier key_spec;
__u32 raw_size; __u32 raw_size;
__u32 __reserved[9]; __u32 key_id;
__u32 __reserved[8];
__u8 raw[]; __u8 raw[];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment