mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user