security_huks模块下hks_rkc.c代码评注第三部分
本篇概述
本篇接着
继续讲述有关hks_rkc.c代码中关于根密钥组件相关操作的内容。本篇将重点讲解密钥库文件的检查操作、密钥库文件中材料的生成相关操作和方法。
代码结构
hks_rkc.c
├── check
│ └── hks_rkc_chk_ksf
│ └── hks_rkc_chk_all_ksf
├── material
│ └── hks_rkc_get_fixed_material
│ └── hks_rkc_calc_material
│ └── hks_rkc_make_random_material
密钥库文件审查
1. hks_rkc_chk_ksf
-
函数功能:检查一个密钥库文件
root key component - check keystore file. -
参数说明:密钥库文件名、返回值(状态量)、密钥库文件数据、有效的密钥库文件数据
parameter:
ksf_name - [in] - ksf name.
rc - [in] - return code.
ksf_data - [in] - ksf data. 实际地址ksf_name下存放的数据
valid_ksf_data - [in] - valid ksf data. 系统记录中的有效ksf_data -
返回值:成功或错误代码
return value:
success or error code
详细代码与评注如下:
static int32_t hks_rkc_chk_ksf(const char *ksf_name, int32_t rc,
const struct hks_rkc_ksf_data *ksf_data,
const struct hks_rkc_ksf_data *valid_ksf_data)
{
if ((rc != HKS_STATUS_OK) ||
memcmp(valid_ksf_data, ksf_data, HKS_RKC_KSF_DATA_SIZE)) { //memcmp函数的原型为 int memcmp(const void *str1, const void *str2, size_t n));其功能是把存储区 str1 和存储区 str2 的前 n 个字节进行比较。该函数是按字节比较的,位于string.h
/*
* If this ksf is different from the first valid ksf,
* try to overwrite it by the first valid ksf.
*/
//如果这个ksf与第一个有效的ksf不同,请尝试用第一个有效的ksf覆盖它
log_error("repair ksf[%s]", ksf_name);
//将valid_ksf_data中的数据写入名为ksf_name的地址下
return hks_rkc_write_ksf(ksf_name, valid_ksf_data);
}
return HKS_STATUS_OK;
}
2. hks_rkc_chk_all_ksf
-
函数功能:检查所有的密钥库文件
root key component - check all keystore files. -
参数说明:所有密钥库文件的返回值、所有密钥库文件的数据、有效密钥库文件数据、有效密钥库文件索引
parameter:
all_ksf_rc - [in] - all reture code.
all_ksf_data - [in] - all data. 实际上的密钥库文件数据
valid_ksf_data - [in] - the first valid data. 记录中有效密钥库文件数据
valid_ksf_index - [in] - the index of first valid data. -
返回值:成功或错误代码
return value:
success or error code
检查所有密钥库文件是建立在检查单个密钥库文件的基础上进行完成的,因此该部分函数中有对hks_rkc_chk_ksf函数的调用。详细代码与评注如下:
static int32_t hks_rkc_chk_all_ksf(const int32_t *all_ksf_rc,
const struct hks_rkc_ksf_data *all_ksf_data,
const struct hks_rkc_ksf_data *valid_ksf_data, uint32_t valid_ksf_index)
{
//检查密钥库文件数是否满足预定义要求
if (g_hks_rkc_cfg.ksf_attr.num > HKS_RKC_KSF_NUM) {
log_error("invalid ksf num=%u", g_hks_rkc_cfg.ksf_attr.num);
return HKS_ERROR_INTERNAL_UNKOWN;
}
uint32_t i = 0;
for (; i < g_hks_rkc_cfg.ksf_attr.num; ++i) {
if (i == valid_ksf_index)
continue;
if (g_hks_rkc_cfg.ksf_attr.name[i] == NULL)
continue;
/*循环检查密钥库文件,检查地址(名)由根密钥组件配置提供,
将检查返回值存入all_ksf_rc中、数据按照索引存入all_ksf_data并且跟valid_ksf_data进行对比,
对比结果返回到rc中*/
int32_t rc = hks_rkc_chk_ksf(g_hks_rkc_cfg.ksf_attr.name[i],
all_ksf_rc[i], all_ksf_data + i, valid_ksf_data);
if (rc != HKS_STATUS_OK) {
log_error("check ksf fail,i=%u,rc=%d", i, rc);
continue;
}
}
return HKS_STATUS_OK;
}
密钥库材料的生成
1. hks_rkc_get_fixed_material
-
函数功能:获得修复材料(材料的重置)
root key component - get fixed material -
参数说明:输出:修复后的材料;输入:材料的长度
parameter:
material - [out] - fixed material.
len - [in] - the length of material, it should be 32 bytes. -
返回值:成功或错误代码
return value:
success or error code
获得根密钥组件得修复材料实质上就是对源材料的重置,改代码并没有采用随机化的方法,而是通过直接定义(赋值)来完成的重置工作。详细代码如下:
static int32_t hks_rkc_get_fixed_material(uint8_t *material, uint32_t len)
{
//定义修复后的材料数组fixed_material[],相当于一种重置
const uint8_t fixed_material[HKS_RKC_MATERIAL_LEN] = {
0xB2, 0xA1, 0x0C, 0x73, 0x52, 0x73, 0x76, 0xA1,
0x60, 0x62, 0x2E, 0x08, 0x52, 0x08, 0x2E, 0xA9,
0x60, 0xBC, 0x2E, 0x73, 0x52, 0x0B, 0x0C, 0xBC,
0xEE, 0x0A, 0x2E, 0x08, 0x52, 0x9C, 0x76, 0xA9
};
//将fixed_material地址下的内容安全复制到material中
int32_t rc = memcpy_s(material, len, fixed_material,
HKS_RKC_MATERIAL_LEN);
if (rc != HKS_STATUS_OK)
return HKS_ERROR_INTERNAL_UNKOWN;
return rc;
}
该部分需要注意的一点是函数memcpy_s的调用,它的功能是fixed_material地址下的内容安全复制到material中,详细的函数定义及使用方法详见:memcpy_s与wmemcpy_s函数的理解。
2. hks_rkc_calc_material
-
函数功能:创建随机材料
root key component - make random material -
参数说明:第一个随机数、第一个随机数的长度、第二个随机数、第二个随机数的长度、密钥库文件数据
parameter:
random1 - [in] - the first random number.
random1_len - [in] - the length of first random number.
random2 - [in] - the second random number.
random2_len - [in] - the length of second random number.
ksf_data - [in,out] - the data of keystore file. -
返回值:成功或错误代码
return value:
success or error code
与上个函数不同的是,hks_rkc_calc_material是利用随机数结合哈希算法SHA256创建随机材料,详细的代码及评注如下:
static int32_t hks_rkc_calc_material(const uint8_t *random1, uint32_t random1_len,
const uint8_t *random2, uint32_t random2_len,
struct hks_rkc_ksf_data *ksf_data)
{
//两种材料的序列号分别定义为1和2
/* two material sequence number */
uint8_t material_sn[HKS_RKC_MATERIAL_NUM] = {
HKS_RKC_MATERIAL1_SN, HKS_RKC_MATERIAL2_SN
};
//hash源的个数,此处定为3
/* hash source number */
uint32_t hash_src_num = HKS_RKC_MATERIAL_HASH_SRC_NUM_NO_E;
//根密钥组件材料的hash源定义,定义了4个
/* hash source */
struct hks_blob hash_src[HKS_RKC_MATERIAL_HASH_SRC_NUM] = {
{ 0, NULL, 0 }, { 0, NULL, 0 }, { 0, NULL, 0 }, { 0, NULL, 0 }
};
//hash结果定义,根密钥组件数=hash结果数
/* hash result */
struct hks_blob hash_result[HKS_RKC_MATERIAL_NUM] = {
{ 0, NULL, 0 }, { 0, NULL, 0 }
};
/* 计算材料
* calculate material
* material1: SHA256(0x1 + R1 + R2 + E) 材料一使用的SHA256算法规则
* material2: SHA256(0x2 + R1 + R2 + E) 材料一使用的SHA256算法规则
*/
//hash源的初始化
hash_src[HKS_RKC_MATERIAL_HASH_SRC_R1].data = random1;
hash_src[HKS_RKC_MATERIAL_HASH_SRC_R1].size = random1_len;
hash_src[HKS_RKC_MATERIAL_HASH_SRC_R2].data = random2;
hash_src[HKS_RKC_MATERIAL_HASH_SRC_R2].size = random2_len;
//熵是可选择的
/* the entropy is optional. */
if (g_hks_rkc_cfg.entropy != NULL) {
hash_src_num = HKS_RKC_MATERIAL_HASH_SRC_NUM;
//HKS_RKC_MATERIAL_HASH_SRC_E 是熵的索引(3)
hash_src[HKS_RKC_MATERIAL_HASH_SRC_E].data =
g_hks_rkc_cfg.entropy;
hash_src[HKS_RKC_MATERIAL_HASH_SRC_E].size =
g_hks_rkc_cfg.entropy_len;
}
//两种材料将作为散列结果输出,此处为hash_result赋ksf_data中主密钥材料的原值
/* Two material would be ouput as hash result. */
hash_result[HKS_RKC_HASH_RESULT_MATERIAL1].data =
ksf_data->rk_material1;
hash_result[HKS_RKC_HASH_RESULT_MATERIAL1].size =
HKS_RKC_MATERIAL_LEN;
hash_result[HKS_RKC_HASH_RESULT_MATERIAL2].data =
ksf_data->rk_material2;
hash_result[HKS_RKC_HASH_RESULT_MATERIAL2].size =
HKS_RKC_MATERIAL_LEN;
//用SHA256(Secure Hash Algorithm 256)来生成两种材料
/* generate two material by SHA256 */
int32_t rc;
uint32_t i = 0;
for (; i < HKS_RKC_MATERIAL_NUM; ++i) { //两次循环调用hks_calc_sha256,生成两个密钥材料存入hash_result中
hash_src[HKS_RKC_MATERIAL_HASH_SRC_SN].data = &(material_sn[i]);
hash_src[HKS_RKC_MATERIAL_HASH_SRC_SN].size = sizeof(uint8_t);
rc = hks_calc_sha256(hash_src, hash_src_num, &(hash_result[i]));
if (rc != HKS_STATUS_OK) {
log_error("calc hash fail,rc=%d,i=%u", rc, i);
return rc;
}
}
return rc;
}
本部分的关键在调用了hks_calc_sha256,该函数利用SHA256算法能够将hash源生成我们想要的hash散列值,其中调用了mbedlts库中有关SHA-256算法组件,有关mbedlts组件的介绍详见:单向散列算法的配置与使用。
3. hks_rkc_make_random_material
-
函数功能:创建随机材料,调用函数hks_rkc_calc_material
root key component - make random material -
参数说明:密钥库文件数据
parameter:
ksf_data - [in,out] - the data of keystore file. -
返回值:成功或失败代码
return value:
success or error code
该部分函数较hks_rkc_calc_material的区别是传入参数中没有随机数,随机数需要调用hks_gen_random生成,而创建随机材料的方法则是通过调用hks_rkc_calc_material函数。详细代码及评注如下:
static int32_t hks_rkc_make_random_material(struct hks_rkc_ksf_data *ksf_data)
{
//定义两个随机变量
/* two random number */
uint8_t random1[HKS_RKC_MATERIAL_LEN] = {0};
uint8_t random2[HKS_RKC_MATERIAL_LEN] = {0};
int32_t rc;
do {
//生成两个随机数分别存入random1、random2
/* Generate 32*2 random number: R1 + R2 */
rc = hks_gen_random(random1, HKS_RKC_MATERIAL_LEN);
if (rc != HKS_STATUS_OK) {
log_error("generate random1 fail,rc=%d", rc);
break;
}
rc = hks_gen_random(random2, HKS_RKC_MATERIAL_LEN);
if (rc != HKS_STATUS_OK) {
log_error("generate random2 fail,rc=%d", rc);
break;
}
//计算材料,将材料结果存入ksf_data中
/* calculate material */
rc = hks_rkc_calc_material(random1, HKS_RKC_MATERIAL_LEN,
random2,
HKS_RKC_MATERIAL_LEN, ksf_data);
if (rc != HKS_STATUS_OK)
break;
} while (0);
//随机数变量需要被释放空间,以确保安全
/* the random number should be cleared after use */
(void)memset_s(random1, sizeof(random1), 0, sizeof(random1));
(void)memset_s(random2, sizeof(random2), 0, sizeof(random2));
return rc;
}
本篇小结
本篇主要讲解密钥库文件的检查操作、密钥库文件中材料的生成相关操作和方法,往后会继续更新hks_rkc.c中更多函数及函数定义方法、内容及操作,敬请期待。