Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2afad6a authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ext4 crypto: enable HW based encryption with ICE"

parents 893e744e a8059e6d
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -6,7 +6,8 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>
#include <linux/security.h>
#include <linux/pfk.h>
#include <linux/pft.h>

#include "blk.h"

@@ -729,6 +730,12 @@ static void blk_account_io_merge(struct request *req)
	}
}

static bool crypto_not_mergeable(const struct bio *bio, const struct bio *nxt)
{
	return (!pft_allow_merge_bio(bio, nxt) ||
		!pfk_allow_merge_bio(bio, nxt));
}

/*
 * Has to be called with the request spinlock acquired
 */
@@ -756,6 +763,9 @@ static int attempt_merge(struct request_queue *q, struct request *req,
	    !blk_write_same_mergeable(req->bio, next->bio))
		return 0;

	if (crypto_not_mergeable(req->bio, next->bio))
		return 0;

	/*
	 * If we are allowed to merge, then append bio list
	 * from next to rq and release next. merge_requests_fn
@@ -860,11 +870,9 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
	    !blk_write_same_mergeable(rq->bio, bio))
		return false;

	/* Don't merge bios of files with different encryption */
	if (!security_allow_merge_bio(rq->bio, bio))
	if (crypto_not_mergeable(rq->bio, bio))
		return false;


	return true;
}

+8 −2
Original line number Diff line number Diff line
@@ -117,10 +117,16 @@ config EXT4_ENCRYPTION
	  decrypted pages in the page cache.

config EXT4_FS_ENCRYPTION
	bool
	default y
	bool "Ext4 FS Encryption"
	default n
	depends on EXT4_ENCRYPTION

config EXT4_FS_ICE_ENCRYPTION
	bool "Ext4 Encryption with ICE support"
	default n
	depends on EXT4_FS_ENCRYPTION
	depends on PFK

config EXT4_DEBUG
	bool "EXT4 debugging support"
	depends on EXT4_FS
+2 −0
Original line number Diff line number Diff line
@@ -14,3 +14,5 @@ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY)		+= xattr_security.o
ext4-$(CONFIG_EXT4_FS_ENCRYPTION)	+= crypto_policy.o crypto.o \
		crypto_key.o crypto_fname.o

ext4-$(CONFIG_EXT4_FS_ICE_ENCRYPTION)	+= ext4_ice.o
+2 −1
Original line number Diff line number Diff line
@@ -458,7 +458,8 @@ errout:

bool ext4_valid_contents_enc_mode(uint32_t mode)
{
	return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS);
	return (mode == EXT4_ENCRYPTION_MODE_AES_256_XTS ||
		mode == EXT4_ENCRYPTION_MODE_PRIVATE);
}

