Update source to Armbian-dev-202610.A311Y3

This commit is contained in:
2026-11-11 08:50:43 +08:00
parent 3428a94f6b
commit f459ef6a9e
12514 changed files with 2264376 additions and 468481 deletions
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
config AMLOGIC_EFUSE_UNIFYKEY
tristate "Amlogic EUSE and UNIFYKEY support"
tristate "Amlogic EFUSE and UNIFYKEY support"
default n
help
amlogic EFUSE and UNIFYKEY glue driver
@@ -22,7 +22,7 @@ config AMLOGIC_UNIFYKEY
not choose by default
config AMLOGIC_EFUSE_BURN
bool "Amlogic efuse pattern burn suppot"
bool "Amlogic efuse pattern burn support"
default n
help
en, if project need burn efuse pattern file, then
@@ -34,5 +34,5 @@ config AMLOGIC_DEFENDKEY
tristate "Amlogic defendkey driver support"
default n
help
amlogic defendkey device driver
not choose by default
amlogic defendkey device driver
not choose by default
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
MODULE_NAME = amlogic-efuse-unifykey
obj-$(CONFIG_AMLOGIC_EFUSE_UNIFYKEY) = $(MODULE_NAME).o
obj-$(CONFIG_AMLOGIC_EFUSE_UNIFYKEY) += $(MODULE_NAME).o
$(MODULE_NAME)-y += efuse_unifykey.o
$(MODULE_NAME)-$(CONFIG_AMLOGIC_EFUSE) += efuse.o efuse_api.o
$(MODULE_NAME)-$(CONFIG_AMLOGIC_EFUSE_BURN) += efuse_burn.o
@@ -20,41 +20,55 @@
#include "efuse_burn.h"
#include "defendkey.h"
#define EFUSE_BIT BIT(0)
#define UNIFYKEY_BIT BIT(1)
#define BURN_BIT BIT(2)
#define DEFENDKEY_BIT BIT(3)
static unsigned int efuse_unifykey_init_mask;
static int __init efuse_unifykey_init(void)
{
int ret;
ret = aml_efuse_init();
if (ret)
return ret;
if (!ret)
efuse_unifykey_init_mask |= EFUSE_BIT;
ret = aml_unifykeys_init();
if (ret) {
aml_efuse_exit();
return ret;
}
if (!ret)
efuse_unifykey_init_mask |= UNIFYKEY_BIT;
ret = aml_efuse_burn_init();
if (ret) {
aml_efuse_burn_exit();
return ret;
}
if (!ret)
efuse_unifykey_init_mask |= BURN_BIT;
ret = aml_defendkey_init();
if (ret) {
aml_efuse_burn_exit();
return ret;
}
if (!ret)
efuse_unifykey_init_mask |= DEFENDKEY_BIT;
if (efuse_unifykey_init_mask != (EFUSE_BIT | UNIFYKEY_BIT | BURN_BIT |
DEFENDKEY_BIT))
pr_err("efuse_unifykey: init incomplete, mask=0x%x, failed:%s%s%s%s\n",
efuse_unifykey_init_mask,
(efuse_unifykey_init_mask & EFUSE_BIT) ? "" : " efuse",
(efuse_unifykey_init_mask & UNIFYKEY_BIT) ? "" : " unifykey",
(efuse_unifykey_init_mask & BURN_BIT) ? "" : " burn",
(efuse_unifykey_init_mask & DEFENDKEY_BIT) ? "" : " defendkey");
return 0;
}
static void __exit efuse_unifykey_exit(void)
{
aml_efuse_exit();
aml_unifykeys_exit();
aml_efuse_burn_exit();
aml_defendkey_exit();
if (efuse_unifykey_init_mask & DEFENDKEY_BIT)
aml_defendkey_exit();
if (efuse_unifykey_init_mask & BURN_BIT)
aml_efuse_burn_exit();
if (efuse_unifykey_init_mask & UNIFYKEY_BIT)
aml_unifykeys_exit();
if (efuse_unifykey_init_mask & EFUSE_BIT)
aml_efuse_exit();
}
module_init(efuse_unifykey_init);
@@ -246,8 +246,13 @@ static u32 Tlv_ReadObject(u8 *input, int32_t len,
switch (tag) {
case EMTLVOBJNAMESIZE:
pcontent->namesize = *((u32 *)(input + idx));
if (pcontent->namesize > MAX_OBJ_NAME_LEN - 1)
goto tlv_readkeycontent_err;
break;
case EMTLVOBJNAME:
if (pcontent->namesize == 0 ||
pcontent->namesize > length)
goto tlv_readkeycontent_err;
memset(pcontent->name, 0, MAX_OBJ_NAME_LEN);
memcpy(pcontent->name, input + idx, pcontent->namesize);
break;
@@ -266,6 +271,9 @@ static u32 Tlv_ReadObject(u8 *input, int32_t len,
memcpy(pcontent->hashptr, input + idx, length);
break;
case EMTLVOBJDATABUF:
if (pcontent->datasize == 0 ||
pcontent->datasize > length)
goto tlv_readkeycontent_err;
pcontent->dataptr = kmalloc(pcontent->datasize,
GFP_KERNEL);
if (!pcontent->dataptr)
@@ -278,10 +286,13 @@ static u32 Tlv_ReadObject(u8 *input, int32_t len,
}
idx += length;
}
if (pcontent->datasize && !pcontent->dataptr)
goto tlv_readkeycontent_err;
return sum;
tlv_readkeycontent_err:
kfree(pcontent->dataptr);
pcontent->dataptr = NULL;
return 0;
}
@@ -371,7 +382,7 @@ static int normalkey_hash(u8 *data, u32 len, u8 *hash)
{
struct crypto_shash *tfm;
struct shash_desc *desc;
int ret = -1;
int ret;
memset(hash, 0, SHA256_DIGEST_SIZE);
tfm = crypto_alloc_shash("sha256", 0, 0);
@@ -461,7 +472,7 @@ int normalkey_add(const u8 *name, u8 *buffer, u32 len, u32 attr)
return -1;
namelen = strlen(name);
if (namelen > MAX_OBJ_NAME_LEN)
if (namelen >= MAX_OBJ_NAME_LEN)
return -1;
obj = normalkey_get(name);
@@ -624,6 +635,8 @@ int normalkey_readfromblock(void *block, unsigned long size)
break;
}
idx += ret;
if (!obj->dataptr)
continue;
normalkey_hash(obj->dataptr, obj->datasize, hash);
if (memcmp(hash, obj->hashptr, 32)) {
kfree(obj->dataptr);
@@ -6,7 +6,7 @@
// #define DEBUG
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/amlogic/arm-smccc.h>
#include <linux/io.h>
#include <linux/mm.h>
@@ -22,13 +22,14 @@ static struct device_node *ofdts_node;
static int pfn_valid_flag;
#endif
static DEFINE_SPINLOCK(storage_lock);
static DEFINE_MUTEX(storage_lock);
static int storage_init_status;
static struct bl31_storage_share_mem *share_mem;
static int share_mem_ioremapped;
static unsigned long storage_smc_ops(u64 func)
{
struct arm_smccc_res res;
struct arm_smccc_res res = {0};
arm_smccc_smc((unsigned long)func, 0, 0, 0, 0, 0, 0, 0, &res);
return res.a0;
@@ -53,16 +54,20 @@ unsigned long secure_storage_write(u8 *keyname, u8 *keybuf,
u8 *keydata;
u8 *name;
unsigned long ret;
unsigned long lockflags;
if (storage_init_status != 1)
mutex_lock(&storage_lock);
if (!share_mem || !share_mem->in || storage_init_status != 1) {
mutex_unlock(&storage_lock);
return RET_EUND;
}
namelen = strlen(keyname);
if (namelen + keylen + 12 > share_mem->size)
if (keylen > share_mem->size ||
namelen + 12 > share_mem->size - keylen) {
mutex_unlock(&storage_lock);
return RET_EMEM;
}
spin_lock_irqsave(&storage_lock, lockflags);
input = (u32 *)(share_mem->in);
*input++ = namelen;
*input++ = keylen;
@@ -72,7 +77,7 @@ unsigned long secure_storage_write(u8 *keyname, u8 *keybuf,
keydata = name + namelen;
memcpy(keydata, keybuf, keylen);
ret = storage_smc_ops(BL31_STORAGE_WRITE);
spin_unlock_irqrestore(&storage_lock, lockflags);
mutex_unlock(&storage_lock);
return ret;
}
@@ -86,16 +91,19 @@ unsigned long secure_storage_read(u8 *keyname, u8 *keybuf,
u8 *name;
u8 *buf;
unsigned long ret;
unsigned long lockflags;
if (storage_init_status != 1)
mutex_lock(&storage_lock);
if (!share_mem || !share_mem->in || !share_mem->out || storage_init_status != 1) {
mutex_unlock(&storage_lock);
return RET_EUND;
}
namelen = strlen(keyname);
if (namelen + 8 > share_mem->size)
if (namelen + 8 > share_mem->size) {
mutex_unlock(&storage_lock);
return RET_EMEM;
}
spin_lock_irqsave(&storage_lock, lockflags);
input = (u32 *)(share_mem->in);
output = (u32 *)(share_mem->out);
*input++ = namelen;
@@ -110,7 +118,7 @@ unsigned long secure_storage_read(u8 *keyname, u8 *keybuf,
buf = (u8 *)(output + 1);
memcpy(keybuf, buf, *readlen);
}
spin_unlock_irqrestore(&storage_lock, lockflags);
mutex_unlock(&storage_lock);
return ret;
}
@@ -122,16 +130,19 @@ unsigned long secure_storage_verify(u8 *keyname, u8 *hashbuf)
u32 namelen;
u8 *name;
unsigned long ret;
unsigned long lockflags;
if (storage_init_status != 1)
mutex_lock(&storage_lock);
if (!share_mem || !share_mem->in || !share_mem->out || storage_init_status != 1) {
mutex_unlock(&storage_lock);
return RET_EUND;
}
namelen = strlen(keyname);
if (namelen + 4 > share_mem->size)
if (namelen + 4 > share_mem->size) {
mutex_unlock(&storage_lock);
return RET_EMEM;
}
spin_lock_irqsave(&storage_lock, lockflags);
input = (u32 *)(share_mem->in);
output = (u32 *)(share_mem->out);
*input++ = namelen;
@@ -140,7 +151,7 @@ unsigned long secure_storage_verify(u8 *keyname, u8 *hashbuf)
ret = storage_smc_ops(BL31_STORAGE_VERIFY);
if (ret == RET_OK)
memcpy(hashbuf, (u8 *)output, 32);
spin_unlock_irqrestore(&storage_lock, lockflags);
mutex_unlock(&storage_lock);
return ret;
}
@@ -152,16 +163,19 @@ unsigned long secure_storage_query(u8 *key_name, u32 *retval)
u32 namelen;
u8 *name;
unsigned long ret;
unsigned long lockflags;
if (storage_init_status != 1)
mutex_lock(&storage_lock);
if (!share_mem || !share_mem->in || !share_mem->out || storage_init_status != 1) {
mutex_unlock(&storage_lock);
return RET_EUND;
}
namelen = strlen(key_name);
if (namelen + 4 > share_mem->size)
if (namelen + 4 > share_mem->size) {
mutex_unlock(&storage_lock);
return RET_EMEM;
}
spin_lock_irqsave(&storage_lock, lockflags);
input = (u32 *)(share_mem->in);
output = (u32 *)(share_mem->out);
*input++ = namelen;
@@ -170,7 +184,7 @@ unsigned long secure_storage_query(u8 *key_name, u32 *retval)
ret = storage_smc_ops(BL31_STORAGE_QUERY);
if (ret == RET_OK)
*retval = *output;
spin_unlock_irqrestore(&storage_lock, lockflags);
mutex_unlock(&storage_lock);
return ret;
}
@@ -182,16 +196,19 @@ unsigned long secure_storage_tell(u8 *keyname, u32 *retval)
u32 namelen;
u8 *name;
unsigned long ret;
unsigned long lockflags;
if (storage_init_status != 1)
mutex_lock(&storage_lock);
if (!share_mem || !share_mem->in || !share_mem->out || storage_init_status != 1) {
mutex_unlock(&storage_lock);
return RET_EUND;
}
namelen = strlen(keyname);
if (namelen + 4 > share_mem->size)
if (namelen + 4 > share_mem->size) {
mutex_unlock(&storage_lock);
return RET_EMEM;
}
spin_lock_irqsave(&storage_lock, lockflags);
input = (u32 *)(share_mem->in);
output = (u32 *)(share_mem->out);
*input++ = namelen;
@@ -200,7 +217,7 @@ unsigned long secure_storage_tell(u8 *keyname, u32 *retval)
ret = storage_smc_ops(BL31_STORAGE_TELL);
if (ret == RET_OK)
*retval = *output;
spin_unlock_irqrestore(&storage_lock, lockflags);
mutex_unlock(&storage_lock);
return ret;
}
@@ -212,16 +229,19 @@ unsigned long secure_storage_status(u8 *keyname, u32 *retval)
u32 namelen;
u8 *name;
u64 ret;
unsigned long lockflags;
if (storage_init_status != 1)
mutex_lock(&storage_lock);
if (!share_mem || !share_mem->in || !share_mem->out || storage_init_status != 1) {
mutex_unlock(&storage_lock);
return RET_EUND;
}
namelen = strlen(keyname);
if (namelen + 4 > share_mem->size)
if (namelen + 4 > share_mem->size) {
mutex_unlock(&storage_lock);
return RET_EMEM;
}
spin_lock_irqsave(&storage_lock, lockflags);
input = (u32 *)(share_mem->in);
output = (u32 *)(share_mem->out);
*input++ = namelen;
@@ -230,7 +250,7 @@ unsigned long secure_storage_status(u8 *keyname, u32 *retval)
ret = storage_smc_ops(BL31_STORAGE_STATUS);
if (ret == RET_OK)
*retval = *output;
spin_unlock_irqrestore(&storage_lock, lockflags);
mutex_unlock(&storage_lock);
return ret;
}
@@ -241,7 +261,7 @@ int __init security_key_init(struct platform_device *pdev)
unsigned long phy_out;
unsigned long phy_block;
storage_init_status = -1;
storage_init_status = 0;
share_mem = devm_kzalloc(&pdev->dev, sizeof(*share_mem), GFP_KERNEL);
if (IS_ERR_OR_NULL(share_mem)) {
@@ -295,6 +315,7 @@ int __init security_key_init(struct platform_device *pdev)
share_mem->in = ioremap_cache(phy_in, share_mem->size);
share_mem->out = ioremap_cache(phy_out, share_mem->size);
share_mem->block = ioremap_cache(phy_block, share_mem->size);
share_mem_ioremapped = 1;
}
pr_info("storage in: 0x%lx, out: 0x%lx, block: 0x%lx\n",
@@ -310,3 +331,25 @@ int __init security_key_init(struct platform_device *pdev)
pr_info("security_key init done!\n");
return 0;
}
void security_key_deinit(void)
{
if (!share_mem)
return;
mutex_lock(&storage_lock);
storage_init_status = 0;
if (share_mem_ioremapped) {
if (share_mem->in)
iounmap(share_mem->in);
if (share_mem->out)
iounmap(share_mem->out);
if (share_mem->block)
iounmap(share_mem->block);
share_mem_ioremapped = 0;
}
share_mem->in = NULL;
share_mem->out = NULL;
share_mem->block = NULL;
mutex_unlock(&storage_lock);
}
@@ -47,4 +47,5 @@ unsigned long secure_storage_tell(u8 *name, u32 *retval);
unsigned long secure_storage_status(u8 *name, u32 *retval);
void *secure_storage_getbuf(u32 *size);
int __init security_key_init(struct platform_device *pdev);
void security_key_deinit(void);
#endif
@@ -27,7 +27,7 @@
#define SECUREKEY_SIZE SECURESTORAGE_WHOLE_SIZE
static DEFINE_MUTEX(securekey_lock);
u8 *securekey_prebuf;
static u8 *securekey_prebuf;
struct storagekey_info_t {
u8 *buffer;
@@ -53,7 +53,7 @@ int is_valid_unifykey_storage_type(u32 storage_type)
return 0;
}
return -EINVAL;
return 1;
}
int register_unifykey_types(struct unifykey_type *uk_type)
@@ -73,13 +73,18 @@ int register_unifykey_types(struct unifykey_type *uk_type)
goto error;
}
if (!uk_type->ops || !unifykey_types.ops) {
ret = -EINVAL;
goto error;
}
unifykey_types.storage_type = uk_type->storage_type;
unifykey_types.ops->read = uk_type->ops->read;
unifykey_types.ops->write = uk_type->ops->write;
error:
if (ret)
pr_err("register unifykey types failed: %d", ret);
pr_err("register unifykey types failed: %d\n", ret);
return ret;
}
EXPORT_SYMBOL(register_unifykey_types);
@@ -112,7 +117,7 @@ static s32 _amlkey_init(u8 *seed, u32 len, int encrypt_type)
}
uk_type = &unifykey_types;
if (unlikely(!uk_type->ops->read)) {
if (!uk_type->ops || unlikely(!uk_type->ops->read)) {
ret = -3;
goto error;
}
@@ -129,12 +134,14 @@ static s32 _amlkey_init(u8 *seed, u32 len, int encrypt_type)
&actual_size);
if (ret) {
memset(storagekey_info.buffer, 0, SECURESTORAGE_HEAD_SIZE);
storagekey_info.buffer = NULL;
ret = -5;
goto _out;
}
if (actual_size >= (1U << 20)) {
memset(storagekey_info.buffer, 0, SECURESTORAGE_HEAD_SIZE);
storagekey_info.buffer = NULL;
ret = -6;
goto _out;
}
@@ -150,7 +157,7 @@ _out:
error:
if (ret)
pr_err("amlkey init failed: %d", ret);
pr_err("amlkey init failed: %d\n", ret);
return ret;
}
@@ -166,6 +173,7 @@ int securekey_prebuf_init(void)
void securekey_prebuf_deinit(void)
{
kfree(securekey_prebuf);
securekey_prebuf = NULL;
}
static u32 _amlkey_exist(const u8 *name)
@@ -291,7 +299,7 @@ static ssize_t _amlkey_write(const u8 *name, u8 *buffer,
buf = securekey_prebuf;
memcpy(buf, storagekey_info.buffer, storagekey_info.size);
if (!uk_type->ops->write) {
if (!uk_type->ops || !uk_type->ops->write) {
err = -7;
retval = 0;
mutex_unlock(&securekey_lock);
@@ -306,7 +314,7 @@ static ssize_t _amlkey_write(const u8 *name, u8 *buffer,
_out:
if (err)
pr_err("amlkey write failed: %d", err);
pr_err("amlkey write failed: %d\n", err);
return retval;
}
@@ -330,8 +338,7 @@ static s32 _amlkey_init_normal(u8 *seed, u32 len, int encrypt_type)
err = -1;
goto error;
}
if (!unifykey_types.ops->read) {
if (!unifykey_types.ops || !unifykey_types.ops->read) {
err = -2;
goto error;
}
@@ -342,6 +349,7 @@ static s32 _amlkey_init_normal(u8 *seed, u32 len, int encrypt_type)
}
mutex_lock(&normalkey_lock);
memset(normal_block, 0, normal_blksz);
ret = unifykey_types.ops->read(normal_block,
normal_blksz,
&normal_flashsize);
@@ -364,7 +372,7 @@ finish:
error:
if (err)
pr_err("amlkey init normal failed: %d", err);
pr_err("amlkey init normal failed: %d\n", err);
return ret;
}
@@ -414,7 +422,7 @@ static unsigned int _amlkey_read_normal(const u8 *name, u8 *buffer, u32 len)
mutex_lock(&normalkey_lock);
obj = normalkey_get(name);
if (obj && len >= obj->datasize) {
if (obj && obj->dataptr && len >= obj->datasize) {
size = obj->datasize;
memcpy(buffer, obj->dataptr, size);
}
@@ -434,8 +442,7 @@ static ssize_t _amlkey_write_normal(const u8 *name, u8 *buffer,
err = -1;
goto error;
}
if (!unifykey_types.ops->write) {
if (!unifykey_types.ops || !unifykey_types.ops->write) {
err = -2;
goto error;
}
@@ -469,7 +476,7 @@ unlock:
error:
if (err)
pr_err("amlkey write normal failed: %d", err);
pr_err("amlkey write normal failed: %d\n", err);
return ret;
}
@@ -491,7 +498,7 @@ static s32 _amlkey_hash_normal(const u8 *name, u8 *hash)
int normal_key_init(struct platform_device *pdev)
{
u32 blksz;
u32 blksz = 0;
int ret;
ret = device_property_read_u32(&pdev->dev, "blocksize", &blksz);
@@ -510,6 +517,7 @@ int normal_key_init(struct platform_device *pdev)
void normal_key_deinit(void)
{
kfree(normal_block);
normal_block = NULL;
}
enum amlkey_if_type {
@@ -518,7 +526,7 @@ enum amlkey_if_type {
IFTYPE_MAX
};
struct amlkey_if amlkey_ifs[] = {
static struct amlkey_if amlkey_ifs[] = {
[IFTYPE_SECURE_STORAGE] = {
.init = _amlkey_init,
.exist = _amlkey_exist,
@@ -546,23 +554,27 @@ int __init amlkey_if_init(struct platform_device *pdev)
int ret;
ret = security_key_init(pdev);
if (ret != -EOPNOTSUPP) {
if (ret == 0) {
pr_info("secure key used!\n");
amlkey_if = &amlkey_ifs[IFTYPE_SECURE_STORAGE];
ret = securekey_prebuf_init();
return ret;
return securekey_prebuf_init();
}
if (ret == -EOPNOTSUPP) {
pr_info("normal key used!\n");
ret = normal_key_init(pdev);
amlkey_if = &amlkey_ifs[IFTYPE_NORMAL_STORAGE];
}
pr_info("normal key used!\n");
ret = normal_key_init(pdev);
amlkey_if = &amlkey_ifs[IFTYPE_NORMAL_STORAGE];
return ret;
}
void amlkey_if_deinit(void)
{
security_key_deinit();
securekey_prebuf_deinit();
normal_key_deinit();
amlkey_if = NULL;
}
@@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/atomic.h>
#if defined(CONFIG_AMLOGIC_EFUSE)
#include <linux/amlogic/efuse.h>
#endif
@@ -35,7 +36,7 @@ typedef int (*key_unify_dev_init)(struct key_info_t *uk_info,
char *buf, unsigned int len);
static struct aml_uk_dev *ukdev_global;
static int lock;
static atomic_t lock = ATOMIC_INIT(0);
static DEFINE_MUTEX(attach_mutex);
struct unifykey_type *storage_device[] = {
#if IS_ENABLED(CONFIG_AMLOGIC_MMC_MESON_GX)
@@ -62,11 +63,17 @@ static struct key_item_t *uk_find_item_by_name(struct list_head *list,
{
struct key_item_t *item;
list_for_each_entry(item, list, node)
/*
* list_for_each_entry can guarantee item is not null.
*/
/* coverity[NULL_FIELD:SUPPRESS] */
list_for_each_entry(item, list, node) {
/* coverity[NULL_FIELD:SUPPRESS] */
if (!strncmp(item->name, name,
((strlen(item->name) > strlen(name)) ?
strlen(item->name) : strlen(name))))
return item;
}
return NULL;
}
@@ -75,9 +82,15 @@ static struct key_item_t *uk_find_item_by_id(struct list_head *list, int id)
{
struct key_item_t *item;
list_for_each_entry(item, list, node)
/*
* list_for_each_entry can guarantee item is not null.
*/
/* coverity[NULL_FIELD:SUPPRESS] */
list_for_each_entry(item, list, node) {
/* coverity[NULL_FIELD:SUPPRESS] */
if (item->id == id)
return item;
}
return NULL;
}
@@ -87,7 +100,12 @@ static int uk_count_key(struct list_head *list)
int count = 0;
struct list_head *node;
/*
* list_for_each can guarantee node is not null.
*/
/* coverity[NULL_FIELD:SUPPRESS] */
list_for_each(node, list)
/* coverity[NULL_FIELD:SUPPRESS] */
count++;
return count;
@@ -108,7 +126,7 @@ static int key_storage_read(char *name, unsigned char *data,
}
/* make sure attr in storage & dts are the same! */
encrypt = amlkey_get_attr((u8 *)name) & KEY_ATTR_ENCRYPT;
encrypt = (amlkey_get_attr((u8 *)name) & KEY_ATTR_ENCRYPT) ? 1 : 0;
encrypt_dts = (u32)(flag & KEY_ATTR_ENCRYPT) ? 1 : 0;
if (encrypt != encrypt_dts) {
@@ -241,7 +259,7 @@ static int key_unify_init(struct aml_uk_dev *ukdev, char *buf,
int auto_attach(struct unifykey_type *uk_type)
{
static int init;
int ret = -1;
int ret;
struct aml_uk_dev *ukdev = get_ukdev();
mutex_lock(&attach_mutex);
@@ -332,7 +350,7 @@ int key_unify_write(struct aml_uk_dev *ukdev, char *name,
case KEY_UNKNOWN_DEV:
default:
pr_err("unknown device for key %s\n", name);
break;
return -EINVAL;
}
return ret;
@@ -378,7 +396,7 @@ int key_unify_read(struct aml_uk_dev *ukdev, char *name,
case KEY_UNKNOWN_DEV:
default:
pr_err("unknown device for key %s\n", name);
break;
return -EINVAL;
}
return ret;
}
@@ -421,7 +439,7 @@ int key_unify_size(struct aml_uk_dev *ukdev, char *name, unsigned int *real)
case KEY_UNKNOWN_DEV:
default:
pr_err("unknown device for key %s\n", name);
break;
return -EINVAL;
}
return ret;
@@ -462,7 +480,7 @@ int key_unify_query(struct aml_uk_dev *ukdev, char *name,
case KEY_UNKNOWN_DEV:
default:
pr_err("unknown device for key %s\n", name);
break;
return -EINVAL;
}
return ret;
}
@@ -542,11 +560,11 @@ static int unifykey_open(struct inode *inode, struct file *file)
{
struct aml_uk_dev *ukdev;
if (lock == 1) {
/* only one open at a time */
if (atomic_xchg(&lock, 1)) {
pr_err("%s: can not operate other key\n", __func__);
return -EPERM;
}
lock = 1;
ukdev = container_of(inode->i_cdev, struct aml_uk_dev, cdev);
file->private_data = ukdev;
@@ -555,7 +573,7 @@ static int unifykey_open(struct inode *inode, struct file *file)
static int unifykey_release(struct inode *inode, struct file *file)
{
lock = 0;
atomic_set(&lock, 0);
return 0;
}
@@ -563,8 +581,9 @@ static loff_t unifykey_llseek(struct file *filp, loff_t off, int whence)
{
struct aml_uk_dev *ukdev;
loff_t newpos;
ukdev = filp->private_data;
if (!ukdev)
return -EINVAL;
switch (whence) {
case 0: /* SEEK_SET (start postion)*/
@@ -577,7 +596,7 @@ static loff_t unifykey_llseek(struct file *filp, loff_t off, int whence)
case 2: /* SEEK_END */
newpos = (loff_t)uk_count_key(&ukdev->uk_hdr) - 1;
newpos = newpos - off;
newpos = newpos + off;
break;
default: /* can't happen */
@@ -605,6 +624,8 @@ static long unifykey_unlocked_ioctl(struct file *file,
int ret;
ukdev = file->private_data;
if (!ukdev)
return -EINVAL;
switch (cmd) {
case KEYUNIFY_ATTACH:
@@ -654,8 +675,7 @@ static long unifykey_unlocked_ioctl(struct file *file,
item->perm = perm;
item->flag = state;
item->id = key->id;
strncpy(item->name, key->name, (KEY_UNIFY_NAME_LEN - 1));
item->name[KEY_UNIFY_NAME_LEN - 1] = '\0';
strscpy(item->name, key->name, KEY_UNIFY_NAME_LEN);
ret = key_unify_size(ukdev, key->name, &item->size);
if (ret != 0) {
pr_err("fail to obtain key size of %s\n", key->name);
@@ -695,24 +715,32 @@ static ssize_t unifykey_read(struct file *file,
loff_t *ppos)
{
struct aml_uk_dev *ukdev;
int ret;
int id;
unsigned int reallen;
struct key_item_t *item;
char *local_buf = NULL;
int ret;
int id;
unsigned int reallen, copy_len;
struct key_item_t *item;
char *local_buf = NULL;
ukdev = file->private_data;
if (!ukdev)
return -EINVAL;
id = (int)(*ppos);
item = uk_find_item_by_id(&ukdev->uk_hdr, id);
if (!item) {
ret = -EINVAL;
goto exit;
if (!item)
return -EINVAL;
if (count == 0)
return -EINVAL;
if (item->dev == KEY_SECURE) {
if (count < SHA256_SUM_LEN)
pr_err("Securekey reads 32-byte hash,but count=%d\n", (int)count);
local_buf = kzalloc(SHA256_SUM_LEN, GFP_KERNEL);
} else {
local_buf = kzalloc(count, GFP_KERNEL);
}
if (item->dev == KEY_SECURE)
count = SHA256_SUM_LEN;
local_buf = kzalloc(count, GFP_KERNEL);
if (!local_buf) {
pr_err("memory not enough,%s:%d\n",
__func__, __LINE__);
@@ -722,14 +750,14 @@ static ssize_t unifykey_read(struct file *file,
ret = key_unify_read(ukdev, item->name, local_buf, count, &reallen);
if (ret < 0)
goto exit;
if (count > reallen)
count = reallen;
if (copy_to_user((void *)buf, (void *)local_buf, count)) {
copy_len = min(count, reallen);
if (copy_to_user((void *)buf, (void *)local_buf, copy_len)) {
ret = -EFAULT;
goto exit;
}
pr_info("%s: name: %s, size %d\n", __func__, item->name, (int)count);
ret = count;
pr_info("%s: name: %s, size %d\n", __func__, item->name, copy_len);
ret = copy_len;
exit:
kfree(local_buf);
return ret;
@@ -746,17 +774,21 @@ static ssize_t unifykey_write(struct file *file,
char *local_buf;
ukdev = file->private_data;
if (!ukdev)
return -EINVAL;
if (count == 0)
return -EINVAL;
id = (int)(*ppos);
item = uk_find_item_by_id(&ukdev->uk_hdr, id);
if (!item)
return -EINVAL;
local_buf = kzalloc(count, GFP_KERNEL);
if (!local_buf)
return -ENOMEM;
id = (int)(*ppos);
item = uk_find_item_by_id(&ukdev->uk_hdr, id);
if (!item) {
ret = -EINVAL;
goto exit;
}
if (copy_from_user(local_buf, buf, count)) {
ret = -EFAULT;
goto exit;
@@ -799,14 +831,18 @@ static ssize_t list_show(const struct class *cla,
ukdev = container_of(cla, struct aml_uk_dev, cls);
key_cnt = uk_count_key(&ukdev->uk_hdr);
n = sprintf(&buf[0], "%d keys installed\n", key_cnt);
n = scnprintf(&buf[0], PAGE_SIZE, "%d keys installed\n", key_cnt);
for (index = 0; index < key_cnt; index++) {
unifykey = uk_find_item_by_id(&ukdev->uk_hdr, index);
if (unifykey)
n += sprintf(&buf[n], "%02d: %s, %s, %x\n",
index, unifykey->name,
keydev[unifykey->dev], unifykey->perm);
if (!unifykey)
continue;
/* one line worst case: index + name + dev + perm <= 73 */
if (n >= PAGE_SIZE - LIST_LINE_MAX)
break;
n += scnprintf(&buf[n], PAGE_SIZE - n, "%02d: %s, %s, %x\n",
index, unifykey->name,
keydev[unifykey->dev], unifykey->perm);
}
buf[n] = 0;
@@ -844,7 +880,7 @@ static ssize_t exist_show(const struct class *cla,
if (keystate > 2)
keystate = 2;
n = sprintf(buf, "%s\n", state[keystate]);
n = scnprintf(buf, PAGE_SIZE, "%s\n", state[keystate]);
buf[n] = 0;
return n;
@@ -881,7 +917,7 @@ static ssize_t secure_show(const struct class *cla,
if (secure > 1)
secure = 1;
_out:
n = sprintf(buf, "%s\n", state[secure]);
n = scnprintf(buf, PAGE_SIZE, "%s\n", state[secure]);
buf[n] = 0;
return n;
@@ -918,7 +954,7 @@ static ssize_t encrypt_show(const struct class *cla,
if (encrypt > 1)
encrypt = 1;
_out:
n = sprintf(buf, "%s\n", state[encrypt]);
n = scnprintf(buf, PAGE_SIZE, "%s\n", state[encrypt]);
buf[n] = 0;
return n;
@@ -970,7 +1006,7 @@ static ssize_t name_show(const struct class *cla,
return 0;
}
n = sprintf(buf, "%s\n", curkey->name);
n = scnprintf(buf, PAGE_SIZE, "%s\n", curkey->name);
buf[n] = 0;
return n;
@@ -990,12 +1026,11 @@ static ssize_t name_store(const struct class *cla,
size_t reval;
ukdev = container_of(cla, struct aml_uk_dev, cls);
curkey = ukdev->curkey;
if (count >= KEY_UNIFY_NAME_LEN)
count = KEY_UNIFY_NAME_LEN - 1;
if (count > KEY_UNIFY_NAME_LEN)
return -EINVAL;
if (count <= 0) {
if (count <= 1) {
pr_err(" count=%zd is invalid in %s\n", count, __func__);
return -EINVAL;
}
@@ -1072,6 +1107,8 @@ static ssize_t read_show(const struct class *cla,
}
if (curkey->dev == KEY_SECURE)
keysize = SHA256_SUM_LEN;
if (keysize > PAGE_SIZE - 1)
keysize = PAGE_SIZE - 1;
pr_err("name: %s, size %d\n", curkey->name, keysize);
keydata = kzalloc(keysize, GFP_KERNEL);
if (!keydata) {
@@ -1104,7 +1141,7 @@ static ssize_t write_store(const struct class *cla,
{
struct aml_uk_dev *ukdev;
struct key_item_t *curkey;
int ret;
int ret = -EINVAL;
unsigned char *keydata = NULL;
size_t key_len = 0;
@@ -1119,8 +1156,10 @@ static ssize_t write_store(const struct class *cla,
if (curkey) {
keydata = kzalloc(count, GFP_KERNEL);
if (!keydata)
goto _out;
if (!keydata) {
ret = -ENOMEM;
return ret;
}
/* check string */
for (key_len = 0; key_len < count; key_len++)
@@ -1142,12 +1181,11 @@ static ssize_t write_store(const struct class *cla,
__func__, __LINE__);
goto _out;
}
ret = count;
}
_out:
kfree(keydata);
keydata = NULL;
return count;
return ret;
}
static ssize_t attach_show(const struct class *cla,
@@ -1159,7 +1197,8 @@ static ssize_t attach_show(const struct class *cla,
/* show attach status. */
ukdev = container_of(cla, struct aml_uk_dev, cls);
n = sprintf(buf, "%s\n", (ukdev->init_flag == 0 ? "no" : "yes"));
n = scnprintf(buf, PAGE_SIZE, "%s\n",
(ukdev->init_flag == 0 ? "no" : "yes"));
buf[n] = 0;
return n;
@@ -1170,9 +1209,12 @@ static ssize_t attach_store(const struct class *cla,
const char *buf, size_t count)
{
struct aml_uk_dev *ukdev;
int ret;
ukdev = container_of(cla, struct aml_uk_dev, cls);
key_unify_init(ukdev, NULL, KEY_UNIFY_NAME_LEN);
ret = key_unify_init(ukdev, NULL, KEY_UNIFY_NAME_LEN);
if (ret < 0)
return ret;
return count;
}
@@ -1271,7 +1313,7 @@ static ssize_t help_show(const struct class *class,
{
ssize_t n = 0;
n = sprintf(buf, "%s", unifykeys_help_str);
n = scnprintf(buf, PAGE_SIZE, "%s", unifykeys_help_str);
buf[n] = 0;
return n;
@@ -1427,6 +1469,8 @@ error3:
error2:
unregister_chrdev_region(ukdev->uk_devno, 1);
error1:
uk_dt_release(pdev);
ukdev_global = NULL;
devm_kfree(&pdev->dev, ukdev);
out:
amlkey_if_deinit();
@@ -1446,6 +1490,7 @@ static void aml_unifykeys_remove(struct platform_device *pdev)
cdev_del(&ukdev->cdev);
class_unregister(&ukdev->cls);
platform_set_drvdata(pdev, NULL);
ukdev_global = NULL;
amlkey_if_deinit();
while (storage_device[i]) {
if (storage_device[i]->unifykey_notifier_list.head)
@@ -14,6 +14,9 @@
#define KEY_UNIFY_NAME_LEN 48
/* one list_show line worst case: "%02d: name, dev, perm\n" + '\0' */
#define LIST_LINE_MAX (KEY_UNIFY_NAME_LEN + 32)
#define aml_unify_debug 0
#define pr_dbg(fmt...)\
do {\
@@ -82,7 +85,7 @@ void *get_ukdev(void);
#ifdef CONFIG_AMLOGIC_UNIFYKEY
int __init aml_unifykeys_init(void);
void __exit aml_unifykeys_exit(void);
void aml_unifykeys_exit(void);
#else
static int __init aml_unifykeys_init(void)
{
@@ -45,14 +45,17 @@ static int uk_item_parse_dt(struct aml_uk_dev *ukdev, struct device_node *node,
goto exit;
}
if (propname) {
if (strcmp(propname, "efuse") == 0)
if (strcmp(propname, "efuse") == 0) {
tmp_item->dev = KEY_EFUSE;
else if (strcmp(propname, "normal") == 0)
} else if (strcmp(propname, "normal") == 0) {
tmp_item->dev = KEY_NORMAL;
else if (strcmp(propname, "secure") == 0)
} else if (strcmp(propname, "secure") == 0) {
tmp_item->dev = KEY_SECURE;
else
} else {
tmp_item->dev = KEY_UNKNOWN_DEV;
ret = -EINVAL;
goto exit;
}
}
tmp_item->perm = 0;
@@ -75,7 +78,7 @@ exit:
static int uk_item_create(struct platform_device *pdev, int *num)
{
int ret = -1;
int ret;
int index;
struct device_node *child;
struct device_node *np = pdev->dev.of_node;
@@ -121,10 +124,18 @@ int uk_dt_release(struct platform_device *pdev)
struct key_item_t *item;
struct key_item_t *tmp;
if (!ukdev)
return 0;
if (pdev->dev.of_node)
of_node_put(pdev->dev.of_node);
/*
* list_for_each_entry_safe can guarantee item is not null.
*/
/* coverity[NULL_FIELD:SUPPRESS] */
list_for_each_entry_safe(item, tmp, &ukdev->uk_hdr, node) {
/* coverity[NULL_FIELD:SUPPRESS] */
list_del(&item->node);
kfree(item);
}