[COMMON] fmp: update multi-host for fmp
authorBoojin Kim <boojin.kim@samsung.com>
Fri, 16 Mar 2018 00:26:50 +0000 (09:26 +0900)
committerJunho Choi <junhosj.choi@samsung.com>
Thu, 24 May 2018 00:02:01 +0000 (09:02 +0900)
Change-Id: Ib2bd3264d07eb6dabb874a5062a16a3d7a2b7d10
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
drivers/crypto/fmp/Kconfig
drivers/crypto/fmp/fmp.c
drivers/crypto/fmp/fmp_fips_cipher.c
drivers/crypto/fmp/fmp_fips_integrity.c
drivers/crypto/fmp/fmp_fips_main.c
drivers/crypto/fmp/fmp_test.c
drivers/crypto/fmp/smu.c
include/crypto/fmp.h
include/crypto/smu.h

index 4215d52fd6c7c2ffdb3ef5ca3504edfd7e885cbc..74046b6b9c53c68d5072174ca475fdda1e914ec5 100644 (file)
@@ -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.
index 2dd14999c31576a97bceb13c11b3bd4dee34c19d..706c4bffc21ccad977728a759eac6d6705bb9c94 100644 (file)
@@ -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;
index 21d5b42cfea3905552b2734f78dcbd9b20351c64..62fc403910f80c482a26baf9f7284243e96e402c 100644 (file)
@@ -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) {
index 5907022e0aaf0d882e7e874cf5458a38a6fea00d..9840f4378aded1c904fd4243dd0544fe809f8b59 100644 (file)
@@ -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;
index 6ccad737956e840b9058f4acb86aafbba476ccb7..5cfd4ddf20663c906aa4407005fed677f64c8738 100644 (file)
@@ -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);
index f4a58e610af151dd93e89f59d7b4aaa66415a41c..8ca62d9fe8e03efe6ed8dfb2d3c07d745ed9bfb2 100644 (file)
@@ -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);
index ce43fb7cfddd341efdfd07385aa3a5e07574db64..237485543b8ed48ecf2461258d26c347973b4129 100644 (file)
@@ -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.
  *
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/slab.h>
+#include <linux/printk.h>
 #include <linux/smc.h>
-#include <linux/list.h>
-
 #include <crypto/smu.h>
 
-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");
index 9275ed94dd79f7a57dee82a4c22420676b79bf1f..6f8f183611024a0b7a2f8442baa4dc13708d94c5 100644 (file)
@@ -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);
index d9fa4f0c10a2a1b039b59887b493e7927dca51ab..cbba9f681c7de6b762e0e18a67260502eade7ea5 100644 (file)
 #ifndef _EXYNOS_SMU_H_
 #define _EXYNOS_SMU_H_
 
-#include <linux/platform_device.h>
-
-#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_ */