unifykey: check secure check secure storage valid before SMC call ATF.

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>
This commit is contained in:
Yan Wang
2017-09-04 19:57:13 +08:00
parent 53160bf7b0
commit cbfe6c2ec4
2 changed files with 112 additions and 68 deletions

View 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;
}

View 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);