security: pfe: Set DUN size accroding 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: If822863893fc0725a5ff0410e7418c352ad70fc1
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
diff --git a/include/crypto/ice.h b/include/crypto/ice.h
index 133041e..0b8f048 100644
--- a/include/crypto/ice.h
+++ b/include/crypto/ice.h
@@ -49,6 +49,18 @@
 	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);
diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c
index 8ad25cc..0e153f2 100644
--- a/security/pfe/pfk.c
+++ b/security/pfe/pfk.c
@@ -75,7 +75,9 @@
 	const struct inode *inode,
 	struct pfk_key_info *key_info,
 	enum ice_cryto_algo_mode *algo,
-	bool *is_pfe);
+	bool *is_pfe,
+	unsigned int *data_unit,
+	const char *storage_type);
 
 typedef bool (*pfk_allow_merge_bio_type)(const struct bio *bio1,
 	const struct bio *bio2, const struct inode *inode1,
@@ -281,21 +283,24 @@
 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;
+	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();
 
 	if (which_pfe != INVALID_PFE) {
 		/* Encrypted file; override ->bi_crypt_key */
 		pr_debug("parsing inode %lu with PFE type %d\n",
 			 inode->i_ino, which_pfe);
 		return (*(pfk_parse_inode_ftable[which_pfe]))
-				(bio, inode, key_info, algo_mode, is_pfe);
+				(bio, inode, key_info, algo_mode, is_pfe,
+					data_unit, (const char *)s_type);
 	}
 
 	/*
@@ -348,6 +353,7 @@
 	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) {
@@ -370,7 +376,8 @@
 		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;
@@ -380,7 +387,8 @@
 		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",
@@ -431,7 +439,7 @@
 	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;
 
diff --git a/security/pfe/pfk_ext4.c b/security/pfe/pfk_ext4.c
index 0eb1225..7000b66 100644
--- a/security/pfe/pfk_ext4.c
+++ b/security/pfe/pfk_ext4.c
@@ -141,7 +141,9 @@
 	const struct inode *inode,
 	struct pfk_key_info *key_info,
 	enum ice_cryto_algo_mode *algo,
-	bool *is_pfe)
+	bool *is_pfe,
+	unsigned int *data_unit,
+	const char *storage_type)
 {
 	int ret = 0;
 
@@ -155,6 +157,19 @@
 	 */
 	*is_pfe = true;
 
+	/* Update dun based upon storage type.
+	 * For ext4 FS UFS has 4k dun whereas eMMC
+	 * uses 512Byte dun.
+	 */
+	if (storage_type && data_unit) {
+		if (!memcmp(storage_type, "ufs", strlen("ufs")))
+			*data_unit = 1 << ICE_CRYPTO_DATA_UNIT_4_KB;
+		else if (!memcmp(storage_type, "sdcc", strlen("sdcc")))
+			*data_unit = 1 << ICE_CRYPTO_DATA_UNIT_512_B;
+		else
+			return -EINVAL;
+	}
+
 	if (!pfk_ext4_is_ready())
 		return -ENODEV;
 
diff --git a/security/pfe/pfk_ext4.h b/security/pfe/pfk_ext4.h
index c33232f..e39d04d 100644
--- a/security/pfe/pfk_ext4.h
+++ b/security/pfe/pfk_ext4.h
@@ -24,7 +24,9 @@
 	const struct inode *inode,
 	struct pfk_key_info *key_info,
 	enum ice_cryto_algo_mode *algo,
-	bool *is_pfe);
+	bool *is_pfe,
+	unsigned int *data_unit,
+	const char *storage_type);
 
 bool pfk_ext4_allow_merge_bio(const struct bio *bio1,
 	const struct bio *bio2, const struct inode *inode1,
diff --git a/security/pfe/pfk_f2fs.c b/security/pfe/pfk_f2fs.c
index 8b9d515..2076267 100644
--- a/security/pfe/pfk_f2fs.c
+++ b/security/pfe/pfk_f2fs.c
@@ -116,7 +116,9 @@
 		const struct inode *inode,
 		struct pfk_key_info *key_info,
 		enum ice_cryto_algo_mode *algo,
-		bool *is_pfe)
+		bool *is_pfe,
+		unsigned int *data_unit,
+		const char *storage_type)
 {
 	int ret = 0;
 
@@ -130,6 +132,18 @@
 	 */
 	*is_pfe = true;
 
+	/* Update the dun based upon storage type.
+	 * Right now both UFS and eMMC storage uses 4KB dun
+	 * for F2FS
+	 */
+	if (storage_type && data_unit) {
+		if (!memcmp(storage_type, "ufs", strlen("ufs")) ||
+			!memcmp(storage_type, "sdcc", strlen("sdcc")))
+			*data_unit = 1 << ICE_CRYPTO_DATA_UNIT_4_KB;
+		else
+			return -EINVAL;
+	}
+
 	if (!pfk_f2fs_is_ready())
 		return -ENODEV;
 
diff --git a/security/pfe/pfk_f2fs.h b/security/pfe/pfk_f2fs.h
index 551d529..2e0c21d 100644
--- a/security/pfe/pfk_f2fs.h
+++ b/security/pfe/pfk_f2fs.h
@@ -24,7 +24,9 @@
 		const struct inode *inode,
 		struct pfk_key_info *key_info,
 		enum ice_cryto_algo_mode *algo,
-		bool *is_pfe);
+		bool *is_pfe,
+		unsigned int *data_unit,
+		const char *storage_type);
 
 bool pfk_f2fs_allow_merge_bio(const struct bio *bio1,
 	const struct bio *bio2, const struct inode *inode1,
diff --git a/security/pfe/pfk_ice.c b/security/pfe/pfk_ice.c
index a86042c..59c4ade 100644
--- a/security/pfe/pfk_ice.c
+++ b/security/pfe/pfk_ice.c
@@ -26,11 +26,7 @@
 #include "pfk_ice.h"
 
 
-/**********************************/
-/** global definitions		 **/
-/**********************************/
-
-#define TZ_ES_SET_ICE_KEY 0x2
+#define TZ_ES_CONFIG_SET_ICE_KEY 0x4
 #define TZ_ES_INVALIDATE_ICE_KEY 0x3
 
 /* index 0 and 1 is reserved for FDE */
@@ -38,44 +34,45 @@
 
 #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 \
+#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_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+		TZ_SYSCALL_PARAM_TYPE_VAL, 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 ICE_KEY_SIZE 32
-#define ICE_SALT_SIZE 32
+#define ICE_BUFFER_SIZE 64
 
-static uint8_t ice_key[ICE_KEY_SIZE];
-static uint8_t ice_salt[ICE_KEY_SIZE];
+enum {
+	TZ_CIPHER_MODE_XTS_128 = 0,
+	TZ_CIPHER_MODE_CBC_128 = 1,
+	TZ_CIPHER_MODE_XTS_256 = 3,
+	TZ_CIPHER_MODE_CBC_256 = 4
+};
+
+static uint8_t ice_buffer[ICE_BUFFER_SIZE];
 
 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)
 {
 	struct scm_desc desc = {0};
 	int ret, ret1;
-	char *tzbuf_key = (char *)ice_key;
-	char *tzbuf_salt = (char *)ice_salt;
+	char *tzbuf = (char *)ice_buffer;
 	char *s_type = storage_type;
 
 	uint32_t smc_id = 0;
-	u32 tzbuflen_key = sizeof(ice_key);
-	u32 tzbuflen_salt = sizeof(ice_salt);
+	u32 size = ICE_BUFFER_SIZE / 2;
 
 	if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) {
 		pr_err("%s Invalid index %d\n", __func__, index);
@@ -86,7 +83,7 @@
 		return -EINVAL;
 	}
 
