From 6417c908ccc1e404e93d61c46023b669805bac46 Mon Sep 17 00:00:00 2001 From: Boojin Kim Date: Fri, 16 Mar 2018 09:26:50 +0900 Subject: [PATCH] [COMMON] fmp: update multi-host for fmp Change-Id: Ib2bd3264d07eb6dabb874a5062a16a3d7a2b7d10 Signed-off-by: Boojin Kim --- drivers/crypto/fmp/Kconfig | 1 + drivers/crypto/fmp/fmp.c | 27 ++- drivers/crypto/fmp/fmp_fips_cipher.c | 4 +- drivers/crypto/fmp/fmp_fips_integrity.c | 5 + drivers/crypto/fmp/fmp_fips_main.c | 6 +- drivers/crypto/fmp/fmp_test.c | 12 +- drivers/crypto/fmp/smu.c | 228 ++---------------------- include/crypto/fmp.h | 7 +- include/crypto/smu.h | 34 +--- 9 files changed, 61 insertions(+), 263 deletions(-) diff --git a/drivers/crypto/fmp/Kconfig b/drivers/crypto/fmp/Kconfig index 4215d52fd6c7..74046b6b9c53 100644 --- a/drivers/crypto/fmp/Kconfig +++ b/drivers/crypto/fmp/Kconfig @@ -14,6 +14,7 @@ config EXYNOS_SMU config EXYNOS_FMP tristate "Samsung EXYNOS FMP driver" depends on CRYPTO_DISKCIPHER + select EXYNOS_SMU help Say yes here to build support for FMP (Flash Memory Protector) to encrypt and decrypt userdata using inline H/W crypto module. diff --git a/drivers/crypto/fmp/fmp.c b/drivers/crypto/fmp/fmp.c index 2dd14999c315..706c4bffc21c 100644 --- a/drivers/crypto/fmp/fmp.c +++ b/drivers/crypto/fmp/fmp.c @@ -41,9 +41,9 @@ static inline void dump_ci(struct fmp_crypto_info *c) { if (c) { - pr_info("%s: crypto:%p algo:%d enc:%d key_size:%d key:%p\n", - __func__, c, c->algo_mode, c->enc_mode, - c->key_size, c->key); + pr_info + ("dump_ci: crypto:%p algo:%d enc:%d key_size:%d key:%p\n", + c, c->algo_mode, c->enc_mode, c->key_size, c->key); if (c->enc_mode == EXYNOS_FMP_FILE_ENC) print_hex_dump(KERN_CONT, "key:", DUMP_PREFIX_OFFSET, 16, 1, c->key, @@ -220,6 +220,7 @@ static int fmplib_set_disk_key(struct exynos_fmp *fmp, u8 *key, u32 key_size) { int ret; + /* TODO: only set for host0 */ __flush_dcache_area(key, (size_t) FMP_MAX_KEY_SIZE); ret = exynos_smc(SMC_CMD_FMP_DISK_KEY_STORED, 0, virt_to_phys(key), @@ -432,7 +433,7 @@ int exynos_fmp_clear(struct fmp_crypto_info *ci, void *priv) return 0; } -int exynos_fmp_setkey(struct fmp_crypto_info *ci, char *in_key, u32 keylen, +int exynos_fmp_setkey(struct fmp_crypto_info *ci, u8 *in_key, u32 keylen, bool persistent) { struct exynos_fmp *fmp = ci->ctx; @@ -547,6 +548,24 @@ err: } #endif +#define CFG_DESCTYPE_3 0x3 +int exynos_fmp_sec_config(int id) +{ + int ret; + + if (id) { + pr_err("%s: fails to set set config for %d. only host0\n", + __func__, id); + return 0; + } + + ret = exynos_smc(SMC_CMD_FMP_SECURITY, 0, id, CFG_DESCTYPE_3); + if (ret) + pr_err("%s: Fail smc call for FMP_SECURITY. ret(%d)\n", + __func__, ret); + return ret; +} + void *exynos_fmp_init(struct platform_device *pdev) { int ret = 0; diff --git a/drivers/crypto/fmp/fmp_fips_cipher.c b/drivers/crypto/fmp/fmp_fips_cipher.c index 21d5b42cfea3..62fc403910f8 100644 --- a/drivers/crypto/fmp/fmp_fips_cipher.c +++ b/drivers/crypto/fmp/fmp_fips_cipher.c @@ -73,8 +73,10 @@ int fmp_cipher_set_iv(struct fmp_test_data *fdata, int ret = 0; struct fmp_crypto_info *ci; - if (!fdata) + if (!fdata) { + pr_err("%s: Invalid fdata\n", __func__); return -EINVAL; + } ci = &fdata->ci; if (iv_len != FMP_IV_SIZE_16) { diff --git a/drivers/crypto/fmp/fmp_fips_integrity.c b/drivers/crypto/fmp/fmp_fips_integrity.c index 5907022e0aaf..9840f4378ade 100644 --- a/drivers/crypto/fmp/fmp_fips_integrity.c +++ b/drivers/crypto/fmp/fmp_fips_integrity.c @@ -29,6 +29,7 @@ #include "fmp_fips_info.h" #include "fmp_fips_integrity.h" +#undef FIPS_CHECK_INTEGRITY #undef FIPS_DEBUG_INTEGRITY /* Same as build time */ @@ -63,6 +64,10 @@ int do_fmp_integrity_check(struct exynos_fmp *fmp) #endif struct exynos_fmp_fips_test_vops *test_vops; +#ifndef FIPS_CHECK_INTEGRITY + return 0; +#endif + if (!fmp || !fmp->dev) { pr_err("%s: invalid fmp device\n", __func__); return -EINVAL; diff --git a/drivers/crypto/fmp/fmp_fips_main.c b/drivers/crypto/fmp/fmp_fips_main.c index 6ccad737956e..5cfd4ddf2066 100644 --- a/drivers/crypto/fmp/fmp_fips_main.c +++ b/drivers/crypto/fmp/fmp_fips_main.c @@ -176,8 +176,6 @@ int exynos_fmp_fips_init(struct exynos_fmp *fmp) dev_info(fmp->dev, "%s: self-tests for FMP passed\n", __func__); } - /* TODO: Add integrity check */ -#ifdef CHECK_INTEGRITY ret = do_fmp_integrity_check(fmp); if (ret) { dev_err(fmp->dev, "%s: integrity check for FMP failed\n", __func__); @@ -187,9 +185,7 @@ int exynos_fmp_fips_init(struct exynos_fmp *fmp) dev_info(fmp->dev, "%s: integrity check for FMP passed\n", __func__); fmp->result.integrity = 1; } -#else - fmp->result.integrity = 1; -#endif + set_fmp_fips_state(FMP_FIPS_SUCCESS_STATE); fmp->result.overall = 1; fmp_test_exit(fmp->test_data); diff --git a/drivers/crypto/fmp/fmp_test.c b/drivers/crypto/fmp/fmp_test.c index f4a58e610af1..8ca62d9fe8e0 100644 --- a/drivers/crypto/fmp/fmp_test.c +++ b/drivers/crypto/fmp/fmp_test.c @@ -177,13 +177,17 @@ int fmp_cipher_run(struct exynos_fmp *fmp, struct fmp_test_data *fdata, void *priv, struct fmp_crypto_info *ci) { int ret = 0; - struct device *dev = fmp->dev; + struct device *dev; static struct buffer_head *bh; u32 org_algo_mode; int op_flags; - if (!fmp || !fdata || !ci) + if (!fmp || !fdata || !ci) { + pr_err("%s: Invalid fmp struct: %p, %p, %p\n", + __func__, fmp, fdata, ci); return -EINVAL; + } + dev = fmp->dev; bh = __getblk(fdata->bdev, fdata->sector, FMP_BLK_SIZE); if (!bh) { @@ -297,8 +301,10 @@ void fmp_test_exit(struct fmp_test_data *fdata) { fmode_t fmode = FMODE_WRITE | FMODE_READ; - if (!fdata) + if (!fdata) { + pr_err("%s: Invalid exynos fmp struct\n", __func__); return; + } if (fdata->bdev) blkdev_put(fdata->bdev, fmode); kzfree(fdata); diff --git a/drivers/crypto/fmp/smu.c b/drivers/crypto/fmp/smu.c index ce43fb7cfddd..237485543b8e 100644 --- a/drivers/crypto/fmp/smu.c +++ b/drivers/crypto/fmp/smu.c @@ -1,5 +1,5 @@ /* - * UFS SMU (Secure Management Unit) driver for Exynos + * SMU (Secure Management Unit) driver for Exynos * * Copyright (C) 2016 Samsung Electronics Co., Ltd. * @@ -8,242 +8,36 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ -#include -#include -#include -#include +#include #include -#include - #include -static LIST_HEAD(smu_devices); - -struct exynos_smu { - struct list_head list; - int id; - int command; - int desc_type; - struct device *dev; -}; - -static int exynos_smu_init(struct platform_device *pdev, - struct smu_data_setting *smu_set) +int exynos_smu_init(int id, int smu_cmd) { - int ret = 0; - struct exynos_smu *smu = NULL; - - if (!pdev || !smu_set) { - pr_err("%s: Invalid input parameter.\n", __func__); - ret = -EINVAL; - goto err; - } + int ret = exynos_smc(SMC_CMD_SMU, smu_cmd, id, 0); - smu = platform_get_drvdata(pdev); - ret = exynos_smc(SMC_CMD_SMU, smu_set->command, smu_set->id, 0); if (ret) - dev_err(smu->dev, "%s: Fail smc call for SMU init. ret(%d)\n", + pr_err("%s: Fail smc call for SMU init. ret(%d)\n", __func__, ret); -err: return ret; } -static int exynos_smu_sec_config(struct platform_device *pdev, - struct smu_data_setting *smu_set) +int exynos_smu_resume(int id) { - int ret = 0; - struct exynos_smu *smu = NULL; + int ret = exynos_smc(SMC_CMD_FMP_SMU_RESUME, 0, id, 0); - if (!pdev || !smu_set) { - pr_err("%s: Invalid input parameter.\n", __func__); - ret = -EINVAL; - goto err; - } - - smu = platform_get_drvdata(pdev); - ret = exynos_smc(SMC_CMD_FMP_SECURITY, 0, smu_set->id, smu_set->desc_type); if (ret) - dev_err(smu->dev, "%s: Fail smc for FMPSECURITY config. ret(%d)\n", + pr_err("%s: Fail smc call for SMU resume. ret(%d)\n", __func__, ret); -err: return ret; } -static int exynos_smu_resume(struct platform_device *pdev, - struct smu_data_setting *smu_set) +int exynos_smu_abort(int id, int smu_cmd) { - int ret = 0; - struct exynos_smu *smu = NULL; - - if (!pdev || !smu_set) { - pr_err("%s: Invalid input parameter.\n", __func__); - ret = -EINVAL; - goto err; - } + int ret = exynos_smc(SMC_CMD_SMU, smu_cmd, id, 0); - smu = platform_get_drvdata(pdev); - ret = exynos_smc(SMC_CMD_FMP_SMU_RESUME, 0, smu_set->id, 0); if (ret) - dev_err(smu->dev, "%s: Fail smc call for SMU resume. ret(%d)\n", + pr_err("%s: Fail smc call for SMU abort. ret(%d)\n", __func__, ret); -err: - return ret; -} - -static int exynos_smu_abort(struct platform_device *pdev, - struct smu_data_setting *smu_set) -{ - int ret = 0; - - if (!pdev || !smu_set) { - pr_err("%s: Invalid input parameter.\n", __func__); - ret = -EINVAL; - goto err; - } - - ret = exynos_smc(SMC_CMD_SMU, smu_set->command, smu_set->id, 0); -err: - return ret; -} - -const struct exynos_smu_variant_ops exynos_smu_ops = { - .name = "exynos-smu", - .init = exynos_smu_init, - .sec_config = exynos_smu_sec_config, - .resume = exynos_smu_resume, - .abort = exynos_smu_abort, -}; - -static const struct of_device_id exynos_smu_match[] = { - { - .compatible = "samsung,exynos-smu", - .data = (void *)&exynos_smu_ops, - }, - {}, -}; -MODULE_DEVICE_TABLE(of, exynos_smu_match); - -struct platform_device *exynos_smu_get_pdevice(struct device_node *node) -{ - struct platform_device *smu_pdev = NULL; - struct exynos_smu *smu = NULL; - - if (!node) { - pr_err("%s: Invalid node\n", __func__); - goto err; - } - - if (!of_device_is_available(node)) { - pr_err("%s: Unavailable device\n", __func__); - goto err; - } - - if (list_empty(&smu_devices)) { - pr_err("%s: Invalie device list\n", __func__); - smu_pdev = ERR_PTR(-EPROBE_DEFER); - goto err; - } - - list_for_each_entry(smu, &smu_devices, list) { - if (smu->dev->of_node == node) { - pr_info("%s: Found smu device %p\n", __func__, smu); - break; - } - } - - smu_pdev = to_platform_device(smu->dev); - pr_info("%s: Matching platform device %p\n", __func__, smu_pdev); -err: - return smu_pdev; -} -EXPORT_SYMBOL(exynos_smu_get_pdevice); - -struct exynos_smu_variant_ops *exynos_smu_get_variant_ops(struct device_node *node) -{ - if (node) { - const struct of_device_id *match; - - match = of_match_node(exynos_smu_match, node); - if (match) - return (struct exynos_smu_variant_ops *)(match->data); - pr_err("%s: Error matching\n", __func__); - } else { - pr_err("%s: Invalid node\n", __func__); - } - return NULL; -} -EXPORT_SYMBOL(exynos_smu_get_variant_ops); - -static int exynos_smu_probe(struct platform_device *pdev) -{ - int ret = 0; - struct exynos_smu *smu; - - if (!pdev) { - pr_err("%s: Invalid platform_device.\n", __func__); - ret = -EINVAL; - goto err_pdev; - } - - smu = kzalloc(sizeof(struct exynos_smu), GFP_KERNEL); - if (!smu) { - ret = -ENOMEM; - goto err_mem; - } - - smu->dev = &pdev->dev; - if (!smu->dev) { - pr_err("%s: Invalid device.\n", __func__); - ret = -EINVAL; - goto err_dev; - } - - platform_set_drvdata(pdev, smu); - list_add_tail(&smu->list, &smu_devices); - - pr_info("%s: Exynos SMU driver is proved\n", __func__); - return ret; - -err_dev: - kfree(smu); -err_mem: -err_pdev: return ret; } - -static int exynos_smu_remove(struct platform_device *pdev) -{ - struct exynos_smu *smu; - - smu = (struct exynos_smu *)platform_get_drvdata(pdev); - if (!smu) - return 0; - - kfree(smu); - return 0; -} - -static struct platform_driver exynos_smu_driver = { - .driver = { - .name = "exynos-smu", - .owner = THIS_MODULE, - .pm = NULL, - .of_match_table = exynos_smu_match, - }, - .probe = exynos_smu_probe, - .remove = exynos_smu_remove, -}; - -static int __init smu_init(void) -{ - return platform_driver_register(&exynos_smu_driver); -} -subsys_initcall(smu_init); - -static void __exit smu_exit(void) -{ - platform_driver_unregister(&exynos_smu_driver); -} -module_exit(smu_exit); - -MODULE_DESCRIPTION("Exynos Specific SMU(Secure Management Unit) driver"); diff --git a/include/crypto/fmp.h b/include/crypto/fmp.h index 9275ed94dd79..6f8f18361102 100644 --- a/include/crypto/fmp.h +++ b/include/crypto/fmp.h @@ -245,9 +245,9 @@ struct fmp_request { u32 ivsize; }; -#if defined(CONFIG_MMC_DW_EXYNOS_FMP) || defined(CONFIG_SCSI_UFS_EXYNOS_FMP) static inline void exynos_fmp_bypass(void *desc, bool cmdq_enabled) { +#if defined(CONFIG_MMC_DW_EXYNOS_FMP) || defined(CONFIG_SCSI_UFS_EXYNOS_FMP) if (cmdq_enabled) { SET_CMDQ_FAS((struct fmp_table_setting *)desc, 0); SET_CMDQ_DAS((struct fmp_table_setting *)desc, 0); @@ -255,13 +255,14 @@ static inline void exynos_fmp_bypass(void *desc, bool cmdq_enabled) SET_FAS((struct fmp_table_setting *)desc, 0); SET_DAS((struct fmp_table_setting *)desc, 0); } -} #endif +} +int exynos_fmp_sec_config(int id); int exynos_fmp_crypt(struct fmp_crypto_info *ci, void *priv); int exynos_fmp_clear(struct fmp_crypto_info *ci, void *priv); int exynos_fmp_setkey(struct fmp_crypto_info *ci, - char *in_key, u32 keylen, bool persistent); + u8 *in_key, u32 keylen, bool persistent); int exynos_fmp_clearkey(struct fmp_crypto_info *ci); void *exynos_fmp_init(struct platform_device *pdev); void exynos_fmp_exit(struct exynos_fmp *fmp); diff --git a/include/crypto/smu.h b/include/crypto/smu.h index d9fa4f0c10a2..cbba9f681c7d 100644 --- a/include/crypto/smu.h +++ b/include/crypto/smu.h @@ -10,25 +10,13 @@ #ifndef _EXYNOS_SMU_H_ #define _EXYNOS_SMU_H_ -#include - -#define CFG_DESCTYPE_0 0x0 -#define CFG_DESCTYPE_1 0x1 -#define CFG_DESCTYPE_2 0x2 -#define CFG_DESCTYPE_3 0x3 - -#if defined(CONFIG_EXYNOS_FMP) -#define CFG_DESCTYPE CFG_DESCTYPE_3 -#else -#define CFG_DESCTYPE CFG_DESCTYPE_0 -#endif - #define ACCESS_CONTROL_ABORT 0x14 enum smu_id { SMU_EMBEDDED = 0, SMU_UFSCARD = 1, SMU_SDCARD = 2, + SMU_ID_MAX, }; enum smu_command { @@ -37,21 +25,7 @@ enum smu_command { SMU_ABORT = 2, }; -struct smu_data_setting { - int id; - int command; - int desc_type; -}; - -struct exynos_smu_variant_ops { - const char *name; - int (*init)(struct platform_device *, struct smu_data_setting *); - int (*sec_config)(struct platform_device *, struct smu_data_setting *); - int (*resume)(struct platform_device *, struct smu_data_setting *); - int (*abort)(struct platform_device *, struct smu_data_setting *); -}; - -struct exynos_smu_variant_ops *exynos_smu_get_variant_ops(struct device_node *node); -struct platform_device *exynos_smu_get_pdevice(struct device_node *node); - +int exynos_smu_init(int id, int smu_cmd); +int exynos_smu_resume(int id); +int exynos_smu_abort(int id, int smu_cmd); #endif /* _EXYNOS_SMU_H_ */ -- 2.20.1