kdf算法介绍以及hks_mbedtls_kdf.c代码分析

一、算法介绍

kdf是一种密钥派生函数,全称Key Derivation Function。密钥派生函数的作用是从一个共享的秘密比特串中派生出密钥数据。在密钥协商过程中,密钥派生函数作用在密钥交换所获共享的秘密比特串上,从中产生所需的会话密钥或进一步加密的密钥数据。
函数的输入:一个比特串z,以及要获得的密钥的比特长度klen。
输出:长度为klen的密钥数据比特串。
其中一种变形形式为hkdf算法。(hmac+kdf)
参考文章:

  1. kdf通俗易懂的介绍
  2. kdf原理
  3. hkdf实现
  4. hmac介绍
  5. hash介绍

二、代码分析

pbkdf算法的实现。传入一个比特串密钥,生成一个指定长度的密钥串存放进derivedKey。
参数详解:

  • mainkey:原始的输入信息,存放输入
  • derparam:存放要生成的派生密钥的参数
  • info:存放信息
  • derivedKey:最后派生结果的存放
//pbkdf2算法的实现
static int32_t DeriveKeyPbkdf2(const struct HksBlob *mainKey, const struct HksKeyDerivationParam *derParam,
    const mbedtls_md_info_t *info, struct HksBlob *derivedKey)
{
    mbedtls_md_context_t ctx;
    mbedtls_md_init(&ctx);

    int32_t ret;
    do {
        ret = mbedtls_md_setup(&ctx, info, 1); /* 1 for using HMAC */
        //选择MD使用和分配内部结构
        if (ret != HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("Mbedtls md setup failed! mbedtls ret = 0x%X", ret);
            break;
        }

        ret = mbedtls_pkcs5_pbkdf2_hmac(&ctx, mainKey->data, mainKey->size, derParam->salt.data,
            derParam->salt.size, derParam->iterations, derivedKey->size, derivedKey->data);
        if (ret != HKS_MBEDTLS_SUCCESS) {
            HKS_LOG_E("Mbedtls pbkdf2 failed! mbedtls ret = 0x%X", ret);
            (void)memset_s(derivedKey->data, derivedKey->size, 0, derivedKey->size);
        }
    } while (0);

    mbedtls_md_free(&ctx);
    return ret;
}
#endif /* HKS_SUPPORT_KDF_PBKDF2 */

HKDF算法 = Hmac + KDF
HMAC是指Hash-based的MAC算法,hash函数是可选的,例如存在这些HMAC实现:

  • HMAC_MD5
  • HMAC_SHA1
  • HMAC_SHA256

KDF算法由上面已经介绍。
函数的参数介绍:

  • mainkey:原始的输入信息,存放输入
  • derparam:存放要生成的派生密钥的参数
  • info:存放信息
  • derivedKey:最后派生结果的存放
#ifdef HKS_SUPPORT_KDF_HKDF
//hkdf算法实现
static int32_t DeriveKeyHkdf(const struct HksBlob *mainKey, const struct HksKeyDerivationParam *derParam,
    const mbedtls_md_info_t *info, struct HksBlob *derivedKey)
{
    int32_t ret = mbedtls_hkdf(info, derParam->salt.data, derParam->salt.size, mainKey->data, mainKey->size,
        derParam->info.data, derParam->info.size, derivedKey->data, derivedKey->size);
    //这是基于hmac的提取和展开键推导函数。输入由mainkey完成,将最终结果写进derivedKey
    if (ret != HKS_MBEDTLS_SUCCESS) {
        HKS_LOG_E("Mbedtls hkdf failed! mbedtls ret = 0x%X", ret);
        (void)memset_s(derivedKey->data, derivedKey->size, 0, derivedKey->size);
    }

    return ret;
}
#endif /* HKS_SUPPORT_KDF_HKDF */

密钥派生函数的封装(分支结构选取)
该部分实现kdf算法和hkdf算法的封装,根据不同情况选择不同算法实现密钥的派生。
参数详解

  • mainkey:原始的输入信息,存放输入
  • derivationSpec:派生密钥的相关特定信息、如派生算法名称等等
  • derivedKey:最后派生结果的存放
//密钥的派生
int32_t HksMbedtlsDeriveKey(const struct HksBlob *mainKey,
    const struct HksKeySpec *derivationSpec, struct HksBlob *derivedKey)
{
    const struct HksKeyDerivationParam *derParam = (struct HksKeyDerivationParam *)(derivationSpec->algParam);

    uint32_t mbedtlsAlg;
    int32_t ret = HksToMbedtlsDigestAlg(derParam->digestAlg, &mbedtlsAlg);
    //将hks对应的mbedlts算法名写进mbedtlsAlg
    if (ret != HKS_SUCCESS) {
        return ret;
    }

    const mbedtls_md_info_t *info = mbedtls_md_info_from_type(mbedtlsAlg);
    //获取算法md信息
    if (info == NULL) {
        HKS_LOG_E("Mbedtls get md info failed! mbedtls ret = 0x%X", ret);
        return HKS_FAILURE;
    }

    switch (derivationSpec->algType) {
        //根据传入的derivationSpec的算法类型,选择执行不同的算法
#ifdef HKS_SUPPORT_KDF_PBKDF2
        case HKS_ALG_PBKDF2:
            return DeriveKeyPbkdf2(mainKey, derParam, info, derivedKey);
#endif
#ifdef HKS_SUPPORT_KDF_HKDF
        case HKS_ALG_HKDF:
            return DeriveKeyHkdf(mainKey, derParam, info, derivedKey);
#endif
        default:
            HKS_LOG_E("Unsupport derive key alg! mode = 0x%X", derivationSpec->algType);
            return HKS_ERROR_INVALID_ARGUMENT;
    }
}