hks_storage.c代码分析

本篇博客主要介绍内存中hash加密算法的实现,主要是一些内存的操作。对密钥和文件内存的交互进行实现。
文件路径:security_huks\frameworks\huks_lite\source\hw_keystore_sdk\soft_service\hks_storage.c

代码分析

hks_calc_hash_sha512函数实现hash算法,基于SHA512算法。

//计算hash算法 
static int32_t hks_calc_hash_sha512(uint8_t *hash512, uint16_t size)
{
    uint8_t *buffer = hks_get_buffer();

    if (buffer == NULL)
        return HKS_ERROR_NULL_POINTER;
    //检查是否buffer是否获取失败
    if (size == 0)
        return HKS_ERROR_BUFFER_TOO_SMALL;
    uint8_t *buf = (uint8_t *)HKS_CALLOC(sizeof(uint8_t), size); //按照8位大小申请空间

    if (buf == NULL) //查看是否成功申请空间
        return HKS_ERROR_MALLOC_FAIL;

    if (memcpy_s(buf, size, buffer, size) != EOK) {
        //将buffer中内容复制进buf,buffer的数据内容长度位size,buf的最大大小位size
        hks_free_ptr(buf);
        return HKS_ERROR_BAD_STATE;
    }
    //计算hash算法,基于SHA512算法实现
    crypto_hash_sha512(hash512, buf, size);

    /* clear buffer after use before free. Don't remove! */
    (void)memset_s(buf, size, 0, size);
    //hash执行成功后将buf数组清0
    hks_free_ptr(buf);
    //释放相应空间
    return HKS_STATUS_OK;
}

对数据有效性的检查,

//检查参数是否有效
static int32_t hks_check_data_valid(const uint8_t *buffer)
{
    uint8_t hash512[HKS_HEADER_HASH_SIZE] = {0};
    uint16_t size = hks_get_header_len() - HKS_HEADER_HASH_SIZE;
    //size表示数据域的长度,header的长度减去hash验证码长度
    int32_t status = hks_calc_hash_sha512(hash512, size);
    //
    if (status != HKS_STATUS_OK)
        return status;
    //比较两个字符串内容
    if (memcmp(hash512, (buffer + size), HKS_HEADER_HASH_SIZE) != 0)
    //比较hash512数组内容是否和(buffer中指定位置开始的字符串是否相同
        return HKS_ERROR_INVALID_KEY_FILE;

    return HKS_STATUS_OK;
}

将文件载入进缓冲区。两个参数一个传入文件名字,另一个参数表示传入密钥是否存在。相当于一个逻辑变量。这个逻辑变量实现密钥信息的状态值,用0-1值表示是否存在该密钥信息。
其中大致步骤就是检查参数,然后符合要求的话就申请空间,读取文件等等操作。

//将文件载入进缓冲区。两个参数一个传入文件名字,另一个参数表示传入密钥是否存在。相当于一个逻辑变量
int32_t hks_load_file_to_buffer(const char *file_name, int32_t *is_key_info_exist)
{
    if ((file_name == NULL) || (is_key_info_exist == NULL))
        return HKS_ERROR_NULL_POINTER;

    if (g_storage_image_buffer != NULL) {
        *is_key_info_exist = HKS_BOOL_TRUE;
        return HKS_STATUS_OK;
    }
    //参数的检查
    int32_t status = hks_apply_buffer(sizeof(uint8_t), HKS_BUF_BYTES);
    //申请缓冲区空间
    if (status != HKS_STATUS_OK)
        return status;

    hks_clean_buffer();
    //缓冲区空间的清理。清0
    uint8_t *buffer = hks_get_buffer();

    if (buffer == NULL)
        return HKS_ERROR_NULL_POINTER;

    int32_t len = 0;
    uint32_t offset = hks_get_store_file_offset();
	//计算一个偏置数据,用来计算文件size或者缓冲区size
    if (offset >= HKS_BUF_BYTES) {
        hks_free_buffer();
        return HKS_ERROR_INTERNAL_UNKOWN;
    }

    status = hks_file_read(file_name, offset,
        buffer, (HKS_BUF_BYTES - offset), &len);
    //将文件内容读入缓冲区buffer,将读取长度写进len
    if (status != HKS_STATUS_OK) {
        hks_free_buffer();
        return status;
    }
    //这里的len是文件读取的长度,大于零表示读取成功
    if (len > 0) {
        status = hks_check_data_valid(buffer);
        if (status != HKS_STATUS_OK) {
            hks_free_buffer();
            return status;
        }
        *is_key_info_exist = HKS_BOOL_TRUE;
        //这个变量的值相当于一个逻辑值,0表示逻辑假,1表示逻辑真
    }
    //len=0表示读入文件失败,释放缓冲区空间
    if (len == 0) {
        status = hks_init_buffer();
        if (status != HKS_STATUS_OK) {
            hks_free_buffer();
            return status;
        }
    }
    return status;
}

