From ea1f6226aea0bf666211ff152f100859f745c20e Mon Sep 17 00:00:00 2001 From: Gaurav Kashyap Date: Thu, 16 Apr 2020 11:10:20 -0700 Subject: [PATCH] soc: qcom: hwkm: fix minor issues 1. Fix key invalidate for double keys so that actual FBE keys can be removed when user is removed. 2. Don't use ICE slot for GP slot. 3. Handle KDF failures gracefully. Change-Id: I161b96d36206378735ba564430e1f413065ba255 Signed-off-by: Gaurav Kashyap --- drivers/soc/qcom/crypto-qti-hwkm.c | 106 ++++++++++++++++++----------- drivers/soc/qcom/hwkm.c | 2 - 2 files changed, 68 insertions(+), 40 deletions(-) diff --git a/drivers/soc/qcom/crypto-qti-hwkm.c b/drivers/soc/qcom/crypto-qti-hwkm.c index 0809b5b0e54b..c521ae81ea6b 100644 --- a/drivers/soc/qcom/crypto-qti-hwkm.c +++ b/drivers/soc/qcom/crypto-qti-hwkm.c @@ -15,9 +15,10 @@ #define TPKEY_SLOT_ICEMEM_SLAVE 0x92 #define KEYMANAGER_ICE_MAP_SLOT(slot) ((slot * 2) + 10) -#define GP_KEYSLOT 134 +#define GP_KEYSLOT 140 #define QTI_HWKM_INIT_DONE 0x1 +#define SLOT_EMPTY_ERROR 0x1000 union crypto_cfg { __le32 regval[2]; @@ -30,27 +31,25 @@ union crypto_cfg { }; }; -static int crypto_qti_hwkm_evict_slot(unsigned int slot) +static int crypto_qti_hwkm_evict_slot(unsigned int slot, bool double_key) { - int err = 0; struct hwkm_cmd cmd_clear; struct hwkm_rsp rsp_clear; memset(&cmd_clear, 0, sizeof(cmd_clear)); cmd_clear.op = KEY_SLOT_CLEAR; cmd_clear.clear.dks = slot; - err = qti_hwkm_handle_cmd(&cmd_clear, &rsp_clear); - if (err) - pr_err("%s: Error with key clear %d\n", __func__, err); - - return err; + if (double_key) + cmd_clear.clear.is_double_key = true; + return qti_hwkm_handle_cmd(&cmd_clear, &rsp_clear); } int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry, const struct blk_crypto_key *key, unsigned int slot, unsigned int data_unit_mask, int capid) { - int err = 0; + int err_program = 0; + int err_clear = 0; struct hwkm_cmd cmd_unwrap; struct hwkm_cmd cmd_kdf; struct hwkm_rsp rsp_unwrap; @@ -81,21 +80,38 @@ int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry, union crypto_cfg cfg; - err = qti_hwkm_clocks(true); - if (err) { - pr_err("%s: Error enabling clocks %d\n", __func__, err); - return err; + if ((key->size) <= RAW_SECRET_SIZE) { + pr_err("%s: Incorrect key size %d\n", __func__, key->size); + return -EINVAL; + } + + err_program = qti_hwkm_clocks(true); + if (err_program) { + pr_err("%s: Error enabling clocks %d\n", __func__, + err_program); + return err_program; } if ((ice_entry->flags & QTI_HWKM_INIT_DONE) != QTI_HWKM_INIT_DONE) { - err = qti_hwkm_init(); - if (err) { - pr_err("%s: Error with HWKM init %d\n", __func__, err); - return err; + err_program = qti_hwkm_init(); + if (err_program) { + pr_err("%s: Error with HWKM init %d\n", __func__, + err_program); + qti_hwkm_clocks(false); + return err_program; } ice_entry->flags |= QTI_HWKM_INIT_DONE; } + //Failsafe, clear GP_KEYSLOT incase it is not empty for any reason + err_clear = crypto_qti_hwkm_evict_slot(GP_KEYSLOT, true); + if (err_clear && (err_clear != SLOT_EMPTY_ERROR)) { + pr_err("%s: Error clearing ICE slot %d, err %d\n", + __func__, GP_KEYSLOT, err_clear); + qti_hwkm_clocks(false); + return err_clear; + } + /* Unwrap keyblob into a non ICE slot using TP key */ cmd_unwrap.op = KEY_UNWRAP_IMPORT; cmd_unwrap.unwrap.dks = GP_KEYSLOT; @@ -103,10 +119,22 @@ int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry, cmd_unwrap.unwrap.sz = (key->size) - RAW_SECRET_SIZE; memcpy(cmd_unwrap.unwrap.wkb, (key->raw) + RAW_SECRET_SIZE, cmd_unwrap.unwrap.sz); - err = qti_hwkm_handle_cmd(&cmd_unwrap, &rsp_unwrap); - if (err) { - pr_err("%s: Error with key unwrap %d\n", __func__, err); - return err; + err_program = qti_hwkm_handle_cmd(&cmd_unwrap, &rsp_unwrap); + if (err_program) { + pr_err("%s: Error with key unwrap %d\n", __func__, + err_program); + qti_hwkm_clocks(false); + return err_program; + } + + //Failsafe, clear ICE keyslot incase it is not empty for any reason + err_clear = crypto_qti_hwkm_evict_slot(KEYMANAGER_ICE_MAP_SLOT(slot), + true); + if (err_clear && (err_clear != SLOT_EMPTY_ERROR)) { + pr_err("%s: Error clearing ICE slot %d, err %d\n", + __func__, KEYMANAGER_ICE_MAP_SLOT(slot), err_clear); + qti_hwkm_clocks(false); + return err_clear; } /* Derive a 512-bit key which will be the key to encrypt/decrypt data */ @@ -128,19 +156,25 @@ int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry, /* Make sure CFGE is cleared */ wmb(); - err = qti_hwkm_handle_cmd(&cmd_kdf, &rsp_kdf); - if (err) { - pr_err("%s: Error programming key %d\n", __func__, err); - /* Clear slot if setting key fails */ - err = crypto_qti_hwkm_evict_slot( - KEYMANAGER_ICE_MAP_SLOT(slot)); - err = crypto_qti_hwkm_evict_slot(GP_KEYSLOT); - if (err) { - pr_err("%s: Error clearing slots %d\n", - __func__, err); + err_program = qti_hwkm_handle_cmd(&cmd_kdf, &rsp_kdf); + if (err_program) { + pr_err("%s: Error programming key %d\n", __func__, + err_program); + err_clear = crypto_qti_hwkm_evict_slot(GP_KEYSLOT, false); + if (err_clear) { + pr_err("%s: Error clearing slot %d err %d\n", + __func__, GP_KEYSLOT, err_clear); } qti_hwkm_clocks(false); - return err; + return err_program; + } + + err_clear = crypto_qti_hwkm_evict_slot(GP_KEYSLOT, false); + if (err_clear) { + pr_err("%s: Error unwrapped slot clear %d\n", __func__, + err_clear); + qti_hwkm_clocks(false); + return err_clear; } ice_writel(ice_entry, cfg.regval[0], (ICE_LUT_KEYS_CRYPTOCFG_R_16 + @@ -148,13 +182,9 @@ int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry, /* Make sure CFGE is enabled before moving forward */ wmb(); - err = crypto_qti_hwkm_evict_slot(GP_KEYSLOT); - if (err) - pr_err("%s: Error unwrapped slot clear %d\n", __func__, err); - qti_hwkm_clocks(false); - return err; + return err_program; } EXPORT_SYMBOL(crypto_qti_program_key); @@ -170,7 +200,7 @@ int crypto_qti_invalidate_key(struct crypto_vops_qti_entry *ice_entry, } /* Clear key from ICE keyslot */ - err = crypto_qti_hwkm_evict_slot(KEYMANAGER_ICE_MAP_SLOT(slot)); + err = crypto_qti_hwkm_evict_slot(KEYMANAGER_ICE_MAP_SLOT(slot), true); if (err) pr_err("%s: Error with key clear %d\n", __func__, err); diff --git a/drivers/soc/qcom/hwkm.c b/drivers/soc/qcom/hwkm.c index af19d185d1bd..7be30ef3834e 100644 --- a/drivers/soc/qcom/hwkm.c +++ b/drivers/soc/qcom/hwkm.c @@ -532,8 +532,6 @@ static int qti_handle_keyslot_clear(const struct hwkm_cmd *cmd_in, rsp_in->status = rsp[RESPONSE_ERR_IDX]; if (rsp_in->status) { - pr_err("%s: KEYSLOT_CLEAR error status 0x%x\n", - __func__, rsp_in->status); return rsp_in->status; }