| #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; |
| } |
| |