对内存中数据的清理(置为0)

//清理内存的密钥信息
int32_t hks_storage_clean_key_info(void)
{
    int32_t status = hks_apply_buffer(sizeof(uint8_t), HKS_BUF_BYTES);
    //先申请一个空间
    if (status != HKS_STATUS_OK)
        return status;
    //申请失败的处理
    hks_clean_buffer();
    uint8_t *buffer = hks_get_buffer();
    //获取缓冲区
    if (buffer == NULL)
        return HKS_ERROR_NULL_POINTER;
    //初始化缓冲区内容为0
    status = hks_init_buffer();
    if (status != HKS_STATUS_OK) {
        hks_free_buffer();
        return status;
    }
    //刷新header的hash内容
    status = hks_refresh_header_hash();
    if (status != HKS_STATUS_OK) {
        hks_free_buffer();
        return status;
    }
    //将缓冲区内容读进file,实现内容迁移方便清理buffer内容
    status = hks_sync_buf_to_file();
    if (status != HKS_STATUS_OK) {
        hks_free_buffer();
        return status;
    }
    return status;
}

用来获取密钥的数量,将结果写进key_num.主要目的是为了后面和本地保存的数量做对比,看是否保存合法。

//用来获取密钥的数量,将结果写进key_num
static int32_t hks_storage_get_key_count(uint32_t *key_num)
{
    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_num = key_count;
    return HKS_STATUS_OK;
}

计算loop数目

//计算loop数目
static uint8_t hks_get_slot_count_loop(void)
{
    uint8_t *buffer = hks_get_buffer();

    if (buffer == NULL)
        return 0;

    uint32_t slot_count_pos = sizeof(uint16_t) + sizeof(uint8_t);
    uint8_t slot_count = 0;
    //读取密钥信息
    hks_blob_read_uint8(&slot_count, (buffer + slot_count_pos));

    uint8_t max_num = HKS_LOCAL_STORAGE_KEY_MAX_NUM;
    //选择slot_count和max_num的数目较少的那个
    uint8_t slot_count_loop = (slot_count <= max_num) ?
        slot_count : max_num;

    return slot_count_loop;
}

来判断密钥是否在内存中存在,返回值表示真假。存在返回true,不存在就返回false

//来判断密钥是否在内存中存在
int hks_is_key_exist_in_store(const struct hks_blob *key_alias)
{
    int32_t status = hks_is_valid_alias(key_alias);
    //判断是否可用
    if (status != HKS_STATUS_OK)
        return HKS_BOOL_FALSE;

    uint8_t *key_pos = NULL;

    status = hks_get_key_pos(key_alias, &key_pos);
    //用来获取密钥的位置信息函数,将函数执行结果写进status
    if (status != HKS_STATUS_OK)
        return HKS_BOOL_FALSE;

    if (key_pos != NULL)
        return HKS_BOOL_TRUE;

    return HKS_BOOL_FALSE;
}

