Commit cd3e8ea8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull fscrypt updates from Eric Biggers:
 "Some cleanups for fs/crypto/:

   - Allow 256-bit master keys with AES-256-XTS

   - Improve documentation and comments

   - Remove unneeded field fscrypt_operations::max_namelen"

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
  fscrypt: improve a few comments
  fscrypt: allow 256-bit master keys with AES-256-XTS
  fscrypt: improve documentation for inline encryption
  fscrypt: clean up comments in bio.c
  fscrypt: remove fscrypt_operations::max_namelen
parents 19901165 b7e072f9
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
.. SPDX-License-Identifier: GPL-2.0
.. SPDX-License-Identifier: GPL-2.0


.. _inline_encryption:

=================
=================
Inline Encryption
Inline Encryption
=================
=================
+61 −22
Original line number Original line Diff line number Diff line
@@ -77,11 +77,11 @@ Side-channel attacks


fscrypt is only resistant to side-channel attacks, such as timing or
fscrypt is only resistant to side-channel attacks, such as timing or
electromagnetic attacks, to the extent that the underlying Linux
electromagnetic attacks, to the extent that the underlying Linux
Cryptographic API algorithms are.  If a vulnerable algorithm is used,
Cryptographic API algorithms or inline encryption hardware are.  If a
such as a table-based implementation of AES, it may be possible for an
vulnerable algorithm is used, such as a table-based implementation of
attacker to mount a side channel attack against the online system.
AES, it may be possible for an attacker to mount a side channel attack
Side channel attacks may also be mounted against applications
against the online system.  Side channel attacks may also be mounted
consuming decrypted data.
against applications consuming decrypted data.


Unauthorized file access
Unauthorized file access
~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -176,11 +176,11 @@ Master Keys


Each encrypted directory tree is protected by a *master key*.  Master
Each encrypted directory tree is protected by a *master key*.  Master
keys can be up to 64 bytes long, and must be at least as long as the
keys can be up to 64 bytes long, and must be at least as long as the
greater of the key length needed by the contents and filenames
greater of the security strength of the contents and filenames
encryption modes being used.  For example, if AES-256-XTS is used for
encryption modes being used.  For example, if any AES-256 mode is
contents encryption, the master key must be 64 bytes (512 bits).  Note
used, the master key must be at least 256 bits, i.e. 32 bytes.  A
that the XTS mode is defined to require a key twice as long as that
stricter requirement applies if the key is used by a v1 encryption
required by the underlying block cipher.
policy and AES-256-XTS is used; such keys must be 64 bytes.


To "unlock" an encrypted directory tree, userspace must provide the
To "unlock" an encrypted directory tree, userspace must provide the
appropriate master key.  There can be any number of master keys, each
appropriate master key.  There can be any number of master keys, each
@@ -1135,6 +1135,50 @@ where applications may later write sensitive data. It is recommended
that systems implementing a form of "verified boot" take advantage of
that systems implementing a form of "verified boot" take advantage of
this by validating all top-level encryption policies prior to access.
this by validating all top-level encryption policies prior to access.


Inline encryption support
=========================

By default, fscrypt uses the kernel crypto API for all cryptographic
operations (other than HKDF, which fscrypt partially implements
itself).  The kernel crypto API supports hardware crypto accelerators,
but only ones that work in the traditional way where all inputs and
outputs (e.g. plaintexts and ciphertexts) are in memory.  fscrypt can
take advantage of such hardware, but the traditional acceleration
model isn't particularly efficient and fscrypt hasn't been optimized
for it.

Instead, many newer systems (especially mobile SoCs) have *inline
encryption hardware* that can encrypt/decrypt data while it is on its
way to/from the storage device.  Linux supports inline encryption
through a set of extensions to the block layer called *blk-crypto*.
blk-crypto allows filesystems to attach encryption contexts to bios
(I/O requests) to specify how the data will be encrypted or decrypted
in-line.  For more information about blk-crypto, see
:ref:`Documentation/block/inline-encryption.rst <inline_encryption>`.

