289 lines
6.0 KiB
C
289 lines
6.0 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
||
/*
|
||
* drivers/storagekey/storagekey.c
|
||
*
|
||
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
||
*
|
||
*/
|
||
|
||
/* extern from bl31 */
|
||
/*
|
||
* when RET_OK
|
||
* query: retval=1: key exsit,=0: key not exsit;
|
||
* tell: retvak = key size
|
||
* status: retval=1: secure, retval=0: non-secure
|
||
|
||
*/
|
||
|
||
#include <common.h>
|
||
#include <linux/types.h>
|
||
#include <amlogic/secure_storage.h>
|
||
#include <amlogic/storage_if.h>
|
||
#include <amlogic/amlkey_if.h>
|
||
#ifdef CONFIG_STORE_COMPATIBLE
|
||
#include <partition_table.h>
|
||
#endif
|
||
|
||
/* key buffer status */
|
||
/* bit0, dirty flag*/
|
||
#define KEYBUFFER_CLEAN (0 << 0)
|
||
#define KEYBUFFER_DIRTY (1 << 0)
|
||
#define SECUESTORAGE_HEAD_SIZE (256)
|
||
#define SECUESTORAGE_WHOLE_SIZE (0x40000)
|
||
|
||
struct storagekey_info_t {
|
||
uint8_t * buffer;
|
||
uint32_t size;
|
||
uint32_t status;
|
||
};
|
||
|
||
static struct storagekey_info_t storagekey_info = {
|
||
.buffer = NULL,
|
||
/* default size */
|
||
.size = SECUESTORAGE_WHOLE_SIZE,
|
||
.status = KEYBUFFER_CLEAN,
|
||
};
|
||
|
||
/**
|
||
*1.init
|
||
* return ok 0, fail 1
|
||
*/
|
||
int32_t amlkey_init(uint8_t *seed, uint32_t len, int encrypt_type)
|
||
{
|
||
int32_t ret = 0;
|
||
uint32_t buffer_size, actual_size;
|
||
|
||
/* do nothing for now*/
|
||
printf("%s() enter!\n", __func__);
|
||
if (storagekey_info.buffer != NULL) {
|
||
printf("%s() %d: already init!\n", __func__, __LINE__);
|
||
goto _out;
|
||
}
|
||
|
||
/* get buffer from bl31 */
|
||
storagekey_info.buffer = secure_storage_getbuffer(&buffer_size);
|
||
if (storagekey_info.buffer == NULL) {
|
||
printf("%s() %d: can't get buffer from bl31!\n",
|
||
__func__, __LINE__);
|
||
ret = -1;
|
||
goto _out;
|
||
}
|
||
|
||
if (encrypt_type == -1)
|
||
encrypt_type = 0;
|
||
secure_storage_set_enctype(encrypt_type);
|
||
|
||
/* full fill key infos from storage. */
|
||
ret = store_key_read(storagekey_info.buffer,
|
||
storagekey_info.size,
|
||
&actual_size);
|
||
if (ret) {
|
||
/* memset head info for bl31 */
|
||
memset(storagekey_info.buffer, 0, SECUESTORAGE_HEAD_SIZE);
|
||
ret = 0;
|
||
goto _out;
|
||
}
|
||
|
||
storagekey_info.size = actual_size;
|
||
secure_storage_notifier_ex(actual_size, 0);
|
||
|
||
storagekey_info.buffer = secure_storage_getbuffer(&buffer_size);
|
||
if (buffer_size != actual_size) {
|
||
ret = -1;
|
||
goto _out;
|
||
}
|
||
|
||
#ifdef CONFIG_STORE_COMPATIBLE
|
||
info_disprotect &= ~DISPROTECT_KEY; //protect
|
||
#endif
|
||
_out:
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
*2. query if the key already programmed
|
||
* return: exsit 1, non 0
|
||
*/
|
||
int32_t amlkey_isexsit(const uint8_t * name)
|
||
{
|
||
int32_t ret = 0;
|
||
uint32_t retval;
|
||
|
||
if ( NULL == name ) {
|
||
printf("%s() %d, invalid key ", __func__, __LINE__);
|
||
return 0;
|
||
}
|
||
|
||
ret = secure_storage_query((uint8_t *)name, &retval);
|
||
if (ret) {
|
||
printf("%s() %d: ret %d\n", __func__, __LINE__, ret);
|
||
retval = 0;
|
||
}
|
||
|
||
return (int32_t)retval;
|
||
}
|
||
|
||
static int32_t amlkey_get_attr(const uint8_t * name)
|
||
{
|
||
int32_t ret = 0;
|
||
uint32_t retval;
|
||
|
||
if ( NULL == name ) {
|
||
printf("%s() %d, invalid key ", __func__, __LINE__);
|
||
return 0;
|
||
}
|
||
|
||
ret = secure_storage_status((uint8_t *)name, &retval);
|
||
if (ret) {
|
||
printf("%s() %d: ret %d\n", __func__, __LINE__, ret);
|
||
retval = 0;
|
||
}
|
||
|
||
return (int32_t)(retval);
|
||
}
|
||
|
||
/**
|
||
* 3.1 query if the programmed key is secure. key must exsit!
|
||
* return secure 1, non 0;
|
||
*/
|
||
int32_t amlkey_issecure(const uint8_t * name)
|
||
{
|
||
return (amlkey_get_attr(name)&UNIFYKEY_ATTR_SECURE_MASK);
|
||
}
|
||
|
||
/**
|
||
* 3.2 query if the programmed key is encrypt
|
||
* return encrypt 1, non-encrypt 0;
|
||
*/
|
||
int32_t amlkey_isencrypt(const uint8_t * name)
|
||
{
|
||
return (amlkey_get_attr(name)&UNIFYKEY_ATTR_ENCRYPT_MASK);
|
||
}
|
||
/**
|
||
* 4. actual bytes of key value
|
||
* return actual size.
|
||
*/
|
||
ssize_t amlkey_size(const uint8_t *name)
|
||
{
|
||
ssize_t size = 0;
|
||
int32_t ret = 0;
|
||
uint32_t retval;
|
||
|
||
if ( NULL == name ) {
|
||
printf("%s() %d, invalid key ", __func__, __LINE__);
|
||
return 0;
|
||
}
|
||
|
||
ret = secure_storage_tell((uint8_t *)name, &retval);
|
||
if (ret) {
|
||
printf("%s() %d: ret %d\n", __func__, __LINE__, ret);
|
||
retval = 0;
|
||
}
|
||
size = (ssize_t)retval;
|
||
return size;
|
||
}
|
||
|
||
/**
|
||
*5. read non-secure key in bytes, return bytes readback actually.
|
||
* return actual size read back.
|
||
*/
|
||
ssize_t amlkey_read(const uint8_t *name, uint8_t *buffer, uint32_t len)
|
||
{
|
||
int32_t ret = 0;
|
||
ssize_t retval = 0;
|
||
uint32_t actual_len;
|
||
|
||
if ( NULL == name ) {
|
||
printf("%s() %d, invalid key ", __func__, __LINE__);
|
||
return 0;
|
||
}
|
||
ret = secure_storage_read((uint8_t *)name, buffer, len, &actual_len);
|
||
if (ret) {
|
||
printf("%s() %d: return %d\n", __func__, __LINE__, ret);
|
||
retval = 0;
|
||
goto _out;
|
||
}
|
||
retval = actual_len;
|
||
_out:
|
||
return retval;
|
||
}
|
||
|
||
/**
|
||
* 6.write secure/non-secure key in bytes , return bytes readback actually
|
||
* attr: bit0, secure/non-secure;
|
||
* bit8, encrypt/non-encrypt;
|
||
* return actual size write down.
|
||
*/
|
||
ssize_t amlkey_write(const uint8_t *name, uint8_t *buffer, uint32_t len, uint32_t attr)
|
||
{
|
||
int32_t ret = 0;
|
||
ssize_t retval = 0;
|
||
uint32_t actual_size;
|
||
|
||
if ( NULL == name ) {
|
||
printf("%s() %d, invalid key ", __func__, __LINE__);
|
||
return retval;
|
||
}
|
||
ret = secure_storage_write((uint8_t *)name, buffer, len, attr);
|
||
if (ret) {
|
||
printf("%s() %d: return %d\n", __func__, __LINE__, ret);
|
||
retval = 0;
|
||
goto _out;
|
||
} else {
|
||
retval = (ssize_t)len;
|
||
/* write down! */
|
||
if (storagekey_info.buffer != NULL) {
|
||
ret = store_key_write(storagekey_info.buffer,
|
||
storagekey_info.size,
|
||
&actual_size);
|
||
if (ret) {
|
||
printf("%s() %d, store_key_write fail\n",
|
||
__func__, __LINE__);
|
||
retval = 0;
|
||
}
|
||
}
|
||
}
|
||
_out:
|
||
return retval;
|
||
}
|
||
/**
|
||
* 7. get the hash value of programmed secure key | 32bytes length, sha256
|
||
* return success 0, fail -1
|
||
*/
|
||
int32_t amlkey_hash_4_secure(const uint8_t * name, uint8_t * hash)
|
||
{
|
||
int32_t ret = 0;
|
||
|
||
ret = secure_storage_verify((uint8_t *)name, hash);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* 7. del key by name
|
||
* return success 0, fail -1
|
||
*/
|
||
int32_t amlkey_del(const uint8_t * name)
|
||
{
|
||
int32_t ret = 0;
|
||
uint32_t actual_size;
|
||
|
||
ret = secure_storage_remove((uint8_t *)name);
|
||
if ((ret == 0) && (storagekey_info.buffer != NULL)) {
|
||
/* flush back */
|
||
ret = store_key_write(storagekey_info.buffer,
|
||
storagekey_info.size,
|
||
&actual_size);
|
||
if (ret) {
|
||
printf("%s() %d, store_key_write fail\n",
|
||
__func__, __LINE__);
|
||
}
|
||
} else {
|
||
printf("%s() %d, remove key fail\n",
|
||
__func__, __LINE__);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|