来判断密钥是否能存,因为本地内存对密钥的存储数量进行了限制。对之前计算的key_num和函数传入的max_num比较,合法返回true,不合法就返回false

//来判断密钥是否能存,因为本地内存对密钥的存储数量进行了限制。
int hks_is_key_can_store(const struct hks_blob *key_alias, uint32_t max_num)
{
    uint32_t key_num = HKS_LOCAL_STORAGE_KEY_MAX_NUM;
    int32_t status = hks_storage_get_key_count(&key_num);

    if (status != HKS_STATUS_OK)
        return HKS_BOOL_FALSE;

    if (key_num < max_num)
        return HKS_BOOL_TRUE;
    //如果本地密钥存储数量小于传入的max_num,函数返回成功
    if ((key_num == max_num) && (hks_is_key_exist_in_store(key_alias) == HKS_BOOL_TRUE))
        return HKS_BOOL_TRUE;

    return HKS_BOOL_FALSE;
}

函数调用前的注意事项,密文的size = 密钥的size+标记位的size。
注意点:nonce表示只使用一次的随机数数据,在密码学中的意义。
在加密技术中的初始向量和加密散列函数都发挥着重要作用,在各类验证协议的通信应用中确保验证信息不被重复使用以对抗重放攻击(Replay Attack)。

//函数调用前的注意事项
//密文的size = 密钥的size+标记位的size
//密钥的加密
int32_t hks_storage_encrypt_key_blob(struct hks_blob *cipher_text,
    uint32_t sealing_alg, const struct hks_blob *key,
    const struct hks_blob *nonce, const struct hks_blob *aad)
{
    hks_if_true_return_error(((cipher_text == NULL) || (key == NULL) || (nonce == NULL) || (aad == NULL)),
        HKS_ERROR_NULL_POINTER);
    //第一步都是检查参数是否合法
    (void)sealing_alg;

    struct hks_blob kek;
    int32_t status = hks_blob_init(&kek, sizeof(uint8_t),
    //对kek密钥进行初始化
        HKS_RKC_KEK_LEN, HKS_BLOB_TYPE_KEY);

    hks_if_status_error_goto_error(status, exit);
    status = hks_rkc_get_kek(nonce, &kek);
    hks_if_status_error_goto_error(status, exit);

    size_t cipher_text_length = 0;
    struct hks_key_param key_param;
    //前面都是些算法和一些变量的初始化
    (void)memset_s(&key_param, sizeof(key_param), 0, sizeof(key_param));
    //对密钥参数进行初始化为0
    key_param.key_len = HKS_MAX_KEY_LEN_256; //256长度
    key_param.key_type = HKS_KEY_TYPE_AES; //
    key_param.key_mode = HKS_ALG_GCM; //算法标签
    struct hks_aead_data aead_data;
    //hks的aead数据
    aead_data.nonce = nonce->data; //只使用一次的随机值 
    aead_data.nonce_length = nonce->size;  //随机值的size
    aead_data.additional_data = aad->data;
    aead_data.additional_data_length = aad->size;  //附加值的size和大小
    aead_data.ciphertext = cipher_text->data;  //密文信息输入
    aead_data.ciphertext_length = cipher_text->size;  //密文的size
    aead_data.plaintext = key->data;
    aead_data.plaintext_length = key->size;
    //对该部分数据进行赋值
    status = hks_mbedtls_aead_encrypt(&kek, &key_param, &aead_data,
        &cipher_text_length);
    //aead加密
    if (status != HKS_STATUS_OK) {
        hks_blob_destroy(cipher_text);
        //加密失败的话直接distroy密文
        goto exit;
    }
    //
    if (cipher_text_length < UINT32_MAX)
        cipher_text->size = (uint32_t)cipher_text_length;
        //密文length的判断
    else
        status = HKS_ERROR_DATA_CORRUPT;

exit:
    hks_blob_destroy(&kek);
    //密钥结构体内存的清理
    return status;
}