unifykey: check secure check secure storage valid before SMC call ATF.
authorYan Wang <yan.wang@amlogic.com>
Mon, 4 Sep 2017 11:57:13 +0000 (19:57 +0800)
committerYan Wang <yan.wang@amlogic.com>
Fri, 13 Oct 2017 06:13:31 +0000 (23:13 -0700)
  PD#150482: unifykey: check secure storage valid before SMC call ATF.

  same as PD#150483.

    ATF use CONFIG to enable/disable secure storage.
    If ATF disable secure storage, secure storage code will be
    compiled out. Kernel should check if secure stroage exists before
    SMC call ATF.

Change-Id: Ifd5e3c42a181bb814dcedad13bebb4596ae95e27
Signed-off-by: Yan Wang <yan.wang@amlogic.com>
drivers/amlogic/unifykey/v8/securitykey.c
include/linux/amlogic/unifykey/security_key.h

index 5b6b23f..c966772 100644 (file)
@@ -56,6 +56,8 @@ static unsigned long storage_version_func;
 static DEFINE_SPINLOCK(storage_lock);
 static unsigned long lockflags;
 
+static int storage_init_status;
+
 static uint64_t storage_smc_ops(uint64_t func)
 {
        register unsigned long x0 asm("x0") = func;
@@ -111,16 +113,19 @@ int32_t secure_storage_write(uint8_t *keyname, uint8_t *keybuf,
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       input = (uint32_t *)storage_in_base;
-       *input++ = namelen;
-       *input++ = keylen;
-       *input++ = keyattr;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       keydata = name + namelen;
-       memcpy(keydata, keybuf, keylen);
-       ret = storage_smc_ops(storage_write_func);
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               input = (uint32_t *)storage_in_base;
+               *input++ = namelen;
+               *input++ = keylen;
+               *input++ = keyattr;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               keydata = name + namelen;
+               memcpy(keydata, keybuf, keylen);
+               ret = storage_smc_ops(storage_write_func);
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
        return smc_to_linux_errno(ret);
 }
@@ -135,17 +140,20 @@ int32_t secure_storage_read(uint8_t *keyname, uint8_t *keybuf,
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       *input++ = namelen;
-       *input++ = keylen;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       ret = storage_smc_ops(storage_read_func);
-       if (ret == RET_OK) {
-               *readlen = *output;
-               buf = (uint8_t *)(output + 1);
-               memcpy(keybuf, buf, *readlen);
-       }
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               *input++ = namelen;
+               *input++ = keylen;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               ret = storage_smc_ops(storage_read_func);
+               if (ret == RET_OK) {
+                       *readlen = *output;
+                       buf = (uint8_t *)(output + 1);
+                       memcpy(keybuf, buf, *readlen);
+               }
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
        return smc_to_linux_errno(ret);
 }
@@ -159,13 +167,16 @@ int32_t secure_storage_verify(uint8_t *keyname, uint8_t *hashbuf)
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       *input++ = namelen;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       ret = storage_smc_ops(storage_verify_func);
-       if (ret == RET_OK)
-               memcpy(hashbuf, (uint8_t *)output, 32);
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               *input++ = namelen;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               ret = storage_smc_ops(storage_verify_func);
+               if (ret == RET_OK)
+                       memcpy(hashbuf, (uint8_t *)output, 32);
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
 
        return smc_to_linux_errno(ret);
@@ -180,13 +191,16 @@ int32_t secure_storage_query(uint8_t *keyname, uint32_t *retval)
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       *input++ = namelen;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       ret = storage_smc_ops(storage_query_func);
-       if (ret == RET_OK)
-               *retval = *output;
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               *input++ = namelen;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               ret = storage_smc_ops(storage_query_func);
+               if (ret == RET_OK)
+                       *retval = *output;
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
 
        return smc_to_linux_errno(ret);
@@ -201,13 +215,16 @@ int32_t secure_storage_tell(uint8_t *keyname, uint32_t *retval)
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       *input++ = namelen;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       ret = storage_smc_ops(storage_tell_func);
-       if (ret == RET_OK)
-               *retval = *output;
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               *input++ = namelen;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               ret = storage_smc_ops(storage_tell_func);
+               if (ret == RET_OK)
+                       *retval = *output;
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
        return smc_to_linux_errno(ret);
 }