/**
+46 −26
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <uapi/linux/keyctl.h>

#include "ext4.h"
#include "ext4_ice.h"
#include "xattr.h"

static void derive_crypt_complete(struct crypto_async_request *req, int rc)
@@ -111,6 +112,12 @@ void ext4_free_encryption_info(struct inode *inode,
	ext4_free_crypt_info(ci);
}

static int ext4_default_data_encryption_mode(void)
{
	return ext4_is_ice_enabled() ? EXT4_ENCRYPTION_MODE_PRIVATE :
		EXT4_ENCRYPTION_MODE_AES_256_XTS;
}

int _ext4_get_encryption_info(struct inode *inode)
{
	struct ext4_inode_info *ei = EXT4_I(inode);
@@ -124,8 +131,8 @@ int _ext4_get_encryption_info(struct inode *inode)
	struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
	struct crypto_ablkcipher *ctfm;
	const char *cipher_str;
	char raw_key[EXT4_MAX_KEY_SIZE];
	char mode;
	int for_fname = 0;
	int mode;
	int res;

	if (!ext4_read_workqueue) {
@@ -150,7 +157,8 @@ retry:
	if (res < 0) {
		if (!DUMMY_ENCRYPTION_ENABLED(sbi))
			return res;
		ctx.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
		ctx.contents_encryption_mode =
			ext4_default_data_encryption_mode();
		ctx.filenames_encryption_mode =
			EXT4_ENCRYPTION_MODE_AES_256_CTS;
		ctx.flags = 0;
@@ -169,12 +177,12 @@ retry:
	crypt_info->ci_keyring_key = NULL;
	memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
	       sizeof(crypt_info->ci_master_key));
	if (S_ISREG(inode->i_mode))
		mode = crypt_info->ci_data_mode;
	else if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
		mode = crypt_info->ci_filename_mode;
	else
	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
		for_fname = 1;
	else if (!S_ISREG(inode->i_mode))
		BUG();
	mode = for_fname ? crypt_info->ci_filename_mode :
		crypt_info->ci_data_mode;
	switch (mode) {
	case EXT4_ENCRYPTION_MODE_AES_256_XTS:
		cipher_str = "xts(aes)";
@@ -182,6 +190,9 @@ retry:
	case EXT4_ENCRYPTION_MODE_AES_256_CTS:
		cipher_str = "cts(cbc(aes))";
		break;
	case EXT4_ENCRYPTION_MODE_PRIVATE:
		cipher_str = "bugon";
		break;
	default:
		printk_once(KERN_WARNING
			    "ext4: unsupported key mode %d (ino %u)\n",
@@ -190,7 +201,7 @@ retry:
		goto out;
	}
	if (DUMMY_ENCRYPTION_ENABLED(sbi)) {
		memset(raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
		memset(crypt_info->ci_raw_key, 0x42, EXT4_AES_256_XTS_KEY_SIZE);
		goto got_key;
	}
	memcpy(full_key_descriptor, EXT4_KEY_DESC_PREFIX,
@@ -232,16 +243,17 @@ retry:
		goto out;
	}
	res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
				  raw_key);
				  crypt_info->ci_raw_key);
	up_read(&keyring_key->sem);
	if (res)
		goto out;
got_key:
	if (for_fname ||
	    (crypt_info->ci_data_mode != EXT4_ENCRYPTION_MODE_PRIVATE)) {
		ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0);
		if (!ctfm || IS_ERR(ctfm)) {
			res = ctfm ? PTR_ERR(ctfm) : -ENOMEM;
		printk(KERN_DEBUG
		       "%s: error %d (inode %u) allocating crypto tfm\n",
			pr_debug("%s: error %d (inode %u) allocating crypto tfm\n",
				__func__, res, (unsigned) inode->i_ino);
			goto out;
		}
@@ -249,11 +261,18 @@ got_key:
		crypto_ablkcipher_clear_flags(ctfm, ~0);
		crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm),
				     CRYPTO_TFM_REQ_WEAK_KEY);
	res = crypto_ablkcipher_setkey(ctfm, raw_key,
		res = crypto_ablkcipher_setkey(ctfm, crypt_info->ci_raw_key,
					       ext4_encryption_key_size(mode));
		if (res)
			goto out;
	memzero_explicit(raw_key, sizeof(raw_key));
		memzero_explicit(crypt_info->ci_raw_key,
			sizeof(crypt_info->ci_raw_key));
	} else if (!ext4_is_ice_enabled()) {
		pr_warn("%s: ICE support not available\n",
		       __func__);
		res = -EINVAL;
		goto out;
	}
	if (cmpxchg(&ei->i_crypt_info, NULL, crypt_info) != NULL) {
		ext4_free_crypt_info(crypt_info);
		goto retry;
@@ -263,8 +282,9 @@ got_key:
out:
	if (res == -ENOKEY)
		res = 0;
	memzero_explicit(crypt_info->ci_raw_key,
		sizeof(crypt_info->ci_raw_key));
	ext4_free_crypt_info(crypt_info);
	memzero_explicit(raw_key, sizeof(raw_key));
	return res;
}

Loading