blob: 8ded7faa36181006edea633793f4efc4bf1fbf60 [file] [log] [blame]
#include "key_manage_i.h"
#include <fdt.h>
#include <libfdt.h>
#define UNIFYKEY_DATAFORMAT_HEXDATA "hexdata"
#define UNIFYKEY_DATAFORMAT_HEXASCII "hexascii"
#define UNIFYKEY_DATAFORMAT_ALLASCII "allascii"
#define UNIFYKEY_DEVICE_EFUSEKEY "efuse"
#define UNIFYKEY_DEVICE_NORMAL "normal"
#define UNIFYKEY_DEVICE_SECURESKEY "secure"
#define UNIFYKEY_PERMIT_READ "read"
#define UNIFYKEY_PERMIT_WRITE "write"
#define UNIFYKEY_PERMIT_DEL "del"
static struct key_info_t unify_key_info={.key_num =0, .key_flag = 0, .efuse_version = -1, .encrypt_type = 0};
static struct key_item_t *unifykey_item=NULL;
static int unifykey_item_verify_check(struct key_item_t *key_item)
{
if (!key_item) {
KM_ERR("unify key item is invalid\n");
return -1;
}
if (!key_item->name || (key_item->dev == KEY_M_UNKNOW_DEV) ||(key_item->datFmt == KEY_M_MAX_DF)) {
KM_ERR("unify key item is invalid\n");
return -1;
}
return 0;
}
static struct key_item_t *unifykey_find_item_by_name(const char *name)
{
struct key_item_t *pre_item;
int i = 0;
const unsigned cnt = unify_key_info.key_num;
for (pre_item = unifykey_item; i < cnt; ++pre_item, ++i)
{
if (!strcmp(pre_item->name,name)) {
return pre_item;
}
}
return NULL;
}
enum key_manager_df_e keymanage_dts_get_key_fmt(const char *keyname)
{
struct key_item_t *key_manage;
enum key_manager_df_e keyValFmt = KEY_M_MAX_DF;
if (!unify_key_info.key_flag) {
KM_ERR("/unify not parsed yet!\n");
return KEY_M_MAX_DF;
}
key_manage = unifykey_find_item_by_name(keyname);
if (key_manage == NULL) {
KM_ERR ("%s key name is not exist\n", keyname) ;
return keyValFmt;
}
if (unifykey_item_verify_check(key_manage)) {
KM_ERR ("%s key name is invalid\n", keyname) ;
return keyValFmt;
}
keyValFmt = key_manage->datFmt;
return keyValFmt;
}
//which device does the key stored in
enum key_manager_dev_e keymanage_dts_get_key_device(const char *keyname)
{
struct key_item_t *key_manage;
if (!unify_key_info.key_flag) {
KM_ERR("/unify not parsed yet!\n");
return KEY_M_MAX_DEV;
}
key_manage = unifykey_find_item_by_name(keyname);
if (key_manage == NULL) {
KM_ERR("%s key name is not exist\n",keyname);
return KEY_M_MAX_DEV;
}
if (unifykey_item_verify_check(key_manage)) {
KM_ERR("%s key name is invalid\n",keyname);
return KEY_M_MAX_DEV;
}
return key_manage->dev;
}
const char* keymanage_dts_get_enc_type(const char* keyname)
{
struct key_item_t *key_manage;
if (!unify_key_info.key_flag) {
KM_ERR("/unify not parsed yet!\n");
return NULL;
}
key_manage = unifykey_find_item_by_name(keyname);
if (key_manage == NULL) {
KM_ERR("%s key name is not exist\n",keyname);
return NULL;
}
return key_manage->encType;
}
const char* keymanage_dts_get_key_type(const char* keyname)
{
struct key_item_t *key_manage;
if (!unify_key_info.key_flag) {
KM_ERR("/unify not parsed yet!\n");
return NULL;
}
key_manage = unifykey_find_item_by_name(keyname);
if (key_manage == NULL) {
KM_ERR("%s key name is not exist\n",keyname);
return NULL;
}
return key_manage->keyType;
}
char unifykey_get_efuse_version(void)
{
char ver=0;
if (!unify_key_info.key_flag) {
KM_ERR("/unify not parsed yet!\n");
return 0;
}
if (unify_key_info.efuse_version != -1) {
ver = (char)unify_key_info.efuse_version;
}
return ver;
}
int unifykey_get_encrypt_type(void)
{
return unify_key_info.encrypt_type;
}
static int unifykey_item_dt_parse(const void* dt_addr,int nodeoffset,int id,char *item_path)
{
struct key_item_t *temp_item=NULL;
char *propdata;
struct fdt_property *prop;
int count;
temp_item = unifykey_item + id;
propdata = (char*)fdt_getprop(dt_addr, nodeoffset, "key-encrypt", NULL);
if (propdata) {
count = strlen(propdata);
if ( count > KEY_UNIFY_TYPE_LEN_MAX ) {
KM_ERR("key-encrypt [%s] too long\n", propdata);
return __LINE__;
}
memcpy(temp_item->encType, propdata, count);
}
propdata = (char*)fdt_getprop(dt_addr, nodeoffset, "key-name",NULL);
if (!propdata) {
printf("%s get key-name fail,%s:%d\n",item_path,__func__,__LINE__);
return __LINE__;
}
count = strlen(propdata);
if (count >= KEY_UNIFY_NAME_LEN) {
KM_ERR("key-name strlen (%d) > max(%d) at key_%d\n", count, KEY_UNIFY_NAME_LEN - 1, id);
return __LINE__;
}
memcpy(temp_item->name, propdata, count);
temp_item->name[count] = 0;
propdata = (char*)fdt_getprop(dt_addr, nodeoffset, "key-device",NULL);
if (!propdata) {
KM_ERR("%s get key-device fail at key_%d\n",item_path, id);
return __LINE__;
}
if (strcmp(propdata,UNIFYKEY_DEVICE_EFUSEKEY) == 0) {
temp_item->dev = KEY_M_EFUSE_NORMAL;
}
else if(strcmp(propdata,UNIFYKEY_DEVICE_SECURESKEY) == 0){
temp_item->dev = KEY_M_SECURE_KEY;
}
else if(strcmp(propdata,UNIFYKEY_DEVICE_NORMAL) == 0){
temp_item->dev = KEY_M_NORAML_KEY;
}
else{
KM_ERR("key-device %s is unknown at key_%d\n", propdata, id);
return __LINE__;
}
propdata = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "key-type",NULL);
if (!propdata) //prop 'key-type' not configured, default to raw except special names
{
strcpy(temp_item->keyType, "raw");
}
else
{
const int keyTypeLen = strlen(propdata);
if (keyTypeLen > KEY_UNIFY_TYPE_LEN_MAX) {
KM_ERR("key[%s]cfg key-type[%s] sz %d > max %d\n", temp_item->name, propdata, keyTypeLen, KEY_UNIFY_TYPE_LEN_MAX);
return __LINE__;
}
strcpy(temp_item->keyType, propdata);
}
#if 0
propdata = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "key-dataformat",NULL);
if (!propdata) {
KM_ERR("%s get key-dataformat fail at key_%d\n",item_path, id);
return __LINE__;
}
#endif
prop = (struct fdt_property*)fdt_get_property((const void *)dt_addr,nodeoffset,"key-permit",NULL) ;
if (!prop) {
KM_ERR("%s get key-permit fail at key_%d\n",item_path, id);
return __LINE__;
}
temp_item->permit = 0;
const int propLen = prop->len > 512 ? strnlen(prop->data, 512) : prop->len;
if (fdt_stringlist_contains(prop->data, propLen, UNIFYKEY_PERMIT_READ)) {
temp_item->permit |= KEY_M_PERMIT_READ;
}
if (fdt_stringlist_contains(prop->data, propLen, UNIFYKEY_PERMIT_WRITE)) {
temp_item->permit |= KEY_M_PERMIT_WRITE;
}
if (fdt_stringlist_contains(prop->data, propLen, UNIFYKEY_PERMIT_DEL)) {
temp_item->permit |= KEY_M_PERMIT_DEL;
}
temp_item->id = id;
KM_DBG("key[%02d] keyname %s, %d\n", id, temp_item->name, temp_item->dev);
return 0;
}
static int unifykey_item_create(const void* dt_addr,int num)
{
int ret = 0;
int i,nodeoffset;
char item_path[100];
for (i=0;i<num;i++)
{
sprintf(item_path, "/unifykey/key_%d", i);
nodeoffset = fdt_path_offset (dt_addr, item_path) ;
if (nodeoffset < 0) {
KM_ERR(" dts: not find node %s.\n",fdt_strerror(nodeoffset));
return __LINE__;
}
ret = unifykey_item_dt_parse(dt_addr,nodeoffset, i, item_path);
if (ret) {
KM_ERR("Fail at parse %s\n", item_path);
return __LINE__;
}
}
// printf("unifykey-num fact is %x\n",count);
return 0;
}
//parse and cache the dts cfg
//TODO: check keys names has no duplicated
int keymanage_dts_parse(const void* dt_addr)
{
int ret = 0;
int nodeoffset;
char *punifykey_num, *encrypt_type;
if (fdt_check_header(dt_addr)!= 0) {
KM_ERR("not a fdt at 0x%p\n", dt_addr);
return __LINE__;
}
nodeoffset = fdt_path_offset(dt_addr, "/unifykey");
if (nodeoffset < 0) {
KM_ERR("dts: err(%s) in find /unifykey.\n",fdt_strerror(nodeoffset));
return __LINE__;
}
unify_key_info.efuse_version = -1;
punifykey_num = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "efuse-version",NULL);
if (punifykey_num) {
unify_key_info.efuse_version = be32_to_cpup((unsigned int*)punifykey_num);
KM_MSG("efuse-version config is %x\n",unify_key_info.efuse_version);
}
unify_key_info.key_num = 0;
punifykey_num = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "unifykey-num",NULL);
if (punifykey_num) {
// printf("unifykey-num config is %x\n",be32_to_cpup((unsigned int*)punifykey_num));
unify_key_info.key_num = be32_to_cpup((unsigned int*)punifykey_num);
}
unify_key_info.encrypt_type = -1;
encrypt_type = (char*)fdt_getprop((const void *)dt_addr, nodeoffset, "unifykey-encrypt",NULL);
if (encrypt_type) {
unify_key_info.encrypt_type = be32_to_cpup((unsigned int*)encrypt_type);
}
if (unify_key_info.key_num <= 0) {
KM_ERR("unifykey-num is not configured\n");
return __LINE__;
}
if (unify_key_info.key_num > 32) {
KM_ERR("Cfg key_num is %d > 32,pls check!\n", unify_key_info.key_num);
return __LINE__;
}
if (unifykey_item) {
free(unifykey_item);
}
const unsigned keyInfBufLen = unify_key_info.key_num * sizeof(struct key_item_t);
unifykey_item = (struct key_item_t*)malloc(keyInfBufLen);
memset(unifykey_item, 0 , keyInfBufLen);
ret = unifykey_item_create(dt_addr,unify_key_info.key_num);
unify_key_info.key_flag = ret ? 0 : 1;
return ret;
}