@@ -221,13 +238,16 @@ int32_t secure_storage_status(uint8_t *keyname, uint32_t *retval)
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       *input++ = namelen;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       ret = storage_smc_ops(storage_status_func);
-       if (ret == RET_OK)
-               *retval = *output;
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               *input++ = namelen;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               ret = storage_smc_ops(storage_status_func);
+               if (ret == RET_OK)
+                       *retval = *output;
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
        return smc_to_linux_errno(ret);
 }
@@ -239,14 +259,17 @@ int32_t secure_storage_list(uint8_t *listbuf,
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       ret = storage_smc_ops(storage_list_func);
-       if (ret == RET_OK) {
-               if (*output > buflen)
-                       *readlen = buflen;
-               else
-                       *readlen = *output;
-               memcpy(listbuf, (uint8_t *)(output+1), *readlen);
-       }
+       if (storage_init_status == 1) {
+               ret = storage_smc_ops(storage_list_func);
+               if (ret == RET_OK) {
+                       if (*output > buflen)
+                               *readlen = buflen;
+                       else
+                               *readlen = *output;
+                       memcpy(listbuf, (uint8_t *)(output+1), *readlen);
+               }
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
        return smc_to_linux_errno(ret);
 }
@@ -259,11 +282,14 @@ int32_t secure_storage_remove(uint8_t *keyname)
        uint64_t ret;
 
        spin_lock_irqsave(&storage_lock, lockflags);
-       namelen = strlen((const char *)keyname);
-       *input++ = namelen;
-       name = (uint8_t *)input;
-       memcpy(name, keyname, namelen);
-       ret = storage_smc_ops(storage_remove_func);
+       if (storage_init_status == 1) {
+               namelen = strlen((const char *)keyname);
+               *input++ = namelen;
+               name = (uint8_t *)input;
+               memcpy(name, keyname, namelen);
+               ret = storage_smc_ops(storage_remove_func);
+       }       else
+               ret = RET_EUND;
        spin_unlock_irqrestore(&storage_lock, lockflags);
        return smc_to_linux_errno(ret);
 }
@@ -345,12 +371,22 @@ static int storage_probe(struct platform_device *pdev)
                return -1;
        }
 
-       storage_in_base = ioremap_cache(phy_storage_in_base,
-                                       storage_block_size);
-       storage_out_base = ioremap_cache(phy_storage_out_base,
-                                       storage_block_size);
-       storage_block_base = ioremap_cache(phy_storage_block_base,
-                                       storage_block_size);
+       if (phy_storage_in_base == SMC_UNK
+                       || phy_storage_out_base == SMC_UNK
+                       || phy_storage_block_base == SMC_UNK
+                       || storage_block_size == SMC_UNK) {
+               storage_in_base = NULL;
+               storage_out_base = NULL;
+               storage_block_base = NULL;
+       }       else {
+               storage_in_base = ioremap_cache(phy_storage_in_base,
+                                               storage_block_size);
+               storage_out_base = ioremap_cache(phy_storage_out_base,
+                                               storage_block_size);
+               storage_block_base = ioremap_cache(phy_storage_block_base,
+                                               storage_block_size);
+       }
+
        pr_info("storage in base: 0x%lx\n", (long)storage_in_base);
        pr_info("storage out base: 0x%lx\n", (long)storage_out_base);
        pr_info("storage block base: 0x%lx\n", (long)storage_block_base);
@@ -358,6 +394,11 @@ static int storage_probe(struct platform_device *pdev)
        ret = 0;
        if (!storage_in_base || !storage_out_base || !storage_block_base)
                ret = -1;
+       if (ret == 0)
+               storage_init_status = 1;
+       else
+               storage_init_status = -1;
+
        pr_info("probe done!\n");
        return ret;
 }
index 04e57d0..b73fd73 100644 (file)
@@ -24,6 +24,9 @@
 #define RET_EINVAL     2       /*name length*/
 #define RET_EMEM       3       /*no enough memory*/
 
+#define RET_EUND       -1
+#define SMC_UNK                0xffffffff
+
 /* keyattr: 0: normal, 1: secure*/
 int32_t secure_storage_write(uint8_t *keyname, uint8_t *keybuf,
                        uint32_t keylen, uint32_t keyattr);