diff options
-rw-r--r-- | drivers/crypto/msm/ice.c | 42 | ||||
-rw-r--r-- | include/linux/pfk.h | 6 | ||||
-rw-r--r-- | security/pfe/pfk.c | 14 | ||||
-rw-r--r-- | security/pfe/pfk_kc.c | 24 | ||||
-rw-r--r-- | security/pfe/pfk_kc.h | 3 |
5 files changed, 86 insertions, 3 deletions
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index 2788c0add14a..a5e5ad34db16 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -24,6 +24,7 @@ #include <linux/pfk.h> #include <crypto/ice.h> #include <soc/qcom/scm.h> +#include <soc/qcom/qseecomi.h> #include "iceregs.h" #define TZ_SYSCALL_CREATE_SMC_ID(o, s, f) \ @@ -40,6 +41,13 @@ #define TZ_OS_KS_RESTORE_KEY_ID_PARAM_ID \ TZ_SYSCALL_CREATE_PARAM_ID_0 +#define TZ_OS_KS_RESTORE_KEY_CONFIG_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_KEYSTORE, 0x06) + +#define TZ_OS_KS_RESTORE_KEY_CONFIG_ID_PARAM_ID \ + TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL) + + #define ICE_REV(x, y) (((x) & ICE_CORE_##y##_REV_MASK) >> ICE_CORE_##y##_REV) #define QCOM_UFS_ICE_DEV "iceufs" #define QCOM_SDCC_ICE_DEV "icesdcc" @@ -830,6 +838,24 @@ static int qcom_ice_restore_config(void) return ret; } +static int qcom_ice_restore_key_config(void) +{ + struct scm_desc desc = {0}; + int ret = -1; + + /* For ice 3, key configuration needs to be restored in case of reset */ + + desc.arginfo = TZ_OS_KS_RESTORE_KEY_CONFIG_ID_PARAM_ID; + desc.args[0] = 10; /* UFS_ICE */ + + ret = scm_call2(TZ_OS_KS_RESTORE_KEY_CONFIG_ID, &desc); + + if (ret) + pr_err("%s: Error: 0x%x\n", __func__, ret); + + return ret; +} + static int qcom_ice_init_clocks(struct ice_device *ice) { int ret = -EINVAL; @@ -1103,6 +1129,22 @@ static int qcom_ice_finish_power_collapse(struct ice_device *ice_dev) err = -EFAULT; goto out; } + + /* + * ICE looses its key configuration when UFS is reset, + * restore it + */ + } else if (ICE_REV(ice_dev->ice_hw_version, MAJOR) > 2) { + err = qcom_ice_restore_key_config(); + if (err) + goto out; + + /* + * for PFE case, clear the cached ICE key table, + * this will force keys to be reconfigured + * per each next transaction + */ + pfk_clear_on_reset(); } } diff --git a/include/linux/pfk.h b/include/linux/pfk.h index 2fc64442b8ee..82ee74199752 100644 --- a/include/linux/pfk.h +++ b/include/linux/pfk.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 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 @@ -24,6 +24,7 @@ int pfk_load_key_start(const struct bio *bio, int pfk_load_key_end(const struct bio *bio, bool *is_pfe); int pfk_remove_key(const unsigned char *key, size_t key_size); bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2); +void pfk_clear_on_reset(void); #else static inline int pfk_load_key_start(const struct bio *bio, @@ -48,6 +49,9 @@ static inline bool pfk_allow_merge_bio(const struct bio *bio1, return true; } +static inline void pfk_clear_on_reset(void) +{} + #endif /* CONFIG_PFK */ #endif /* PFK_H */ diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c index 7e38c9fbf171..2e5aa2fb6688 100644 --- a/security/pfe/pfk.c +++ b/security/pfe/pfk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, 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 @@ -476,6 +476,18 @@ bool pfk_allow_merge_bio(const struct bio *bio1, const struct bio *bio2) return (*(pfk_allow_merge_bio_ftable[which_pfe1]))(bio1, bio2, inode1, inode2); } +/** + * Flush key table on storage core reset. During core reset key configuration + * is lost in ICE. We need to flash the cache, so that the keys will be + * reconfigured again for every subsequent transaction + */ +void pfk_clear_on_reset(void) +{ + if (!pfk_is_ready()) + return; + + pfk_kc_clear_on_reset(); +} module_init(pfk_init); module_exit(pfk_exit); diff --git a/security/pfe/pfk_kc.c b/security/pfe/pfk_kc.c index cd3f08b3959d..39e67569a1dd 100644 --- a/security/pfe/pfk_kc.c +++ b/security/pfe/pfk_kc.c @@ -826,3 +826,27 @@ out: return res; } + +/** + * pfk_kc_clear_on_reset() - clear the table and remove all keys from ICE + * The assumption is that at this point we don't have any pending transactions + * Also, there is no need to clear keys from ICE + * + * Return 0 on success, error otherwise + * + */ +void pfk_kc_clear_on_reset(void) +{ + struct kc_entry *entry = NULL; + int i = 0; + + if (!kc_is_ready()) + return; + + kc_spin_lock(); + for (i = 0; i < PFK_KC_TABLE_SIZE; i++) { + entry = kc_entry_at_index(i); + kc_clear_entry(entry); + } + kc_spin_unlock(); +} diff --git a/security/pfe/pfk_kc.h b/security/pfe/pfk_kc.h index ce3fac7edbbe..0b0ec8825c15 100644 --- a/security/pfe/pfk_kc.h +++ b/security/pfe/pfk_kc.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 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 @@ -26,6 +26,7 @@ int pfk_kc_remove_key_with_salt(const unsigned char *key, size_t key_size, const unsigned char *salt, size_t salt_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); |