security_huks模块下hks_rkc.c代码评注第四部分

本篇概述

本篇是接着:

在讲解完密钥库文件的检查操作、密钥库文件中材料的生成相关操作和方法后,本篇将继续讲述hks_rkc.c代码中有关密钥获取以及写所有密钥库文件的部分内容。

代码框架

hks_rkc.c
├── get_related_key
│ └── hks_rkc_pbkdf2_hmac
│ └── hks_rkc_get_rmk_raw_key
│ └── hks_rkc_derive_rmk
├── write
│ └── hks_rkc_write_all_ksf

密钥获取部分

1. hks_rkc_pbkdf2_hmac

  • 函数功能:使用pbkdf2_hmac算法获取派生密钥
    root key component - calculate pbkdf2 hmac

  • 参数说明:hash算法、原始密钥、椒盐化、迭代次数、派生密钥
    parameter:
    hash_alg - [in] - hash algorithm.
    raw_key - [in] - raw key.
    salt - [in] - salt.
    iter_num - [in] - the number of iterater.
    dk - [in,out] - derived key.

  • 返回值:成功或错误代码
    return value:
    success or error code

为了掌握hks_rkc_pbkdf2_hmac函数中相关操作内容,我们需要关注一下几个重点内容:

  1. 有关mbedtls的相关定义及操作

  2. PBKDF2-HMAC算法

  3. mbedtls中预定义的mbedtls_pkcs5_pbkdf2_hmac函数

        int mbedtls_pkcs5_pbkdf2_hmac	(	
        mbedtls_md_context_t * 	ctx,
        const unsigned char * 	password,
        size_t 	plen,
        const unsigned char * 	salt,
        size_t 	slen,
        unsigned int 	iteration_count,
        uint32_t 	key_length,
        unsigned char * 	output 
        )		
    

    PKCS#5 PBKDF2 using HMAC.

         Parameters  参数讲解:
         
         ctx				Generic HMAC context				通用HMAC上下文
         password			Password to use when generating key	生成密钥时使用的密码
         plen				Length of password					密钥长度
         salt				Salt to use when generating key		生成密钥使用的盐化量
         slen				Length of salt				 		盐化量长度
         iteration_count	Iteration count						迭代次数
         key_length	Length of generated key in bytes			生成密钥的存储长度
         
         output	Generated key. Must be at least as big as key_length
         输出:生成密钥
         
         Returns 返回值:
         0 on success, or a MBEDTLS_ERR_XXX code if verification fails.
         Definition at line 217 of file pkcs5.c.
    

详细代码及评注如下:

static int32_t hks_rkc_pbkdf2_hmac(uint32_t hash_alg,
    const struct hks_blob *raw_key, const struct hks_blob *salt,
    uint32_t iter_num, struct hks_blob *dk)
{
    //定义摘要算法类型变量
    mbedtls_md_type_t md_type;

    //此处我们只支持SHA256,检查传入参数hash_alg是否为SHA256,这代表了派生根主密钥使用的hash算法
    if (hash_alg == HKS_RKC_RMK_HMAC_SHA256) {
        md_type = MBEDTLS_MD_SHA256;
    } else {
        log_error("the hash algorithm(%u) is unsupported", hash_alg);
        return HKS_ERROR_NOT_SUPPORTED;
    }

    //初始化通用消息摘要上下文
    /* Initialize the generic message-digest context. */
    mbedtls_md_context_t sha_ctx;

    mbedtls_md_init(&sha_ctx);

    //通过hash算法来得到通用消息摘要上下文
    /* Get the generic message-digest context by hash algorithm. */
    const mbedtls_md_info_t *info_sha = mbedtls_md_info_from_type(md_type);

    if (info_sha == NULL) {
        log_error("info sha is invalid");
        return HKS_ERROR_INTERNAL_UNKOWN;
    }

    int32_t rc;

    do {
        //设置通用消息摘要上下文,简单理解成将info_sha的信息设置到sha_ctx通用消息摘要上下文地址下
        /* Setup the generic message-digest context. */
        rc = mbedtls_md_setup(&sha_ctx, info_sha,
            HKS_RKC_RMK_HMAC_FLAG);
        if (rc != HKS_SUCCESS) {
            log_error("setup mbedtls md fail,rc=%d", rc);
            break;
        }

        //利用PBKDF2-HMAC计算原始密钥rk的hash散列结果,结果存入派生密钥dk中
        /* PBKDF2-HMAC */
        rc = mbedtls_pkcs5_pbkdf2_hmac(&sha_ctx, raw_key->data,
            raw_key->size,
            salt->data, salt->size, iter_num, dk->size, dk->data);
        if (rc != HKS_SUCCESS) {
            log_error("mbedtls pbkdf2 hmac fail,rc=%d", rc);
            break;
        }
    } while (0);

    //释放通用信息摘要内容定义的空间
    /* Free the generic message-digest context. */
    mbedtls_md_free(&sha_ctx);
    if (rc != HKS_STATUS_OK)
        return HKS_ERROR_INTERNAL_UNKOWN;

    return HKS_STATUS_OK;
}

