Files

289 lines
6.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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;
}