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

Commit c35ee759 authored by Neeraj Soni's avatar Neeraj Soni Committed by Gerrit - the friendly Code Review server
Browse files

security: pfe: Set DUN size according to file system and storage type



EXT4 FS and F2FS has different way of setting Data Unit Number (DUN)
size value for UFS and eMMC storage devices. EXT4 FS uses sector number
while F2FS uses inode|pgidx. Check Storage and file system type
before setting the DUN value in Inline Crypto Engine (ICE).

Change-Id: I2de18ddd8908ce63b6d54b34b21d750d79f49cc2
Signed-off-by: default avatarNeeraj Soni <neersoni@codeaurora.org>
Signed-off-by: default avatarShivaprasad Hongal <shongal@codeaurora.org>
parent defdcf8d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -49,6 +49,18 @@ struct ice_data_setting {
	bool				encr_bypass;
};

/* MSM ICE Crypto Data Unit of target DUN of Transfer Request */
enum ice_crypto_data_unit {
	ICE_CRYPTO_DATA_UNIT_512_B          = 0,
	ICE_CRYPTO_DATA_UNIT_1_KB           = 1,
	ICE_CRYPTO_DATA_UNIT_2_KB           = 2,
	ICE_CRYPTO_DATA_UNIT_4_KB           = 3,
	ICE_CRYPTO_DATA_UNIT_8_KB           = 4,
	ICE_CRYPTO_DATA_UNIT_16_KB          = 5,
	ICE_CRYPTO_DATA_UNIT_32_KB          = 6,
	ICE_CRYPTO_DATA_UNIT_64_KB          = 7,
};

typedef void (*ice_error_cb)(void *, u32 error);