2. hks_rkc_get_rmk_raw_key

  • 函数功能:为根主密钥获取原始密钥
    root key component - get the raw key for derive root master key

  • 参数说明:为密钥库文件加载的数据、原始密钥(输出)
    parameter:
    ksf_data - [in] - the data which loaded from keystore file.
    raw_key - [out] - raw key

  • 返回值:成功或错误代码
    return value:
    success or error code

获取思路:用初始化材料与密钥库文件数据中的两个材料做异或,得到的结果即为原始密钥,并将其写入raw_key。
详细代码及评注如下:

static int32_t hks_rkc_get_rmk_raw_key(const struct hks_rkc_ksf_data *ksf_data,
    struct hks_blob *raw_key)
{
    //定义根密钥组件材料并初始化
    uint8_t material3[HKS_RKC_MATERIAL_LEN] = {0};

    //调用函数hks_rkc_get_fixed_material获取修复的材料
    /* Get the fixed material */
    int32_t rc = hks_rkc_get_fixed_material(material3, HKS_RKC_MATERIAL_LEN);

    if (rc != HKS_STATUS_OK)
        return rc;

    //材料之间按位做异或运算,得到的结果即为原始密钥
    /* materials xor */
    uint32_t i = 0;

    for (; i < HKS_RKC_MATERIAL_LEN; i++)
        raw_key->data[i] = (uint8_t)(ksf_data->rk_material1[i] ^
            ksf_data->rk_material2[i] ^ material3[i]);

    //附加硬件标识符,获取硬件唯一标识符存入原始密钥数据后,注意data的前HKS_RKC_MATERIAL_LEN位存的是异或后的材料
    /* append hardware UDID */
    rc = hks_get_hardware_udid(raw_key->data + HKS_RKC_MATERIAL_LEN,
        HKS_HARDWARE_UDID_LEN);
    if (rc != HKS_STATUS_OK)
        return rc;

    return HKS_STATUS_OK;
}

3. hks_rkc_derive_rmk

  • 函数功能:获取派生根主密钥
    root key component - derive root master key

  • 参数说明:为密钥库文件加载的数据、根主密钥(输出)、根主密钥长度
    parameter:
    ksf_data - [in] - the data which loaded from keystore file.
    rmk - [out] - root master key,
    使用后调用者必须清楚 it must be clear by caller after use.
    rmk_len - [in] - the length of root master key,
    它需要是64字节 it should be 64 bytes.

  • 返回值:成功或失败代码
    return value:
    success or error code

函数执行思路:
有密钥库文件数据ksf_data调用函数hks_rkc_get_rmk_raw_key,利用ksf_data中存储的密钥生成材料生成原始密钥raw_key,接着结合盐化量salt,通过调用函数hks_rkc_pbkdf2_hmac,经过pbkdf2_hmac算法生成派生密钥存入dk(derive key)中。
需要注意的是dk的定义为:struct hks_blob dk = { 0, rmk, rmk_len },本质上就是根主密钥rmk。
该函数的详细代码与评注如下:

