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

这个函数主要是为了实现密钥序列化,做的一些数据主备和密钥预处理。
函数参数:

  1. key_info:存放的密钥信息
  2. sealing_alg:密封算法
  3. nonce:存放即时随机数据
  4. 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;
}

以上为部分代码注释