struct qcom_ice_variant_ops *qcom_ice_get_variant_ops(struct device_node *node);
+22 −4
Original line number Diff line number Diff line
@@ -280,14 +280,29 @@ bool pfe_is_inode_filesystem_type(const struct inode *inode,
static int pfk_get_key_for_bio(const struct bio *bio,
		struct pfk_key_info *key_info,
		enum ice_cryto_algo_mode *algo_mode,
		bool *is_pfe)
		bool *is_pfe, unsigned int *data_unit)
{
	const struct inode *inode;
	enum pfe_type which_pfe;
	const struct blk_encryption_key *key = NULL;
	char *s_type = NULL;

	inode = pfk_bio_get_inode(bio);
	which_pfe = pfk_get_pfe_type(inode);
	s_type = (char *)pfk_kc_get_storage_type();

	/*
	 * Update dun based on storage type.
	 * 512 byte dun - For ext4 emmc
	 * 4K dun - For ext4 ufs, f2fs ufs and f2fs emmc
	 */

	if (data_unit) {
		if (!bio_dun(bio) && !memcmp(s_type, "sdcc", strlen("sdcc")))
			*data_unit = 1 << ICE_CRYPTO_DATA_UNIT_512_B;
		else
			*data_unit = 1 << ICE_CRYPTO_DATA_UNIT_4_KB;
	}

	if (which_pfe != INVALID_PFE) {
		/* Encrypted file; override ->bi_crypt_key */
@@ -349,6 +364,7 @@ int pfk_load_key_start(const struct bio *bio,
	struct pfk_key_info key_info = {NULL, NULL, 0, 0};
	enum ice_cryto_algo_mode algo_mode = ICE_CRYPTO_ALGO_MODE_AES_XTS;
	enum ice_crpto_key_size key_size_type = 0;
	unsigned int data_unit = 1 << ICE_CRYPTO_DATA_UNIT_512_B;
	u32 key_index = 0;

	if (!is_pfe) {
@@ -371,7 +387,8 @@ int pfk_load_key_start(const struct bio *bio,
		return -EINVAL;
	}

	ret = pfk_get_key_for_bio(bio, &key_info, &algo_mode, is_pfe);
	ret = pfk_get_key_for_bio(bio, &key_info, &algo_mode, is_pfe,
					&data_unit);

	if (ret != 0)
		return ret;
@@ -381,7 +398,8 @@ int pfk_load_key_start(const struct bio *bio,
		return ret;

	ret = pfk_kc_load_key_start(key_info.key, key_info.key_size,
			key_info.salt, key_info.salt_size, &key_index, async);
			key_info.salt, key_info.salt_size, &key_index, async,
			data_unit);
	if (ret) {
		if (ret != -EBUSY && ret != -EAGAIN)
			pr_err("start: could not load key into pfk key cache, error %d\n",
@@ -432,7 +450,7 @@ int pfk_load_key_end(const struct bio *bio, bool *is_pfe)
	if (!pfk_is_ready())
		return -ENODEV;

	ret = pfk_get_key_for_bio(bio, &key_info, NULL, is_pfe);
	ret = pfk_get_key_for_bio(bio, &key_info, NULL, is_pfe, NULL);
	if (ret != 0)
		return ret;

+49 −45
Original line number Diff line number Diff line
@@ -30,31 +30,32 @@
/** global definitions		 **/
/**********************************/

#define TZ_ES_SET_ICE_KEY 0x2
#define TZ_ES_INVALIDATE_ICE_KEY 0x3
#define TZ_ES_CONFIG_SET_ICE_KEY 0x4

/* index 0 and 1 is reserved for FDE */
#define MIN_ICE_KEY_INDEX 2

#define MAX_ICE_KEY_INDEX 31

#define TZ_ES_SET_ICE_KEY_ID \
	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_ES, TZ_ES_SET_ICE_KEY)
#define TZ_ES_CONFIG_SET_ICE_KEY_ID \
	TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_ES, \
	TZ_ES_CONFIG_SET_ICE_KEY)

#define TZ_ES_INVALIDATE_ICE_KEY_ID \
		TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, \
			TZ_SVC_ES, TZ_ES_INVALIDATE_ICE_KEY)

#define TZ_ES_SET_ICE_KEY_PARAM_ID \
	TZ_SYSCALL_CREATE_PARAM_ID_5( \
		TZ_SYSCALL_PARAM_TYPE_VAL, \
		TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL, \
		TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)

#define TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID \
	TZ_SYSCALL_CREATE_PARAM_ID_1( \
	TZ_SYSCALL_PARAM_TYPE_VAL)

#define TZ_ES_CONFIG_SET_ICE_KEY_PARAM_ID \
	TZ_SYSCALL_CREATE_PARAM_ID_5( \
	TZ_SYSCALL_PARAM_TYPE_VAL, \
	TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL, \
	TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL)

#define CONTEXT_SIZE 0x1000

#define KEYMASTER_UTILS_CMD_ID 0x200UL
@@ -64,18 +65,22 @@

#define USE_KM_MAJOR_VERSION 4
#define USE_KM_MINOR_VERSION 513

#define ICE_KEY_SIZE 32
#define ICE_SALT_SIZE 32
#define ICE_BUFFER_SIZE 64

static uint32_t keymaster_minor_version;
static uint32_t keymaster_major_version;

static uint8_t ice_key[ICE_KEY_SIZE];
static uint8_t ice_salt[ICE_KEY_SIZE];
static uint8_t ice_buffer[ICE_BUFFER_SIZE];

static struct qseecom_handle *qhandle;

enum {
	ICE_CIPHER_MODE_XTS_128 = 0,
	ICE_CIPHER_MODE_CBC_128 = 1,
	ICE_CIPHER_MODE_XTS_256 = 3,
	ICE_CIPHER_MODE_CBC_256 = 4
};

static uint32_t get_keymaster_version(struct qseecom_handle *qhandle)
{
	int ret = 0;
@@ -144,24 +149,26 @@ static int set_wrapped_key(uint32_t index, const uint8_t *key,
	int ret = 0;
	u32 set_req_len = 0;
	u32 set_rsp_len = 0;
	u32 size = ICE_BUFFER_SIZE / 2;
	struct pfk_ice_key_req *set_req_buf;
	struct pfk_ice_key_rsp *set_rsp_buf;

	memcpy(ice_key, key, sizeof(ice_key));
	memcpy(ice_salt, salt, sizeof(ice_salt));
	memcpy(ice_buffer, key, size);
	memcpy(ice_buffer + size, salt, size);

	set_req_buf = (struct pfk_ice_key_req *) qhandle->sbuf;
	set_req_buf->cmd_id = KEYMASTER_SET_ICE_KEY;
	set_req_buf->index = index;
	set_req_buf->ice_key_offset = sizeof(struct pfk_ice_key_req);
	set_req_buf->ice_key_size = ICE_KEY_SIZE;
	set_req_buf->ice_key_size = size;
	set_req_buf->ice_salt_offset = set_req_buf->ice_key_offset +
					set_req_buf->ice_key_size;
	set_req_buf->ice_salt_size = ICE_SALT_SIZE;
	set_req_buf->ice_salt_size = size;

	memcpy((uint8_t *) set_req_buf + set_req_buf->ice_key_offset, ice_key,
				set_req_buf->ice_key_size);
	memcpy((uint8_t *) set_req_buf + set_req_buf->ice_salt_offset, ice_salt,
	memcpy((uint8_t *) set_req_buf + set_req_buf->ice_key_offset,
			ice_buffer, set_req_buf->ice_key_size);
	memcpy((uint8_t *) set_req_buf + set_req_buf->ice_salt_offset,
			ice_buffer + set_req_buf->ice_key_size,
			set_req_buf->ice_salt_size);

	set_req_len = sizeof(struct pfk_ice_key_req) + set_req_buf->ice_key_size
@@ -209,38 +216,35 @@ static int clear_wrapped_key(uint32_t index)
	return ret;
}

static int set_key(uint32_t index, const uint8_t *key, const uint8_t *salt)
static int set_key(uint32_t index, const uint8_t *key, const uint8_t *salt,
		unsigned int data_unit)
{
	struct scm_desc desc = {0};
	int ret = 0;
	uint32_t smc_id = 0;
	char *tzbuf_key = (char *)ice_key;
	char *tzbuf_salt = (char *)ice_salt;
	u32 tzbuflen_key = sizeof(ice_key);
	u32 tzbuflen_salt = sizeof(ice_salt);
	char *tzbuf = (char *)ice_buffer;
	uint32_t size = ICE_BUFFER_SIZE / 2;

	if (!tzbuf_key || !tzbuf_salt) {
	if (!tzbuf) {
		pr_err("%s No Memory\n", __func__);
		return -ENOMEM;
	}

	memset(tzbuf_key, 0, tzbuflen_key);
	memset(tzbuf_salt, 0, tzbuflen_salt);
	memset(tzbuf, 0, ICE_BUFFER_SIZE);

	memcpy(ice_key, key, sizeof(ice_key));
	memcpy(ice_salt, salt, sizeof(ice_salt));
	memcpy(ice_buffer, key, size);
	memcpy(ice_buffer+size, salt, size);

	dmac_flush_range(tzbuf_key, tzbuf_key + tzbuflen_key);
	dmac_flush_range(tzbuf_salt, tzbuf_salt + tzbuflen_salt);
	dmac_flush_range(tzbuf, tzbuf + ICE_BUFFER_SIZE);

	smc_id = TZ_ES_SET_ICE_KEY_ID;
	smc_id = TZ_ES_CONFIG_SET_ICE_KEY_ID;

	desc.arginfo = TZ_ES_SET_ICE_KEY_PARAM_ID;
	desc.arginfo = TZ_ES_CONFIG_SET_ICE_KEY_PARAM_ID;
	desc.args[0] = index;
	desc.args[1] = virt_to_phys(tzbuf_key);
	desc.args[2] = tzbuflen_key;
	desc.args[3] = virt_to_phys(tzbuf_salt);
	desc.args[4] = tzbuflen_salt;
	desc.args[1] = virt_to_phys(tzbuf);
	desc.args[2] = ICE_BUFFER_SIZE;
	desc.args[3] = ICE_CIPHER_MODE_XTS_256;
	desc.args[4] = data_unit;

	ret = scm_call2(smc_id, &desc);
	if (ret)
@@ -267,7 +271,7 @@ static int clear_key(uint32_t index)
}

int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt,
			char *storage_type)
			char *storage_type, unsigned int data_unit)
{
	int ret = 0, ret1 = 0;
	char *s_type = storage_type;
@@ -292,12 +296,12 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt,
		goto out;
	}

	if (pfk_wrapped_key_supported() && should_use_keymaster()) {
	if (should_use_keymaster()) {
		pr_debug("%s: Setting wrapped key\n", __func__);
		ret = set_wrapped_key(index, key, salt);
	} else {
		pr_debug("%s: Setting keys with QSEE kernel\n", __func__);
		ret = set_key(index, key, salt);
		ret = set_key(index, key, salt, data_unit);
	}

	if (ret) {
@@ -308,7 +312,7 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt,
				goto out;
		}
		/* Try to invalidate the key to keep ICE in proper state */
		if (pfk_wrapped_key_supported() && should_use_keymaster())
		if (should_use_keymaster())
			ret1 = clear_wrapped_key(index);
		else
			ret1 = clear_key(index);
@@ -345,7 +349,7 @@ int qti_pfk_ice_invalidate_key(uint32_t index, char *storage_type)
		return ret;
	}

	if (pfk_wrapped_key_supported() && should_use_keymaster()) {
	if (should_use_keymaster()) {
		ret = clear_wrapped_key(index);
		pr_debug("%s: Clearing wrapped key\n", __func__);
	} else {
+1 −13
Original line number Diff line number Diff line
@@ -51,20 +51,8 @@ struct pfk_km_get_version_rsp {
int pfk_ice_init(void);
int pfk_ice_deinit(void);

#ifdef CONFIG_PFK_WRAPPED_KEY_SUPPORTED
static inline bool pfk_wrapped_key_supported(void)
{
	return true;
}
#else
static inline bool pfk_wrapped_key_supported(void)
{
	return false;
}
#endif

int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt,
			char *storage_type);
			char *storage_type, unsigned int data_unit);
int qti_pfk_ice_invalidate_key(uint32_t index, char *storage_type);

#endif /* PFK_ICE_H_ */
+17 −4
Original line number Diff line number Diff line
@@ -131,6 +131,16 @@ static inline void kc_spin_unlock(void)
	spin_unlock_irqrestore(&kc_lock, flags);
}

/**
 * pfk_kc_get_storage_type() - return the hardware storage type.
 *
 * Return: storage type queried during bootup.
 */
const char *pfk_kc_get_storage_type(void)
{
	return s_type;
}

/**
 * kc_entry_is_available() - checks whether the entry is available
 *
@@ -389,13 +399,15 @@ static void kc_clear_entry(struct kc_entry *entry)
 * @key_size: key_size
 * @salt: salt
 * @salt_size: salt_size
 * @data_unit: dun size
 *
 * The previous key is securely released and wiped, the new one is loaded
 * to ICE.
 * Should be invoked under spinlock
 */
static int kc_update_entry(struct kc_entry *entry, const unsigned char *key,
	size_t key_size, const unsigned char *salt, size_t salt_size)
	size_t key_size, const unsigned char *salt, size_t salt_size,
	unsigned int data_unit)
{
	int ret;

@@ -412,7 +424,7 @@ static int kc_update_entry(struct kc_entry *entry, const unsigned char *key,
	kc_spin_unlock();

	ret = qti_pfk_ice_set_key(entry->key_index, entry->key,
			entry->salt, s_type);
			entry->salt, s_type, data_unit);

	kc_spin_lock();
	return ret;
@@ -479,7 +491,7 @@ int pfk_kc_deinit(void)
 */
int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
		const unsigned char *salt, size_t salt_size, u32 *key_index,
		bool async)
		bool async, unsigned int data_unit)
{
	int ret = 0;
	struct kc_entry *entry = NULL;
@@ -544,7 +556,8 @@ int pfk_kc_load_key_start(const unsigned char *key, size_t key_size,
			break;
		}
	case (FREE):
		ret = kc_update_entry(entry, key, key_size, salt, salt_size);
		ret = kc_update_entry(entry, key, key_size, salt, salt_size,
					data_unit);
		if (ret) {
			entry->state = SCM_ERROR;
			entry->scm_error = ret;
Loading