static int32_t hks_rkc_derive_rmk(const struct hks_rkc_ksf_data *ksf_data,
    uint8_t *rmk, uint32_t rmk_len)
{
    //定义根密钥组件椒盐数据
    uint8_t salt_data[HKS_RKC_SALT_LEN] = {0};
    //将根密钥组件的密钥库文件数据中的根主密钥椒盐量ksf_data->rmk_salt复制到上面定义的椒盐数据变量salt_data中
    int32_t rc = memcpy_s(salt_data, HKS_RKC_SALT_LEN, ksf_data->rmk_salt,
        HKS_RKC_SALT_LEN);

    //判断系统状态是否成功生成了材料
    if (rc != HKS_STATUS_OK) {
        log_error("generate material fail,rc=%d", rc);
        return HKS_ERROR_INTERNAL_UNKOWN;
    }

    //定义并初始化派生密钥、椒盐、原始密钥数据
    struct hks_blob dk = { 0, rmk, rmk_len };//此处一旦dk确认,则rmk和rmk_len也随之确认,派生密钥即根主密钥信息
    struct hks_blob salt = { 0, salt_data, HKS_RKC_SALT_LEN };
    struct hks_blob raw_key;

    //初始化原始密钥raw_key,大小、类型、存储长度
    rc = hks_blob_init(&raw_key, sizeof(uint8_t), HKS_RKC_RAW_KEY_LEN,
        HKS_BLOB_TYPE_RAW);
    if (rc != HKS_STATUS_OK) {
        log_error("init raw key fail,rc=%d", rc);
        return rc;
    }

    do {
        //调用函数hks_rkc_get_rmk_raw_key(为根主密钥获取原始密钥函数)获取原始密钥
        /* get the raw key */
        rc = hks_rkc_get_rmk_raw_key(ksf_data, &raw_key);
        if (rc != HKS_STATUS_OK)
            break;

        //利用根主密钥的原始密钥raw_key结合PBKDF2-HMAC算法(调用函数hks_rkc_pbkdf2_hmac)获取派生根主密钥dk
        /* PBKDF2-HMAC */
        rc = hks_rkc_pbkdf2_hmac(ksf_data->rmk_hash_alg, &raw_key, &salt,
            ksf_data->rmk_iter, &dk);
        if (rc != HKS_STATUS_OK)
            break;
    } while (0);

    //释放空间(摧毁)原始密钥,以保证系统的安全
    hks_blob_destroy(&raw_key);

    return rc;
}

写所有密钥库文件

hks_rkc_write_all_ksf

  • 函数功能:写所有的密钥库文件
    root key component - write all keystore file

  • 参数说明:密钥库文件数据
    parameter:
    ksf_data - [in] - the data of keystore file.

  • 返回值:成功或错误代码
    return value:
    success or error code

此部分与文件服务hks_file.c部分相关,详细代码与评注如下:

static int32_t hks_rkc_write_all_ksf(const struct hks_rkc_ksf_data *ksf_data)
{
    //检查根密钥组件密钥库文件个数是否满足要求
    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;
    int32_t rc;
    uint32_t success_num = 0;

    for (; i < g_hks_rkc_cfg.ksf_attr.num; ++i) {
        //跳过密钥库文件名为空的根密钥组件配置
        if (g_hks_rkc_cfg.ksf_attr.name[i] == NULL)
            continue;

        //调用写入密钥库文件函数,将ksf_data的数据写入密钥库文件名为g_hks_rkc_cfg.ksf_attr.name[i]的地址下
        rc = hks_rkc_write_ksf(g_hks_rkc_cfg.ksf_attr.name[i],
            ksf_data);
        //如果写入成功则进行计数
        if (rc != HKS_STATUS_OK)
            continue;
        ++success_num;
    }

    /* 如果所有密钥库文件写入失败,返回错误代码,否则,返回成功代码。
     * If all keystore file were wrotten fail, return error code,
     * otherwise, return success code.
     */
    //也就是说只要成功写入一个文件就返回成功
    if (success_num == 0)
        rc = HKS_ERROR_WRITE_FILE_FAIL;
    else
        rc = HKS_STATUS_OK;

    return rc;
}

本篇小结

本篇继续讲述了hks_rkc.c代码中有关密钥获取以及写所有密钥库文件的相关内容,下面将会继续更新有关密钥的加密以及密钥掩码的生成等相关函数,敬请期待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值