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

Unverified Commit cf2d88c8 authored by derfelot's avatar derfelot
Browse files

eCryptfs: Add Sony encryption filter

Taken from Sony 47.2.A.10.107 stock kernel
parent fe85754e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -20,3 +20,10 @@ config ECRYPT_FS_MESSAGING
	  Enables the /dev/ecryptfs entry for use by ecryptfsd. This allows
	  for userspace to wrap/unwrap file encryption keys by other
	  backends, like OpenSSL.

config WTL_ENCRYPTION_FILTER
	bool "Enables filtering for some files not to encrypt on eCryptfs"
	default y
	depends on ECRYPT_FS
	help
	Modification of encrypted filesystem for SD card encryption
+12 −0
Original line number Diff line number Diff line
@@ -22,6 +22,11 @@
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include <linux/fs.h>
#include <linux/mount.h>
@@ -145,6 +150,13 @@ static int ecryptfs_crypto_api_algify_cipher_name(char **algified_name,
	int algified_name_len;
	int rc;

	if (!strncmp(cipher_name, "aes", sizeof("aes")) &&
	    (!strncmp(chaining_modifier, "cbc", sizeof("cbc")) ||
	     !strncmp(chaining_modifier, "xts", sizeof("xts")))) {
		cipher_name = "fipsaes";
		cipher_name_len = strnlen(cipher_name, sizeof("fipsaes"));
	}

	algified_name_len = (chaining_modifier_len + cipher_name_len + 3);
	(*algified_name) = kmalloc(algified_name_len, GFP_KERNEL);
	if (!(*algified_name)) {
+34 −0
Original line number Diff line number Diff line
@@ -24,6 +24,11 @@
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#ifndef ECRYPTFS_KERNEL_H
#define ECRYPTFS_KERNEL_H
@@ -40,6 +45,13 @@
#include <linux/ecryptfs.h>
#include <linux/crypto.h>

#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#define ENC_NAME_FILTER_MAX_INSTANCE 5
#define ENC_NAME_FILTER_MAX_LEN (256*5)
#define ENC_EXT_FILTER_MAX_INSTANCE 60
#define ENC_EXT_FILTER_MAX_LEN 16
#endif

#define ECRYPTFS_DEFAULT_IV_BYTES 16
#define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096
#define ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE 8192
@@ -234,6 +246,9 @@ struct ecryptfs_crypt_stat {
#define ECRYPTFS_ENCFN_USE_FEK        0x00001000
#define ECRYPTFS_UNLINK_SIGS          0x00002000
#define ECRYPTFS_I_SIZE_INITIALIZED   0x00004000
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#define ECRYPTFS_ENCRYPTED_OTHER_DEVICE 0x00008000
#endif
	u32 flags;
	unsigned int file_version;
	size_t iv_bytes;
@@ -345,6 +360,10 @@ struct ecryptfs_mount_crypt_stat {
#define ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK   0x00000020
#define ECRYPTFS_GLOBAL_ENCFN_USE_FEK          0x00000040
#define ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY    0x00000080
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#define ECRYPTFS_ENABLE_FILTERING              0x00000100
#define ECRYPTFS_ENABLE_NEW_PASSTHROUGH        0x00000200
#endif
	u32 flags;
	struct list_head global_auth_tok_list;
	struct mutex global_auth_tok_list_mutex;
@@ -357,6 +376,13 @@ struct ecryptfs_mount_crypt_stat {
	char global_default_fnek_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
	unsigned char global_default_cipher_mode[ECRYPTFS_MAX_CIPHER_NAME_SIZE
							 + 1];
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
	int max_name_filter_len;
	char enc_filter_name[ENC_NAME_FILTER_MAX_INSTANCE]
				[ENC_NAME_FILTER_MAX_LEN + 1];
	char enc_filter_ext[ENC_EXT_FILTER_MAX_INSTANCE]
				[ENC_EXT_FILTER_MAX_LEN + 1];
#endif
};

/* superblock private data. */
@@ -781,6 +807,14 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
		       loff_t offset);

#ifdef CONFIG_WTL_ENCRYPTION_FILTER
extern int is_file_name_match(struct ecryptfs_mount_crypt_stat *mcs,
			struct dentry *fp_dentry);

extern int is_file_ext_match(struct ecryptfs_mount_crypt_stat *mcs,
			char *str);
#endif

void clean_inode_pages(struct address_space *mapping,
		pgoff_t start, pgoff_t end);

+172 −0
Original line number Diff line number Diff line
@@ -22,6 +22,11 @@
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include <linux/file.h>
#include <linux/poll.h>
@@ -33,6 +38,12 @@
#include <linux/fs_stack.h>
#include <linux/ecryptfs.h>
#include "ecryptfs_kernel.h"
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
#include <linux/ctype.h>
#define ECRYPTFS_IOCTL_GET_ATTRIBUTES	_IOR('l', 0x10, __u32)
#define ECRYPTFS_WAS_ENCRYPTED 0x0080
#define ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE 0x0100
#endif

/**
 * ecryptfs_read_update_atime
@@ -138,6 +149,47 @@ static int read_or_initialize_metadata(struct dentry *dentry)
	crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
	mount_crypt_stat = &ecryptfs_superblock_to_private(
						inode->i_sb)->mount_crypt_stat;

#ifdef CONFIG_WTL_ENCRYPTION_FILTER
	if (crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED
		&& crypt_stat->flags & ECRYPTFS_POLICY_APPLIED
		&& crypt_stat->flags & ECRYPTFS_ENCRYPTED
		&& !(crypt_stat->flags & ECRYPTFS_KEY_VALID)
		&& !(crypt_stat->flags & ECRYPTFS_KEY_SET)
		&& crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED) {
		crypt_stat->flags |= ECRYPTFS_ENCRYPTED_OTHER_DEVICE;
	}
	mutex_lock(&crypt_stat->cs_mutex);
	if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_NEW_PASSTHROUGH)
			&& (crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
		if (ecryptfs_read_metadata(dentry)) {
			crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
					| ECRYPTFS_ENCRYPTED);
			rc = 0;
			goto out;
		}
	} else if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING)
			&& (crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
		struct dentry *fp_dentry =
			ecryptfs_inode_to_private(inode)->lower_file->f_path.dentry;
		char filename[NAME_MAX+1] = {0};
		if (fp_dentry->d_name.len <= NAME_MAX)
			memcpy(filename, fp_dentry->d_name.name,
					fp_dentry->d_name.len + 1);

		if (is_file_name_match(mount_crypt_stat, fp_dentry)
			|| is_file_ext_match(mount_crypt_stat, filename)) {
			if (ecryptfs_read_metadata(dentry))
				crypt_stat->flags &=
				~(ECRYPTFS_I_SIZE_INITIALIZED
				| ECRYPTFS_ENCRYPTED);
			rc = 0;
			goto out;
		}
	}
	mutex_unlock(&crypt_stat->cs_mutex);
#endif

	mutex_lock(&crypt_stat->cs_mutex);

	if (crypt_stat->flags & ECRYPTFS_POLICY_APPLIED &&
@@ -384,6 +436,45 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
	struct file *lower_file = ecryptfs_file_to_lower(file);
	long rc = -ENOTTY;

#ifdef CONFIG_WTL_ENCRYPTION_FILTER
	if (cmd == ECRYPTFS_IOCTL_GET_ATTRIBUTES) {
		u32 __user *user_attr = (u32 __user *)arg;
		u32 attr = 0;
		char filename[NAME_MAX+1] = {0};
		struct dentry *ecryptfs_dentry = file->f_path.dentry;
		struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
			&ecryptfs_superblock_to_private(ecryptfs_dentry->d_sb)
				->mount_crypt_stat;

		struct inode *inode = d_inode(ecryptfs_dentry);
		struct ecryptfs_crypt_stat *crypt_stat =
			&ecryptfs_inode_to_private(inode)->crypt_stat;
		struct dentry *fp_dentry =
			ecryptfs_inode_to_private(inode)->lower_file->f_path.dentry;
		if (fp_dentry->d_name.len <= NAME_MAX)
			memcpy(filename, fp_dentry->d_name.name,
					fp_dentry->d_name.len + 1);

		mutex_lock(&crypt_stat->cs_mutex);
		if ((crypt_stat->flags & ECRYPTFS_ENCRYPTED
			|| crypt_stat->flags & ECRYPTFS_ENCRYPTED_OTHER_DEVICE)
			|| ((mount_crypt_stat->flags
					& ECRYPTFS_ENABLE_FILTERING)
				&& (is_file_name_match
					(mount_crypt_stat, fp_dentry)
				|| is_file_ext_match
					(mount_crypt_stat, filename)))) {
			if (crypt_stat->flags & ECRYPTFS_KEY_VALID)
				attr = ECRYPTFS_WAS_ENCRYPTED;
			else
				attr = ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE;
		}
		mutex_unlock(&crypt_stat->cs_mutex);
		put_user(attr, user_attr);
		return 0;
	}
#endif

	if (!lower_file->f_op->unlocked_ioctl)
		return rc;

@@ -427,6 +518,87 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#endif

#ifdef CONFIG_WTL_ENCRYPTION_FILTER
int is_file_name_match(struct ecryptfs_mount_crypt_stat *mcs,
					struct dentry *fp_dentry)
{
	int i;
	char *str = NULL;
	if (!(strcmp("/", fp_dentry->d_name.name))
		|| !(strcmp("", fp_dentry->d_name.name)))
		return 0;
	str = kzalloc(mcs->max_name_filter_len + 1, GFP_KERNEL);
	if (!str) {
		printk(KERN_ERR "%s: Out of memory whilst attempting "
			       "to kzalloc [%d] bytes\n", __func__,
			       (mcs->max_name_filter_len + 1));
		return 0;
	}

	for (i = 0; i < ENC_NAME_FILTER_MAX_INSTANCE; i++) {
		int len = 0;
		struct dentry *p = fp_dentry;
		if (!strlen(mcs->enc_filter_name[i]))
			break;

		while (1) {
			if (len == 0) {
				len = strlen(p->d_name.name);
				if (len > mcs->max_name_filter_len)
					break;
				strcpy(str, p->d_name.name);
			} else {
				len = len + 1 + strlen(p->d_name.name) ;
				if (len > mcs->max_name_filter_len)
					break;
				strcat(str, "/");
				strcat(str, p->d_name.name);
			}

			if (strncasecmp(str, mcs->enc_filter_name[i], len))
				break;
			p = p->d_parent;

			if (!(strcmp("/", p->d_name.name))
				|| !(strcmp("", p->d_name.name))) {
				if (len == strlen(mcs->enc_filter_name[i])) {
					kfree(str);
					return 1;
				}
				break;
			}
		}
	}
	kfree(str);
	return 0;
}

int is_file_ext_match(struct ecryptfs_mount_crypt_stat *mcs, char *str)
{
	int i;
	char ext[NAME_MAX + 1] = {0};

	char *token;
	int count = 0;
	while ((token = strsep(&str, ".")) != NULL) {
		strncpy(ext, token, NAME_MAX);
		count++;
	}
	if (count <= 1)
		return 0;

	for (i = 0; i < ENC_EXT_FILTER_MAX_INSTANCE; i++) {
		if (!strlen(mcs->enc_filter_ext[i]))
			return 0;
		if (strlen(ext) != strlen(mcs->enc_filter_ext[i]))
			continue;
		if (!strncasecmp(ext, mcs->enc_filter_ext[i], strlen(ext)))
			return 1;
	}
	return 0;
}
#endif

const struct file_operations ecryptfs_dir_fops = {
	.iterate = ecryptfs_readdir,
	.read = generic_read_dir,
+39 −0
Original line number Diff line number Diff line
@@ -22,6 +22,11 @@
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
/*
 * NOTE: This file has been modified by Sony Mobile Communications Inc.
 * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc,
 * and licensed under the license of the file.
 */

#include <linux/file.h>
#include <linux/vmalloc.h>
@@ -243,10 +248,44 @@ int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
			ecryptfs_dentry, rc);
		goto out;
	}
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
	mutex_lock(&crypt_stat->cs_mutex);
	if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
		struct dentry *fp_dentry =
			ecryptfs_inode_to_private(ecryptfs_inode)
			->lower_file->f_path.dentry;
		struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
			&ecryptfs_superblock_to_private(ecryptfs_dentry->d_sb)
			->mount_crypt_stat;
		char filename[NAME_MAX+1] = {0};
		if (fp_dentry->d_name.len <= NAME_MAX)
			memcpy(filename, fp_dentry->d_name.name,
					fp_dentry->d_name.len + 1);

		if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_NEW_PASSTHROUGH)
		|| ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING) &&
			(is_file_name_match(mount_crypt_stat, fp_dentry) ||
			is_file_ext_match(mount_crypt_stat, filename)))) {
			crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
				| ECRYPTFS_ENCRYPTED);
			ecryptfs_put_lower_file(ecryptfs_inode);
		} else {
			rc = ecryptfs_write_metadata(ecryptfs_dentry,
				 ecryptfs_inode);
			if (rc)
				printk(
				KERN_ERR "Error writing headers; rc = [%d]\n"
				    , rc);
			ecryptfs_put_lower_file(ecryptfs_inode);
		}
	}
	mutex_unlock(&crypt_stat->cs_mutex);
#else
	rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);
	if (rc)
		printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
	ecryptfs_put_lower_file(ecryptfs_inode);
#endif
out:
	return rc;
}
Loading