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

Commit 2b190ecb authored by Andrey Markovytch's avatar Andrey Markovytch
Browse files

PFK: new module to work with ecryptfs



PFK is a new module that accompanies eCryptfs and
enables it to utilize ICE hw encryption engine. Module
is responsible for storing encryption/decryption keys
inside eCryptfs inodes for each file and loading them
to ICE

Change-Id: I6e755ca657164919147fe0d9482477e14a4be5eb
Signed-off-by: default avatarAndrey Markovytch <andreym@codeaurora.org>
parent 97da78b1
Loading
Loading
Loading
Loading
+79 −27
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/cdev.h>
#include <linux/regulator/consumer.h>
#include <linux/msm-bus.h>
#include <linux/pfk.h>
#include <crypto/ice.h>
#include <soc/qcom/scm.h>
#include "iceregs.h"
@@ -100,6 +101,51 @@ struct ice_device {
	struct qcom_ice_bus_vote bus_vote;
};

static int qti_ice_setting_config(struct request *req,
		struct platform_device *pdev,
		struct ice_crypto_setting *crypto_data,
		struct ice_data_setting *setting,
		bool *configured)
{
	struct ice_device *ice_dev = NULL;

	*configured = false;
	ice_dev = platform_get_drvdata(pdev);

	if (!ice_dev) {
		pr_debug("%s no ICE device\n", __func__);

		/* make the caller finish peacfully */
		*configured = true;
		return 0;
	}

	if (ice_dev->is_ice_disable_fuse_blown) {
		pr_err("%s ICE disabled fuse is blown\n", __func__);
		return -ENODEV;
	}

	if ((short)(crypto_data->key_index) >= 0) {

		*configured = true;

		memcpy(&setting->crypto_data, crypto_data,
				sizeof(setting->crypto_data));

		if (rq_data_dir(req) == WRITE)
			setting->encr_bypass = false;
		else if (rq_data_dir(req) == READ)
			setting->decr_bypass = false;
		else {
			/* Should I say BUG_ON */
			setting->encr_bypass = true;
			setting->decr_bypass = true;
		}
	}

	return 0;
}

static int qcom_ice_enable_clocks(struct ice_device *, bool);

static int qcom_ice_set_bus_vote(struct ice_device *ice_dev, int vote)
@@ -1116,8 +1162,10 @@ static int qcom_ice_config(struct platform_device *pdev, struct request *req,
		struct ice_data_setting *setting)
{
	struct ice_crypto_setting *crypto_data;
	struct ice_device *ice_dev;
	struct ice_crypto_setting pfk_crypto_data = {0};
	union map_info *info;
	int ret = 0;
	bool configured = 0;

	if (!pdev || !req || !setting) {
		pr_err("%s: Invalid params passed\n", __func__);
@@ -1139,6 +1187,27 @@ static int qcom_ice_config(struct platform_device *pdev, struct request *req,
		return 0;
	}

	ret = pfk_load_key(req->bio, &pfk_crypto_data);
	if (0 == ret) {
		ret = qti_ice_setting_config(req, pdev, &pfk_crypto_data,
			setting, &configured);

		if (0 == ret) {
			/**
			 * if configuration was complete, we are done, no need
			 * to go further with FDE
			 */
			if (configured)
				return 0;
		} else {
			/**
			 * there was an error with configuring the setting,
			 * exit with error
			 */
			return ret;
		}
	}

	/*
	 * info field in req->end_io_data could be used by mulitple dm or
	 * non-dm entities. To ensure that we are running operation on dm
@@ -1147,37 +1216,20 @@ static int qcom_ice_config(struct platform_device *pdev, struct request *req,
	if (bio_flagged(req->bio, BIO_INLINECRYPT)) {
		info = dm_get_rq_mapinfo(req);
		if (!info) {
			pr_err("%s info not available in request\n", __func__);
			pr_debug("%s info not available in request\n",
				 __func__);
			return 0;
		}

		ice_dev = platform_get_drvdata(pdev);

		crypto_data = (struct ice_crypto_setting *)info->ptr;

		if (!ice_dev)
			return 0;

		if (ice_dev->is_ice_disable_fuse_blown) {
			pr_err("%s ICE disabled fuse is blown\n", __func__);
			return -ENODEV;
		if (!crypto_data) {
			pr_err("%s crypto_data not available in request\n",
				 __func__);
			return -EINVAL;
		}

		if (crypto_data->key_index >= 0) {

			memcpy(&setting->crypto_data, crypto_data,
					sizeof(struct ice_crypto_setting));

			if (rq_data_dir(req) == WRITE)
				setting->encr_bypass = false;
			else if (rq_data_dir(req) == READ)
				setting->decr_bypass = false;
			else {
				/* Should I say BUG_ON */
				setting->encr_bypass = true;
				setting->decr_bypass = true;
			}
		}
		return qti_ice_setting_config(req, pdev, crypto_data,
			setting, &configured);
	}

	/*

include/linux/pfk.h

0 → 100644
+50 −0
Original line number Diff line number Diff line
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef PFK_H_
#define PFK_H_

#include <linux/bio.h>

struct ice_crypto_setting;

#ifdef CONFIG_PFK

int pfk_load_key(const struct bio *bio, struct ice_crypto_setting *ice_setting);
int pfk_remove_key(const unsigned char *key, size_t key_size);
bool pfk_allow_merge_bio(struct bio *bio1, struct bio *bio2);

#else
static inline int pfk_load_key(const struct bio *bio,
		struct ice_crypto_setting *ice_setting)
{
	return -ENODEV;
}

static inline int pfk_remove_key(const unsigned char *key, size_t key_size)
{
	return -ENODEV;
}

static inline bool pfk_allow_merge_bio(const struct bio *bio1,
		const struct bio *bio2)
{
	return true;
}

static inline void pfk_remove_all_keys(void)
{
}

#endif /* CONFIG_PFK */

#endif /* PFK_H */
+5 −0
Original line number Diff line number Diff line
@@ -6,6 +6,11 @@ menu "Security options"

source security/keys/Kconfig

if ARCH_MSM
source security/pfe/Kconfig
endif


config SECURITY_DMESG_RESTRICT
	bool "Restrict unprivileged access to the kernel syslog"
	default n
+3 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack
subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
subdir-$(CONFIG_SECURITY_APPARMOR)	+= apparmor
subdir-$(CONFIG_SECURITY_YAMA)		+= yama
subdir-$(CONFIG_ARCH_MSM)		+= pfe

# always enable default capabilities
obj-y					+= commoncap.o
@@ -19,9 +20,11 @@ obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/
obj-$(CONFIG_SECURITY_SMACK)		+= smack/
obj-$(CONFIG_AUDIT)			+= lsm_audit.o

obj-$(CONFIG_SECURITY_TOMOYO)		+= tomoyo/
obj-$(CONFIG_SECURITY_APPARMOR)		+= apparmor/
obj-$(CONFIG_SECURITY_YAMA)		+= yama/
obj-$(CONFIG_ARCH_MSM)		        += pfe/
obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o

# Object integrity file lists

security/pfe/Kconfig

0 → 100644
+17 −0
Original line number Diff line number Diff line
menu "Qualcomm Technologies, Inc Per File Encryption security device drivers"
	depends on ARCH_MSM

config PFK
	bool "Per-File-Key driver"
	depends on SECURITY
	depends on ECRYPT_FS
	default n
	help
		This driver is used for storing eCryptfs information
		in file node.
		This is part of eCryptfs hardware enhanced solution
		provided by Qualcomm Technologies, Inc.
		Information is used when file is encrypted later using
		ICE or dm crypto engine

endmenu
Loading