security_huks模块下hks_rkc.c代码评注第一部分
本篇综述
hks_rkc.c中主要包含了对密钥库文件操作的各项函数定义,结合hks_rkc.h我们能详细了解根密钥组件在密钥系统当中是如何工作并发挥效能的。本篇是hks_rkc.c代码评注的第一部分,主要讲解在hks_rkc.c中变量定义与初始化、密钥库文件缓冲区填写的相关操作、以及密钥库文件的写入方法。
变量定义与初始化
-
引入头文件
在后序函数的定义中会用到下述头文件当中定义的各类函数及变量,再次列写出头文件代码:#ifndef _CUT_AUTHENTICATE_ #include "hks_rkc.h" #include <mbedtls/pkcs5.h> #include "securec.h" #include "common/hks_common.h" #include "common/hks_log_utils.h" #include "common/hks_mem.h" #include "hks_errno.h" #include "hks_file.h"
-
关键结构体变量
下面两个结构体变量g_hks_rkc_cfg 和 g_hks_rkc_def_init_para 的初始化分别对应了结构体hks_rkc_cfg 和 结构体hks_rkc_init_para,这两个结构体分别是存储根密钥组件配置和存储根密钥组件初始化参数的,两个结构体的定义在hks_rkc.h中,我将它们抄录在此:/* 定义结构体:根密钥组件的配置 */ /* the configuration of root key component */ struct hks_rkc_cfg { /* system state 系统状态 */ uint8_t state; /* the version of root key component 根密钥组件版本 */ uint16_t version; /* the storage type of root key component 根密钥组件的存储类型 */ uint8_t storage_type; /* the created time of rook key 根密钥的建立时间 */ struct hks_time rk_created_time; //hks_time结构体类型从年精确到秒 /* the expired time of rook key 根密钥的过期时间 */ struct hks_time rk_expired_time; /* the attribute of keystore file 密钥库文件的属性 */ struct hks_rkc_ksf_attr ksf_attr; /* the iterator number of times which derive Root Master Key 派生根主密钥(键)的迭代次数 */ uint32_t rmk_iter; /* the hash algorithm which derive Root Master Key 派生根主密钥(键)使用的hash算法 */ uint32_t rmk_hash_alg; /* external entropy 外熵 */ uint8_t *entropy; /* the length external entropy 外熵的长度 */ uint32_t entropy_len; /* the mask of master key 主密钥(键)掩码*/ uint8_t mk_mask[HKS_RKC_MK_LEN]; /* the encrption algorithm of master key 主密钥的加密算法 */ uint32_t mk_encrypt_alg; /* the hash algorithm for key-encrypting key 密钥加密密钥的哈希算法 */ uint32_t kek_hash_alg; /* the iterator number for key-encrypting key 密钥加密密钥的迭代次数*/ uint32_t kek_iter; /* reserve data, 32 byte 保留数据,32个字节*/ uint8_t reserve[HKS_RKC_CFG_RSV_LEN]; }; /* 定义结构体:根密钥组件的初始化参数 */ /* the initialization parameter of root key component */ struct hks_rkc_init_para { /* the version of root key component 根密钥组件版本 */ uint16_t version; /* the storage type of root key component 根密钥组件的存储类型 */ uint8_t storage_type; /* the attribute of keystore file 密钥库文件的属性 */ struct hks_rkc_ksf_attr ksf_attr; /* the iterator number of times which derive Root Master Key 派生根主密钥(键)的迭代次数 */ uint32_t rmk_iter; /* the hash algorithm which derive Root Master Key 派生根主密钥(键)使用的hash算法 */ uint32_t rmk_hash_alg; /* external entropy, optionally, it could be empty 外部熵,可为空 */ uint8_t *entropy; /* the length external entropy 外部熵的长度 */ uint32_t entropy_len; /* the encrption algorithm of master key 主密钥的加密算法 */ uint32_t mk_encrypt_alg; /* the hash algorithm for key-encrypting key 密钥加密密钥的哈希算法 */ uint32_t kek_hash_alg; /* the iterator number for key-encrypting key 密钥加密密钥的迭代次数 */ uint32_t kek_iter; };
两个结构体变量的初始化代码如下:
/* 定义结构体类型变量:根密钥组件的配置 */ /* the configuration of root key component */ struct hks_rkc_cfg g_hks_rkc_cfg = { HKS_RKC_STATE_INIT, HKS_RKC_VER, HKS_RKC_STORAGE_FILE_SYS, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, { NULL, NULL } }, HKS_RKC_RMK_ITER, HKS_RKC_RMK_HMAC_SHA256, NULL, 0, {0}, HKS_RKC_MK_CRYPT_ALG_AES256_GCM, HKS_RKC_RMK_HMAC_SHA256, HKS_RKC_KEK_ITER, {0} }; /* 定义变量:根密钥组件的初始化参数 */ /* the default initialized parameter of root key component */ const struct hks_rkc_init_para g_hks_rkc_def_init_para = { HKS_RKC_VER, HKS_RKC_STORAGE_FILE_SYS, { HKS_RKC_KSF_NUM, { "info1.data", "info2.data" } }, HKS_RKC_RMK_ITER, HKS_RKC_RMK_HMAC_SHA256, NULL, 0, HKS_RKC_MK_CRYPT_ALG_AES256_GCM, HKS_RKC_RMK_HMAC_SHA256, HKS_RKC_KEK_ITER };
-
其他变量的初始化
下面代码中包括了密钥库文件标志、主密钥的附加数据以及主密钥的数据初始化,其中主密钥数据g_hks_rkc_mk 是一个结构体变量,该结构体变量为:/* 定义结构体:主密钥(键)*/ /* master key */ struct hks_rkc_mk { /* whether master key is valid 主密钥是否合法*/ uint8_t is_valid; /* the created time of master key 主密钥的创建时间 */ struct hks_time mk_created_time; /* the expired time of master key 主密钥的过期时间 */ struct hks_time mk_expired_time; /* the master key with mask 主密钥掩码 */ uint8_t mk_with_mask[HKS_RKC_MK_LEN]; };
密钥库文件标志、主密钥的附加数据以及主密钥的数据初始化代码如下:
/* 密钥库文件标志 */ /* the flag of keystore file */ const uint8_t g_hks_rkc_ksf_flag[HKS_RKC_KSF_FLAG_LEN] = { 0x5F, 0x64, 0x97, 0x8D, 0x19, 0x4F, 0x89, 0xCF }; /* 主密钥的附加数据 */ /* the additional data of master key */ uint8_t g_hks_rkc_mk_add_data[HKS_RKC_MK_ADD_DATA_LEN] = { /* H K S R K C M K */ 0x48, 0x4B, 0x53, 0x52, 0x4B, 0x43, 0x4D, 0x4B }; /* 主密钥的数据*/ /* the data of master key */ struct hks_rkc_mk g_hks_rkc_mk = { HKS_BOOL_FALSE, { 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, {0} };
密钥库文件属性初始化
-
函数功能:初始化密钥库文件的属性
root key component - initialize the attribute of keystore file -
传参:密钥库文件属性的结构体变量
parameter:
ksf_attr - [in] - the attribute of keystore file. -
返回值:成功或错误代码
return value:
success or error code -
提示:如果在这个函数中初始化过程失败,动态内存将会被hks_rkc_destroy()函数释放
note:
If initialization failed in this function,
the dynamic memory will be freed by hks_rkc_destroy(). -
注意:初始化密钥库文件的属性的本质在于对密钥库文件名的克隆
代码如下:static int32_t hks_rkc_init_ksf_attr(const struct hks_rkc_ksf_attr *ksf_attr) { g_hks_rkc_cfg.ksf_attr.num = ksf_attr->num;//密钥库文件标识码 uint32_t i = 0; int32_t rc = HKS_STATUS_OK; //从参数中克隆密钥库文件名 /* clone keystore filename from parameter. */ for (; i < ksf_attr->num; ++i) { char *filename = hks_clone_str(ksf_attr->name[i], HKS_RKC_KSF_NAME_LEN_MAX); if (filename == NULL) { //内存将会被hks_rkc_destroy()函数释放 /* the memory will be freed by hks_rkc_destroy() */ rc = HKS_ERROR_MALLOC_FAIL; break; } g_hks_rkc_cfg.ksf_attr.name[i] = filename; } return rc; }
初始化熵
-
函数功能:初始化熵
root key component - initialize entropy -
传入参数:熵、熵的长度
parameter:
entropy - [in] - entropy.
entropy_len - [in] - the length of entropy. -
返回值:成功或错误代码
return value:
success or error code代码如下:
static int32_t hks_rkc_init_entropy(const uint8_t *entropy, const uint32_t entropy_len) { //传入的熵可以为NULL /* the entropy is optional. */ if (entropy == NULL) { //熵为空则跳过,注意此时转态为正常 /* the entropy is empty, skip it. */ log_info("the entropy is empty"); return HKS_STATUS_OK; } //如果熵不为空则熵的长度需要被检查 /* if entropy is not empty, the length should be checked. */ if ((entropy_len == 0) || (entropy_len > HKS_RKC_ENTROPY_LEN_MAX)) { log_error("invalid para,entropy_len=%u", entropy_len); return HKS_ERROR_INVALID_ARGUMENT; } //为初始化熵开辟空间 g_hks_rkc_cfg.entropy = (uint8_t *)HKS_MALLOC(entropy_len); if (g_hks_rkc_cfg.entropy == NULL) { log_error("malloc entropy buffer fail,len=%u", entropy_len); return HKS_ERROR_MALLOC_FAIL; } //将长度写入 g_hks_rkc_cfg.entropy_len = entropy_len; //将熵的内容写入开辟出来的g_hks_rkc_cfg.entropy空间中 int32_t rc = memcpy_s(g_hks_rkc_cfg.entropy, entropy_len, entropy, entropy_len); //检查系统状态 if (rc != HKS_STATUS_OK) return HKS_ERROR_INTERNAL_UNKOWN; return HKS_STATUS_OK; }
填充密钥库文件缓冲区
填充哈希字段到缓冲区
-
函数功能:填充密钥库文件缓冲区哈希字段
root key component - fill hash field of keystore file buffer -
参数说明:密钥库文件缓冲区、密钥库文件缓冲区长度、密钥库文件缓冲区偏移量
parameter:
ksf_buf - [in] - the buffer of keystore file.
ksf_buf_len - [out] - the length of keystore file buffer.
ksf_buf_offset - [in,out] - the offset of keystore file buffer. -
返回值:成功或错误代码
return value:
success or error code代码如下:
static int32_t hks_rkc_fill_ksf_hash(uint8_t *ksf_buf, uint32_t ksf_buf_len, uint32_t *ksf_buf_offset) { struct hks_blob hash_src = { 0, NULL, 0 }; //定义hash源 struct hks_blob hash = { 0, NULL, 0 }; //定义hash结果 //检查密钥库文件缓冲区长度(大小)以及缓冲区偏移量是否满足要求 if ((ksf_buf_len < HKS_RKC_KSF_FLAG_LEN) || (*ksf_buf_offset <= HKS_RKC_KSF_FLAG_LEN) || (ksf_buf_len < *ksf_buf_offset)) return HKS_ERROR_INSUFFICIENT_CAPACITY; /* 使用sha256算法 * calculate SHA256 * skip file flag, begin with version, end with reserve field. */ //ksf_buf的前8位都是标记位,真正的hash源数据在标记位之后 hash_src.data = ksf_buf + HKS_RKC_KSF_FLAG_LEN; //hash源数据的大小是偏移量-标记位占用大小 hash_src.size = *ksf_buf_offset - HKS_RKC_KSF_FLAG_LEN; //hash结果数据存放在ksf_buf+hash源数据移位之后 hash.data = ksf_buf + *ksf_buf_offset; //HKS_RKC_HASH_LEN为根密钥组件hash值长度 hash.size = HKS_RKC_HASH_LEN; int32_t rc = hks_calc_sha256(&hash_src, HKS_RKC_KSF_HASH_SRC_NUM, &hash); if (rc != HKS_STATUS_OK) return rc; //ksf缓冲区的偏移量要加上hash结果的长度 *ksf_buf_offset += HKS_RKC_HASH_LEN; return HKS_STATUS_OK; }
上述代码用到了SHA256算法,该算法原理是计算一个单项hash散列值,实现代码如下:
//计算sha526相关算法原理 int32_t hks_calc_sha256(const struct hks_blob *hash_src, uint32_t hash_src_num, struct hks_blob *hash_result) { if (hash_src == NULL) { log_error("invalid hash src"); return HKS_ERROR_NULL_POINTER; } if (hash_result == NULL) { log_error("invalid hash result"); return HKS_ERROR_NULL_POINTER; } //检查传入参数的合理性 mbedtls_sha256_context sha256_ctx; mbedtls_sha256_init(&sha256_ctx); //定义SHA256并且完成初始化 int rc = mbedtls_sha256_starts_ret(&sha256_ctx, HKS_BOOL_FALSE); //SHA256开始设置 if (rc != HKS_SUCCESS) { log_error("sha256 starts fail,rc=%d", rc); return HKS_ERROR_INTERNAL_UNKOWN; //start_ret设置失败的处理 } do { uint32_t i = 0; for (; i < hash_src_num; ++i) { rc = mbedtls_sha256_update_ret(&sha256_ctx, hash_src[i].data, hash_src[i].size); //更新相关内容 if (rc != HKS_SUCCESS) { log_error("sha256 update fail,rc=%d,i=%u", rc, i); break; } } if (rc != HKS_STATUS_OK) break; rc = mbedtls_sha256_finish_ret(&sha256_ctx, hash_result->data); //结束sha256算法 if (rc != HKS_SUCCESS) { log_error("sha256 finish fail,rc=%d,i=%u", rc, i); break; } } while (0);//用来执行一次的循环 mbedtls_sha256_free(&sha256_ctx); //释放sha256_ctx空间 if (rc != HKS_STATUS_OK) return HKS_ERROR_INTERNAL_UNKOWN; return HKS_STATUS_OK; }
填充根密钥数据到缓冲区
-
函数功能:将根密钥数据填入密钥库文件缓冲区中
root key component - fill root key data into keystore file buffer -
参数说明:密钥库文件数据、密钥库文件缓冲区、密钥库文件缓冲区长度、密钥库文件缓冲区偏移量
parameter:
ksf_data - [in] - the data of keystore file.
ksf_buf - [out] - the buffer of keystore file.
ksf_buf_len - [in] - the buffer length of keystore file.
ksf_buf_offset - [in,out] - the buffer offset of keystore file. -
返回值:成功或错误代码
return value:
success or error code -
注意:
填入的动作需要调用的变量类型转换写入函数hks_u16_2_u8_buf、hks_time_2_u8_buf等见hks_utility.c文件。
填入数据源都在结构体hks_rkc_ksf_data变量ksf_data中。
填入目标在密钥库文件缓冲区。代码如下:
static int32_t hks_rkc_fill_ksf_rk(const struct hks_rkc_ksf_data *ksf_data, uint8_t *ksf_buf, uint32_t ksf_buf_len, uint32_t *ksf_buf_offset) { //填写密钥版本 /* Fill version */ int32_t rc = hks_u16_2_u8_buf(ksf_data->version, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入根密钥的创建时间 /* Fill rk_creat_time */ rc = hks_time_2_u8_buf(&(ksf_data->rk_created_time), ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入根密钥的过期时间 /* Fill rk_expired_time */ rc = hks_time_2_u8_buf(&(ksf_data->rk_expired_time), ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入根密钥的第一个材料 /* Fill the first material */ rc = hks_u8_array_2_u8_buf(ksf_data->rk_material1, HKS_RKC_MATERIAL_LEN, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入根密钥的第二个材料 /* Fill the second material */ rc = hks_u8_array_2_u8_buf(ksf_data->rk_material2, HKS_RKC_MATERIAL_LEN, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入派生根主密钥(键)的迭代次数 /* Fill iterator number */ rc = hks_u32_2_u8_buf(ksf_data->rmk_iter, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入派生根主密钥的椒盐化参数 /* Fill salt */ rc = hks_u8_array_2_u8_buf(ksf_data->rmk_salt, HKS_RKC_SALT_LEN, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入派生根主密钥(键)使用的hash算法 /* Fill hash algorithm */ rc = hks_u32_2_u8_buf(ksf_data->rmk_hash_alg, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入根密钥的主密钥保留部分 /* Fill reserve field */ rc = hks_u8_array_2_u8_buf(ksf_data->rk_rsv, sizeof(ksf_data->rk_rsv), ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; return HKS_STATUS_OK; }
填充主密钥数据到缓冲区
-
函数功能:填充主密钥数据到密钥库文件缓冲区ksf_buf中
root key component - fill masetr key data into keystore file buffer -
参数说明:密钥库文件数据、密钥库文件缓冲区、密钥库文件缓冲区长度、密钥库文件缓冲区偏移量
parameter:
ksf_data - [in] - the data of keystore file.
ksf_buf - [out] - the buffer of keystore file.
ksf_buf_len - [in] - the buffer length of keystore file.
ksf_buf_offset - [in,out] - the buffer offset of keystore file. -
返回值:成功或错误代码
return value:
success or error code代码及评注如下:
static int32_t hks_rkc_fill_ksf_mk(const struct hks_rkc_ksf_data *ksf_data, uint8_t *ksf_buf, uint32_t ksf_buf_len, uint32_t *ksf_buf_offset) { //填入主密钥创建时间 /* Fill mk_created_time */ int32_t rc = hks_time_2_u8_buf(&(ksf_data->mk_created_time), ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入主密钥过期时间 /* Fill mk_expired_time */ rc = hks_time_2_u8_buf(&(ksf_data->mk_expired_time), ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入主密钥使用的加密算法 /* Fill encrption algorithm */ rc = hks_u32_2_u8_buf(ksf_data->mk_encrypt_alg, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入主密钥IV /* Fill IV */ rc = hks_u8_array_2_u8_buf(ksf_data->mk_iv, HKS_RKC_MK_IV_LEN, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入主密钥密文 /* Fill ciphertext */ rc = hks_u8_array_2_u8_buf(ksf_data->mk_ciphertext, HKS_RKC_MK_CIPHERTEXT_LEN, ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //填入主密钥保留数据 /* Fill reserve field */ rc = hks_u8_array_2_u8_buf(ksf_data->mk_rsv, sizeof(ksf_data->mk_rsv), ksf_buf, ksf_buf_len, ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; return rc; }
填充密钥库文件信息(整体封装)
-
函数功能:填写密钥库文件信息到缓冲区ksf_buf中
root key component - fill keystore file buffer -
参数说明:密钥库文件数据结构体、密钥库文件缓冲区、密钥库文件缓冲区大小
parameter:
ksf_data - [in] - the data of keystore file.
ksf_buf - [out] - the buffer of keystore file.
ksf_buf_len - [in] - the buffer length of keystore file. -
返回值:成功或错误代码
return value:
success or error code -
函数封装:密钥库文件信息是根密钥信息、主密钥信息以及hash字段信息的并集,因此本代码封装了上面定义的hks_rkc_fill_ksf_rk、hks_rkc_fill_ksf_mk、hks_rkc_fill_ksf_hash这三个函数,共同完成了密钥库文件信息的填充。
代码如下:
static int32_t hks_rkc_fill_ksf_buf(const struct hks_rkc_ksf_data *ksf_data, uint8_t *ksf_buf, uint32_t ksf_buf_len) { uint32_t ksf_buf_offset = 0; //填写密钥库文件标志,该标志定义在本篇开头 /* Fill file flag */ int32_t rc = hks_u8_array_2_u8_buf(g_hks_rkc_ksf_flag, HKS_RKC_KSF_FLAG_LEN, ksf_buf, ksf_buf_len, &ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //封装,填写根密钥进入密钥库文件缓冲区 /* Fill root key */ rc = hks_rkc_fill_ksf_rk(ksf_data, ksf_buf, ksf_buf_len, &ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; //封装,填写主密钥进入密钥库文件缓冲区 /* Fill master key */ rc = hks_rkc_fill_ksf_mk(ksf_data, ksf_buf, ksf_buf_len, &ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; /* * calculate and fill SHA256 result * skip file flag, begin with version, end with reserve field. */ //封装,填充密钥库文件缓冲区的哈希字段 rc = hks_rkc_fill_ksf_hash(ksf_buf, ksf_buf_len, &ksf_buf_offset); if (rc != HKS_STATUS_OK) return rc; return HKS_STATUS_OK; }
写入密钥库文件
-
函数功能:写密钥库文件到指定密钥库文件地址下
root key component - write keystore file -
传入参数:密钥库文件名、密钥库文件数据结构体变量
parameter:
ksf_name - [in] - keystore filename.
ksf_data - [in] - the data of keystore file. -
返回值:成功或错误代码
return value:
success or error code代码如下:
static int32_t hks_rkc_write_ksf(const char *ksf_name, const struct hks_rkc_ksf_data *ksf_data)
{
//为密钥库缓冲区申请空间
uint8_t *ksf_buf = (uint8_t *)HKS_MALLOC(HKS_RKC_KSF_BUF_LEN);
//检查空间是否成功开辟
if (ksf_buf == NULL) {
log_error("malloc ksf buffer fail");
return HKS_ERROR_MALLOC_FAIL;
}
//清除缓冲区的数据
/* Clear buffer data before using it. */
(void)memset_s(ksf_buf, HKS_RKC_KSF_BUF_LEN, 0, HKS_RKC_KSF_BUF_LEN);
int32_t rc;
do {
//将ksf_data中的数据填入ksf_buf中,此处调用上面定义的封装函数hks_rkc_fill_ksf_buf
/* Fill data into buffer. */
rc = hks_rkc_fill_ksf_buf(ksf_data, ksf_buf, HKS_RKC_KSF_BUF_LEN);
if (rc != HKS_STATUS_OK)
break;
//将缓冲区ksf_buf中的数据写入密钥库文件ksf_name的地址下
/* write buffer data into keystore file */
rc = hks_file_write(ksf_name, HKS_FILE_OFFSET_BASE, ksf_buf,
HKS_RKC_KSF_BUF_LEN);
if (rc != HKS_STATUS_OK) {
log_error("write ksf fail,name=%s,rc=%d", ksf_name, rc);
break;
}
log_info("write ksf success");
} while (0);
//将缓冲区中的数据清楚
/* clear buffer after use. */
(void)memset_s(ksf_buf, HKS_RKC_KSF_BUF_LEN, 0, HKS_RKC_KSF_BUF_LEN);
//释放缓冲区
/* The buffer must be freed no matter success or fail. */
hks_free_ptr(ksf_buf);
return rc;
}
本篇小结
hks_rkc.c代码评注第一部分主要讲解在hks_rkc.c中变量定义与初始化、密钥库文件缓冲区填写的相关操作、以及密钥库文件的写入方法,感谢大家的阅读与点赞。