diff options
author | Neeraj Soni <neersoni@codeaurora.org> | 2018-08-17 20:39:35 +0530 |
---|---|---|
committer | Anurudh Kumar Tiwari <aktiwari@codeaurora.org> | 2018-09-04 11:46:33 +0530 |
commit | cd6e78581acf722f022495bc50498a732fa64b24 (patch) | |
tree | 5630ad2a5b58cd46c4eae97f8e3e9b5965f54cba | |
parent | 5d14c24f62e91e034e28571cc9ea4df3099156d3 (diff) |
security: pfe: Set DUN size accroding to file system and storage typeLA.UM.7.8.r1-02800-SDM710.0
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>
-rw-r--r-- | include/crypto/ice.h | 12 | ||||
-rw-r--r-- | security/pfe/pfk.c | 20 | ||||
-rw-r--r-- | security/pfe/pfk_ext4.c | 17 | ||||
-rw-r--r-- | security/pfe/pfk_ext4.h | 4 | ||||
-rw-r--r-- | security/pfe/pfk_f2fs.c | 16 | ||||
-rw-r--r-- | security/pfe/pfk_f2fs.h | 4 | ||||
-rw-r--r-- | security/pfe/pfk_ice.c | 63 | ||||
-rw-r--r-- | security/pfe/pfk_ice.h | 2 | ||||
-rw-r--r-- | security/pfe/pfk_kc.c | 21 | ||||
-rw-r--r-- | security/pfe/pfk_kc.h | 3 |
10 files changed, 112 insertions, 50 deletions
diff --git a/include/crypto/ice.h b/include/crypto/ice.h index 133041ea9ec8..0b8f048f39cb 100644 --- a/include/crypto/ice.h +++ b/include/crypto/ice.h @@ -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); diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c index 8ad25cc0f3e2..0e153f2c8dd1 100644 --- a/security/pfe/pfk.c +++ b/security/pfe/pfk.c @@ -75,7 +75,9 @@ typedef int (*pfk_parse_inode_type)(const struct bio *bio, 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 @@ 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; + 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 @@ 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) { @@ -370,7 +376,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; @@ -380,7 +387,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", @@ -431,7 +439,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; diff --git a/security/pfe/pfk_ext4.c b/security/pfe/pfk_ext4.c index 0eb122565ecc..7000b666657b 100644 --- a/security/pfe/pfk_ext4.c +++ b/security/pfe/pfk_ext4.c @@ -141,7 +141,9 @@ int pfk_ext4_parse_inode(const struct bio *bio, 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 @@ int pfk_ext4_parse_inode(const struct bio *bio, */ *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 c33232f35a14..e39d04d82df5 100644 --- a/security/pfe/pfk_ext4.h +++ b/security/pfe/pfk_ext4.h @@ -24,7 +24,9 @@ int pfk_ext4_parse_inode(const struct bio *bio, 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 8b9d515043e8..2076267f0592 100644 --- a/security/pfe/pfk_f2fs.c +++ b/security/pfe/pfk_f2fs.c @@ -116,7 +116,9 @@ int pfk_f2fs_parse_inode(const struct bio *bio, 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 @@ int pfk_f2fs_parse_inode(const struct bio *bio, */ *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 551d529bced6..2e0c21d16ea6 100644 --- a/security/pfe/pfk_f2fs.h +++ b/security/pfe/pfk_f2fs.h @@ -24,7 +24,9 @@ int pfk_f2fs_parse_inode(const struct bio *bio, 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 a86042c98e1f..59c4adeaee47 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 + +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_key[ICE_KEY_SIZE]; -static uint8_t ice_salt[ICE_KEY_SIZE]; +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 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, return -EINVAL; } - if (!tzbuf_key || !tzbuf_salt) { + if (!tzbuf) { pr_err("%s No Memory\n", __func__); return -ENOMEM; } @@ -96,23 +93,21 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, 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 31772e798636..8fd0d83b3ae0 100644 --- a/security/pfe/pfk_ice.h +++ b/security/pfe/pfk_ice.h @@ -26,7 +26,7 @@ int pfk_ice_init(void); 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 eecc0260087d..a8e990926af3 100644 --- a/security/pfe/pfk_kc.c +++ b/security/pfe/pfk_kc.c @@ -132,6 +132,16 @@ static inline void kc_spin_unlock(void) } /** + * 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 @@ 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; @@ -478,7 +490,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; @@ -543,7 +555,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; diff --git a/security/pfe/pfk_kc.h b/security/pfe/pfk_kc.h index 6adeee2259cd..89d40be95fdf 100644 --- a/security/pfe/pfk_kc.h +++ b/security/pfe/pfk_kc.h @@ -19,7 +19,7 @@ int pfk_kc_init(void); 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_with_salt(const unsigned char *key, size_t key_size, 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; |