hks_storage.c代码分析
这里添加密钥节点信息
通过新申请一个密钥节点,申请缓冲区,指定一个偏置信息将buffer中写进节点,然后节点指针偏移(自增运算一次)在读进缓冲区,相当于节点多了一位,主要是靠这里的在自增运算实现。
密钥节点的减少原理类似,这里就不赘述了
//添加密钥节点
static int32_t hks_add_key_count(void)
{
uint8_t *buffer = hks_get_buffer();
if (buffer == NULL)
return HKS_ERROR_NULL_POINTER;
uint8_t key_count = 0;
uint32_t key_count_pos = sizeof(uint16_t);
//
hks_blob_read_uint8(&key_count, (buffer + key_count_pos));
++key_count;//通过这一行命令实现密钥节点的增加
hks_blob_write_uint8((buffer + key_count_pos), key_count);
//将信息写入,实现节点的增加
return HKS_STATUS_OK;
}
//
static int32_t hks_reduce_key_count(void)
{
uint8_t *buffer = hks_get_buffer();
if (buffer == NULL)
return HKS_ERROR_NULL_POINTER;
uint8_t key_count = 0;
uint32_t key_count_pos = sizeof(uint16_t);
hks_blob_read_uint8(&key_count, (buffer + key_count_pos));
if (key_count == 0)
return HKS_STATUS_OK;
--key_count; //和上面类似,这里实现自检运算
hks_blob_write_uint8((buffer + key_count_pos), key_count);
return HKS_STATUS_OK;
}
hks_slot_add_key
在slot中增加一组key。先申请缓冲区,使用临时缓冲区tmp指向申请的缓冲区,加一个头部长度的偏置。然后计算插槽节点数目,遍历所有slot_count,将tmp中内容写进标记位flags,然后判断是否符合要求。对idle的逻辑变量进行改变值。最后初始化相关tmp内容,申请一个密钥节点信息写进slot_count。
//槽中增加密钥
static int32_t hks_slot_add_key(const uint8_t *buf, uint32_t len)
{
uint8_t *image_buffer = hks_get_buffer();
//先申请一个缓冲区
if (image_buffer == NULL)
return HKS_ERROR_NULL_POINTER;
uint8_t slot_count_loop = hks_get_slot_count_loop();
//计算出slot_count_loop数量
uint8_t *tmp = image_buffer + hks_get_header_len();
uint16_t slot_shift = hks_get_key_slot_len();
uint8_t flags = 0;
int32_t find_idle = HKS_BOOL_FALSE;
for (uint8_t i = 0; i < slot_count_loop; i++) {
//将每个插槽都进行访问一遍
hks_blob_read_uint8(&flags, tmp);
//将tmp临时缓冲区内容读进flags
if ((flags == HKS_SLOT_PUBLIC_KEY_IDLE) ||
(flags == HKS_SLOT_KEYPAIR_IDLE)) {
//判断读入内容
find_idle = HKS_BOOL_TRUE;
break;
}
tmp += slot_shift;
//temp指针往前移动slot_shift
}
if (memset_s(tmp, slot_shift, 0, slot_shift) != EOK)
return HKS_ERROR_BAD_STATE;
//将tmp中内容初始化为0
if (memcpy_s(tmp, len, buf, slot_shift) != EOK)
return HKS_ERROR_BAD_STATE;
//将buf内容写进tmp临时缓冲区
int32_t status = hks_add_key_count();
//添加一个密钥节点
if (status != HKS_STATUS_OK)
return status;
//如果flag中内容没有符合要求的
if (find_idle == HKS_BOOL_FALSE) {
status = hks_add_slot_count();
if (status != HKS_STATUS_OK)
return status;
}
return HKS_STATUS_OK;
}
下面hi密钥信息在内存中的存储方式和形式
Key_info into file according to format:
key_info = header|keyslot1|keyslot2|
header = version(2 bytes) | key_count(1 bytes)
| slot_count(1 bytes)
| sealing_alg(4 bytes) | sealing_nonce(16 bytes) | hash(64 bytes)
keyslot = falgs(1 bytes) | sealing_nonce(16 bytes) | alias_size(1 bytes)
| alias(alias_size bytes) | param | key_size(1 bytes)
| key(key_size bytes)
param = key_type(4 bytes) | key_len(2 bytes) | usage(4 bytes)
| mode(4 bytes)
| padding(1 bytes) | key_role(4 bytes) | domain(2 bytes)
| auth_id_type(1 bytes)
| auth_id_size(1 bytes) | auth_id_data( auth_id_size bytes)
hks_sync_buf_to_file
这个函数功能十分简单,就是读取buf中的内容写进文件file。主要原理就是要获取一个文件的在内存中存储的偏置信息,语句偏置信息读取文件名,将缓冲区里面存储的信息写进文件名对应的file。关键点是获取offset
//从缓冲区写进文件
static int32_t hks_sync_buf_to_file(void)
{
uint8_t *buffer = hks_get_buffer();
if (buffer == NULL)
return HKS_ERROR_NULL_POINTER;
uint32_t offset = hks_get_store_file_offset();
//获取文件在内存中存储的偏置信息
if (offset >= HKS_BUF_BYTES)
return HKS_ERROR_INTERNAL_UNKOWN;
//计算偏执信息
return hks_file_write(HKS_KEY_STORE_FILE_NAME, offset,
buffer, HKS_BUF_BYTES - offset);
//将缓冲区内容写进file
}
密钥信息序列化前的准备hks_prepare_serialize_key_info
这个函数主要是为了实现密钥序列化,做的一些数据主备和密钥预处理。
函数参数:
- key_info:存放的密钥信息
- sealing_alg:密封算法
- nonce:存放即时随机数据
- key:最后的输出密钥,也就是准备好的密钥
这里将随机数写进nonce,用途可能是要在序列化时候使用,在这个函数中并没有体现用途和意义。
期间对密钥的类型做了一次特判:主要是判断key_info->param中的密钥类型,如果是PUBLIC_KEY_ED25519,就写进公钥,如果是EDDSA_KEYPAIR_ED25519就写进私钥。相当于对密钥信息key_info的数据处理。
//密钥信息的序列化准备
static int32_t hks_prepare_serialize_key_info(
const struct hks_storage_key_info *key_info,
uint32_t *sealing_alg,
struct hks_blob *nonce,
struct hks_blob *key)
{
int32_t status = hks_get_sealing_info(sealing_alg);
if (status != HKS_STATUS_OK)
return HKS_ERROR_READ_FILE_FAIL;
status = hks_gen_random(nonce->data, nonce->size);
//生成一组随机数,将数据写进nonce->data,size写进nonce->size
hks_if_status_error_return(status);
//检查是否申请成功
if (key_info->param->key_type == HKS_KEY_TYPE_EDDSA_PUBLIC_KEY_ED25519)
*key = *(key_info->public_key);
else if (key_info->param->key_type == HKS_KEY_TYPE_EDDSA_KEYPAIR_ED25519)
*key = *(key_info->private_key);
//这两个判断主要是判断key_info->param中的密钥类型,如果是PUBLIC_KEY_ED25519,就写进公钥,如果是EDDSA_KEYPAIR_ED25519就写进私钥
else
return HKS_ERROR_INVALID_ARGUMENT;
return HKS_STATUS_OK;
}
序列化实现
这个是序列化的正式实现,主要是涉及密钥的保存。序列化的方式可以是密钥的存储方式更加便捷。同时也方便两端机器对密钥的加解密实现。上一部分准备中用到的nonce数据在这里使用,用来实现密钥私钥的准备。同时这里的函数使用了一个goto语句,跳转到退出界面,然后摧毁随机数和密文信息。
大部分操作在内存中完成,实现一些读写操作。
//正是开始序列化
static int32_t hks_serialize_key_info(uint8_t *buf,
const struct hks_blob *key_alias,
const struct hks_storage_key_info *key_info)
{
uint32_t n = 0;
uint32_t sealing_alg = HKS_SEALING_DEFAULT;
//密封算法这里使用默认的密封算法
struct hks_blob key;
struct hks_blob nonce_blob = HKS_BLOB_DEFAULT_VALUE;
struct hks_blob cipher_text = HKS_BLOB_DEFAULT_VALUE;
//相关数据的初始化
if (key_info->param == NULL)
return HKS_ERROR_NULL_POINTER;
if ((key_info->param->key_type != HKS_KEY_TYPE_EDDSA_PUBLIC_KEY_ED25519) &&
(key_info->param->key_type != HKS_KEY_TYPE_EDDSA_KEYPAIR_ED25519))
return HKS_ERROR_INVALID_ARGUMENT;
//判断key_info->param中的密钥类型,如果是PUBLIC_KEY_ED25519,就写进公钥,如果是EDDSA_KEYPAIR_ED25519就写进私钥
/* Prepare */
int32_t status = hks_blob_init(&nonce_blob, sizeof(uint8_t), HKS_SEALING_NONCE_SIZE, HKS_BLOB_TYPE_RAW);
//准备阶段,随机数在这里使用用来初始化blob密钥
hks_if_status_error_return(status);
//对密钥信息进行处理,并生成一组随机数
status = hks_prepare_serialize_key_info(key_info, &sealing_alg, &nonce_blob, &key);
hks_if_status_error_goto_error(status, exit);
/* Write flags */
//根据不通的密钥参数类型,写进对应的缓冲区
if (key_info->param->key_type == HKS_KEY_TYPE_EDDSA_PUBLIC_KEY_ED25519)
n += hks_blob_write_uint8((buf + n), HKS_SLOT_PUBLIC_KEY_OCCUPY);
else
n += hks_blob_write_uint8((buf + n), HKS_SLOT_KEYPAIR_OCCUPY);
//这里将随机数信息写进缓冲区
/* Write nonce */
status = hks_blob_write_buf((buf + n), (hks_get_key_slot_len() - n), nonce_blob.data, nonce_blob.size, &n);
hks_if_status_error_goto_error(status, exit);
//将密钥信息写进缓冲区,如果失败就执行退出过程
/* Write key info */
status = hks_serialize_fill_buf(buf, key_alias, key.size, key_info, &n);
hks_if_status_error_goto_error(status, exit);
/* Encrypt key, AAD is now the buf itself */
struct hks_blob buf_blob = { HKS_BLOB_TYPE_RAW, buf, n };
status = hks_blob_init(&cipher_text, sizeof(uint8_t), (key.size + HKS_SEALING_TAG_SIZE), HKS_BLOB_TYPE_KEY);
hks_if_status_error_goto_error(status, exit);
//密钥信息的加密,这里在内存中实现加密
status = hks_storage_encrypt_key_blob(&cipher_text, sealing_alg, &key, &nonce_blob, &buf_blob);
if (status == HKS_STATUS_OK) {
status = hks_blob_write_buf((buf + n), (hks_get_key_slot_len() - n), cipher_text.data, cipher_text.size, &n);
hks_if_status_error_goto_error(status, exit);
}
exit:
//推出后将随机数和密文信息进行摧毁
hks_blob_destroy(&nonce_blob);
hks_blob_destroy(&cipher_text);
return status;
}
//刷新
static int32_t hks_refresh_header_hash(void)
{
uint8_t *buffer = hks_get_buffer();
//获取buffer
if (buffer == NULL)
return HKS_ERROR_NULL_POINTER;
uint8_t hash512[HKS_HEADER_HASH_SIZE] = {0};
uint16_t size = hks_get_header_len() - HKS_HEADER_HASH_SIZE;
int32_t status = hks_calc_hash_sha512(hash512, size);
//计算hash码
if (status != HKS_STATUS_OK)
return status;
uint32_t n = 0;
//将密钥写进buffer
status = hks_blob_write_buf((buffer + size), (hks_get_header_len() - size), hash512, HKS_HEADER_HASH_SIZE, &n);
if (status != HKS_STATUS_OK)
return status;
return HKS_STATUS_OK;
}
以上为部分代码注释