On supported filesystems (currently ext4 and f2fs), fscrypt can use
blk-crypto instead of the kernel crypto API to encrypt/decrypt file
contents.  To enable this, set CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y in
the kernel configuration, and specify the "inlinecrypt" mount option
when mounting the filesystem.

Note that the "inlinecrypt" mount option just specifies to use inline
encryption when possible; it doesn't force its use.  fscrypt will
still fall back to using the kernel crypto API on files where the
inline encryption hardware doesn't have the needed crypto capabilities
(e.g. support for the needed encryption algorithm and data unit size)
and where blk-crypto-fallback is unusable.  (For blk-crypto-fallback
to be usable, it must be enabled in the kernel configuration with
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y.)

Currently fscrypt always uses the filesystem block size (which is
usually 4096 bytes) as the data unit size.  Therefore, it can only use
inline encryption hardware that supports that data unit size.

Inline encryption doesn't affect the ciphertext or other aspects of
the on-disk format, so users may freely switch back and forth between
using "inlinecrypt" and not using "inlinecrypt".

Implementation details
Implementation details
======================
======================


@@ -1184,6 +1228,13 @@ keys`_ and `DIRECT_KEY policies`_.
Data path changes
Data path changes
-----------------
-----------------


When inline encryption is used, filesystems just need to associate
encryption contexts with bios to specify how the block layer or the
inline encryption hardware will encrypt/decrypt the file contents.

When inline encryption isn't used, filesystems must encrypt/decrypt
the file contents themselves, as described below:

For the read path (->readpage()) of regular files, filesystems can
For the read path (->readpage()) of regular files, filesystems can
read the ciphertext into the page cache and decrypt it in-place.  The
read the ciphertext into the page cache and decrypt it in-place.  The
page lock must be held until decryption has finished, to prevent the
page lock must be held until decryption has finished, to prevent the
@@ -1197,18 +1248,6 @@ buffer. Some filesystems, such as UBIFS, already use temporary
buffers regardless of encryption.  Other filesystems, such as ext4 and
buffers regardless of encryption.  Other filesystems, such as ext4 and
F2FS, have to allocate bounce pages specially for encryption.
F2FS, have to allocate bounce pages specially for encryption.


Fscrypt is also able to use inline encryption hardware instead of the
kernel crypto API for en/decryption of file contents.  When possible,
and if directed to do so (by specifying the 'inlinecrypt' mount option
for an ext4/F2FS filesystem), it adds encryption contexts to bios and
uses blk-crypto to perform the en/decryption instead of making use of
the above read/write path changes.  Of course, even if directed to
make use of inline encryption, fscrypt will only be able to do so if
either hardware inline encryption support is available for the
selected encryption algorithm or CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK
is selected.  If neither is the case, fscrypt will fall back to using
the above mentioned read/write path changes for en/decryption.

Filename hashing and encoding
Filename hashing and encoding
-----------------------------
-----------------------------


+17 −15
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0
/*
/*
 * This contains encryption functions for per-file encryption.
 * Utility functions for file contents encryption/decryption on
 * block device-based filesystems.
 *
 *
 * Copyright (C) 2015, Google, Inc.
 * Copyright (C) 2015, Google, Inc.
 * Copyright (C) 2015, Motorola Mobility
 * Copyright (C) 2015, Motorola Mobility
 *
 * Written by Michael Halcrow, 2014.
 *
 * Filename encryption additions
 *	Uday Savagaonkar, 2014
 * Encryption policy handling additions
 *	Ildar Muslukhov, 2014
 * Add fscrypt_pullback_bio_page()
 *	Jaegeuk Kim, 2015.
 *
 * This has not yet undergone a rigorous security audit.
 *
 * The usage of AES-XTS should conform to recommendations in NIST
 * Special Publication 800-38E and IEEE P1619/D16.
 */
 */


#include <linux/pagemap.h>
#include <linux/pagemap.h>
@@ -26,6 +13,21 @@
#include <linux/namei.h>
#include <linux/namei.h>
#include "fscrypt_private.h"
#include "fscrypt_private.h"


/**
 * fscrypt_decrypt_bio() - decrypt the contents of a bio
 * @bio: the bio to decrypt
 *
 * Decrypt the contents of a "read" bio following successful completion of the
 * underlying disk read.  The bio must be reading a whole number of blocks of an
 * encrypted file directly into the page cache.  If the bio is reading the
 * ciphertext into bounce pages instead of the page cache (for example, because
 * the file is also compressed, so decompression is required after decryption),
 * then this function isn't applicable.  This function may sleep, so it must be
 * called from a workqueue rather than from the bio's bi_end_io callback.
 *
 * This function sets PG_error on any pages that contain any blocks that failed
 * to be decrypted.  The filesystem must not mark such pages uptodate.
 */
void fscrypt_decrypt_bio(struct bio *bio)
void fscrypt_decrypt_bio(struct bio *bio)
{
{
	struct bio_vec *bv;
	struct bio_vec *bv;
+1 −2
Original line number Original line Diff line number Diff line
@@ -429,8 +429,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,


	if (fscrypt_has_encryption_key(dir)) {
	if (fscrypt_has_encryption_key(dir)) {
		if (!fscrypt_fname_encrypted_size(&dir->i_crypt_info->ci_policy,
		if (!fscrypt_fname_encrypted_size(&dir->i_crypt_info->ci_policy,
						  iname->len,
						  iname->len, NAME_MAX,
						  dir->i_sb->s_cop->max_namelen,
						  &fname->crypto_buf.len))
						  &fname->crypto_buf.len))
			return -ENAMETOOLONG;
			return -ENAMETOOLONG;
		fname->crypto_buf.name = kmalloc(fname->crypto_buf.len,
		fname->crypto_buf.name = kmalloc(fname->crypto_buf.len,
+13 −3
Original line number Original line Diff line number Diff line
@@ -20,6 +20,11 @@


#define FSCRYPT_FILE_NONCE_SIZE	16
#define FSCRYPT_FILE_NONCE_SIZE	16


/*
 * Minimum size of an fscrypt master key.  Note: a longer key will be required
 * if ciphers with a 256-bit security strength are used.  This is just the
 * absolute minimum, which applies when only 128-bit encryption is used.
 */
#define FSCRYPT_MIN_KEY_SIZE	16
#define FSCRYPT_MIN_KEY_SIZE	16


#define FSCRYPT_CONTEXT_V1	1
#define FSCRYPT_CONTEXT_V1	1
@@ -413,7 +418,11 @@ struct fscrypt_master_key_secret {
	 */
	 */
	struct fscrypt_hkdf	hkdf;
	struct fscrypt_hkdf	hkdf;


	/* Size of the raw key in bytes.  Set even if ->raw isn't set. */
	/*
	 * Size of the raw key in bytes.  This remains set even if ->raw was
	 * zeroized due to no longer being needed.  I.e. we still remember the
	 * size of the key even if we don't need to remember the key itself.
	 */
	u32			size;
	u32			size;


	/* For v1 policy keys: the raw key.  Wiped for v2 policy keys. */
	/* For v1 policy keys: the raw key.  Wiped for v2 policy keys. */
@@ -549,8 +558,9 @@ int __init fscrypt_init_keyring(void);
struct fscrypt_mode {
struct fscrypt_mode {
	const char *friendly_name;
	const char *friendly_name;
	const char *cipher_str;
	const char *cipher_str;
	int keysize;
	int keysize;		/* key size in bytes */
	int ivsize;
	int security_strength;	/* security strength in bytes */
	int ivsize;		/* IV size in bytes */
	int logged_impl_name;
	int logged_impl_name;
	enum blk_crypto_mode_num blk_crypto_mode;
	enum blk_crypto_mode_num blk_crypto_mode;
};
};
Loading