-	if (!tzbuf_key || !tzbuf_salt) {
+	if (!tzbuf) {
 		pr_err("%s No Memory\n", __func__);
 		return -ENOMEM;
 	}
@@ -96,23 +93,21 @@
 		return -EINVAL;
 	}
 
-	memset(tzbuf_key, 0, tzbuflen_key);
-	memset(tzbuf_salt, 0, tzbuflen_salt);
+	memset(tzbuf, 0, ICE_BUFFER_SIZE);
 
-	memcpy(ice_key, key, tzbuflen_key);
-	memcpy(ice_salt, salt, tzbuflen_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] = TZ_CIPHER_MODE_XTS_256;
+	desc.args[4] = data_unit;
 
 	ret = qcom_ice_setup_ice_hw((const char *)s_type, true);
 
diff --git a/security/pfe/pfk_ice.h b/security/pfe/pfk_ice.h
index 31772e7..8fd0d83 100644
--- a/security/pfe/pfk_ice.h
+++ b/security/pfe/pfk_ice.h
@@ -26,7 +26,7 @@
 int pfk_ice_deinit(void);
 
 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);
 
 
diff --git a/security/pfe/pfk_kc.c b/security/pfe/pfk_kc.c
index eecc026..a8e9909 100644
--- a/security/pfe/pfk_kc.c
+++ b/security/pfe/pfk_kc.c
@@ -132,6 +132,16 @@
 }
 
 /**
+ * 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
  *
  * Return true if it is , false otherwise or if invalid
@@ -389,13 +399,15 @@
  * @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 @@
 	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;
@@ -478,7 +490,7 @@
  */
 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;
@@ -543,7 +555,8 @@
 			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;
diff --git a/security/pfe/pfk_kc.h b/security/pfe/pfk_kc.h
index 6adeee2..89d40be 100644
--- a/security/pfe/pfk_kc.h
+++ b/security/pfe/pfk_kc.h
@@ -19,7 +19,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);
 void pfk_kc_load_key_end(const unsigned char *key, size_t key_size,
 		const unsigned char *salt, size_t salt_size);
 int pfk_kc_remove_key_with_salt(const unsigned char *key, size_t key_size,
@@ -27,6 +27,7 @@
 int pfk_kc_remove_key(const unsigned char *key, size_t key_size);
 int pfk_kc_clear(void);
 void pfk_kc_clear_on_reset(void);
+const char *pfk_kc_get_storage_type(void);
 extern char *saved_command_line;