security_huks模块下hks_service.c代码评注(二)
本篇概述
本篇接续security_huks模块下hks_service.c代码评注(一),在讲解完有关密钥生成以及aead加密算法的基础上,主要讲述剩余的密钥相关服务、算法服务以及非对称密钥部分的部分代码。
代码框架
hks_service.c
├── key_service
│ └── hks_get_size_from_algrithom
│ └── hks_service_hmac_ex
│ └── hks_service_key_derivation
│ └── hks_service_key_agreement
├── algorithm_service
│ └── hks_service_get_random
│ └── hks_service_hmac
│ └── hks_mbedtls_hash
│ └── hks_service_hash
密钥信息服务
本部分将接着讲述有关密钥信息的获取以及派生密钥与密钥许可相关函数的运行思路和具体执行步骤。
1. hks_get_size_from_algrithom
函数功能:从算法中获取输出密钥的长度
本部分主要是通过调用判断算法的类型来返回相应的密钥定义长度,需要区分HASH_SHA_256和HASH_SHA_512两种算法。详细代码如下:
//函数功能:从算法中获取输出密钥的长度
static int32_t hks_get_size_from_algrithom(uint32_t alg, uint32_t* output_size)
{
if (output_size == NULL)
return HKS_ERROR_NULL_POINTER;
//初始化输出密钥大小
*output_size = 0;
//检查算法类型,区别HASH_SHA_256和HASH_SHA_512
if ((alg == hks_alg_hmac(HKS_ALG_HASH_SHA_256)) || (alg == HKS_ALG_HASH_SHA_256))
*output_size = HKS_HASH256_MIN_OUT_SIZE;
if ((alg == hks_alg_hmac(HKS_ALG_HASH_SHA_512)) || (alg == HKS_ALG_HASH_SHA_512))
*output_size = HKS_HASH512_MIN_OUT_SIZE;
//返回肯定状态
return HKS_STATUS_OK;
}
2. hks_service_hmac_ex
函数功能:hmac对称服务方案
本函数在检查传参的基础上主要通过调用函数hks_service_hmac()进行密钥的hmac算法加密进而获取对称密钥,并通过调用函数hks_get_size_from_algrithom()来获取密钥大小。详细代码如下:
//函数功能:hmac对称服务方案
int32_t hks_service_hmac_ex(const struct hks_blob* key,
uint32_t alg, const struct hks_blob* src_data, struct hks_blob* output)
{
//检查传入参数是否合规
hks_if_true_return_error(((key == NULL) || (key->data == NULL) || (key->size <= 0)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error(((alg != hks_alg_hmac(HKS_ALG_HASH_SHA_256)) &&
(alg != hks_alg_hmac(HKS_ALG_HASH_SHA_512))), HKS_ERROR_INVALID_ARGUMENT);
hks_if_true_return_error(((src_data == NULL) || (src_data->data == NULL) || (src_data->size <= 0)),
HKS_ERROR_NULL_POINTER);
hks_if_true_return_error(((output == NULL) || (output->data == NULL)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error((((alg == hks_alg_hmac(HKS_ALG_HASH_SHA_256)) &&
(output->size < HKS_HASH256_MIN_OUT_SIZE)) || ((alg == hks_alg_hmac(HKS_ALG_HASH_SHA_512)) &&
(output->size < HKS_HASH512_MIN_OUT_SIZE))), HKS_ERROR_BUF_TOO_SMALL);
//hmac算法生成密钥不能超过hash输出的大小
/* hmac key len not less than hash output size */
hks_if_true_return_error((((alg == hks_alg_hmac(HKS_ALG_HASH_SHA_256)) &&
(key->size < HKS_HASH256_MIN_OUT_SIZE))), HKS_ERROR_INVALID_ARGUMENT);
hks_if_true_return_error((((alg == hks_alg_hmac(HKS_ALG_HASH_SHA_512)) &&
(key->size < HKS_HASH512_MIN_OUT_SIZE))), HKS_ERROR_INVALID_ARGUMENT);
//调用hmac服务对密钥进行hmac算法加密
int32_t status = hks_service_hmac(key, alg, src_data, output);
hks_check_return_code(status, &status);
//获取从算法中获取输出密钥的大小
status = hks_get_size_from_algrithom(alg, &output->size);
hks_if_status_error_return(status);
return status;
}
3. hks_service_key_derivation
函数功能:派生密钥服务
输入参数:派生密钥、密钥导出扩展、椒盐化、标志、密钥参数
该函数的核心在于其调用的接口函数:hks_mbedtls_key_derivation。派生密钥接口函数如下:
//密钥派生mbedtls接口函数
int32_t hks_mbedtls_key_derivation(struct hks_blob *derived_key,
const uint32_t alg, const struct hks_blob *kdf_key,
const struct hks_blob *salt, const struct hks_blob *label)
{
int32_t status = 0;
//选择算法SHA_256和SHA_512对应的不同方法生成派生密钥
switch (alg) {
case hks_alg_hkdf(HKS_ALG_HASH_SHA_256):
status = mbedtls_hkdf(
mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
salt->data, salt->size, kdf_key->data, kdf_key->size,
label->data, label->size, derived_key->data,
derived_key->size);
break;
case hks_alg_hkdf(HKS_ALG_HASH_SHA_512):
status = mbedtls_hkdf(
mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
salt->data, salt->size, kdf_key->data, kdf_key->size,
label->data, label->size, derived_key->data,
derived_key->size);
break;
default:
break;
}
hks_check_return_code(mbedtls_to_hks_error(status), &status);
return status;
}
函数hks_service_key_derivation()代码及注解如下:
//派生密钥服务 输入参数:派生密钥、密钥导出扩展、椒盐化、标志、密钥参数
int32_t hks_service_key_derivation(struct hks_blob *derived_key,
const struct hks_blob *kdf_key, const struct hks_blob *salt,
const struct hks_blob *label, const struct hks_key_param *key_params)
{
//检查派生密钥、kdf密钥、密钥参数、盐化量是否满足条件
hks_if_true_return_error(((derived_key == NULL) || (kdf_key == NULL) || (salt == NULL) ||
(label == NULL) || (key_params == NULL)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error((derived_key->data == NULL), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error((derived_key->size < HKS_DERIVED_KEY_MIN_OUT_SIZE), HKS_ERROR_BUFFER_TOO_SMALL);
hks_if_true_return_error(((kdf_key->data == NULL) || (kdf_key->size <= 0)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error(((key_params->key_type != HKS_KEY_TYPE_DERIVE) ||
(key_params->key_usage != HKS_KEY_USAGE_DERIVE)), HKS_ERROR_INVALID_ARGUMENT);
hks_if_true_return_error(((key_params->key_mode != hks_alg_hkdf(HKS_ALG_HASH_SHA_256)) &&
(key_params->key_mode != hks_alg_hkdf(HKS_ALG_HASH_SHA_512))), HKS_ERROR_INVALID_ARGUMENT);
hks_if_true_return_error(((key_params->key_len != HKS_MAX_KEY_LEN_128) &&
(key_params->key_len != HKS_MAX_KEY_LEN_256)), HKS_ERROR_INVALID_ARGUMENT);
hks_if_true_return_error(((salt->data == NULL) || (label->data == NULL)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error(((salt->size < HKS_SALT_MAX_SIZE) || (label->size < HKS_SALT_MAX_SIZE)),
HKS_ERROR_INVALID_ARGUMENT);
//调用接口函数生成派生密钥
int32_t status = hks_mbedtls_key_derivation(derived_key, key_params->key_mode, kdf_key, salt, label);
return status;
}
4. hks_service_key_agreement
函数功能:密钥许可服务
需要注意的是:
- 私有密钥的数据由hks生成,因此它必须是高位编址
- 对等公有密钥数据是从外部进入的,因此需要确保它是低位编址
因此在读入对等公钥时需要对其进行一个高低位翻转。高低位编址详见Endian。
本部分代码的核心思路是利用对等公钥检查公钥数据,并通过密钥协商算法建立沟通机制,进而生成许可密钥,将许可密钥进行编码转换后存入系统。详细代码及评注如下:
//函数功能:密钥许可服务
int32_t hks_service_key_agreement(struct hks_blob *agreed_key,
const struct hks_key_param *private_key_param,
const struct hks_blob *private_key,
const struct hks_blob *peer_public_key,
const uint32_t agreement_alg)
{
//检查许可密钥、私有公有密钥及密钥参数是否为空且大小是否满足条件
hks_if_true_return_error(((agreed_key == NULL) || (private_key_param == NULL) || (private_key == NULL) ||
(peer_public_key == NULL)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error((private_key->size != CRYPTO_PUBLIC_KEY_BYTES), HKS_ERROR_INVALID_PRIVATE_KEY);
hks_if_true_return_error((peer_public_key->size != CRYPTO_PUBLIC_KEY_BYTES), HKS_ERROR_INVALID_PUBLIC_KEY);
(void)agreement_alg;
//定义mbedtls接口变量
mbedtls_ecdh_context *ctx_cli = NULL;
size_t ctx_cli_size = sizeof(*ctx_cli);
//为语境变量分配空间
ctx_cli = (mbedtls_ecdh_context *)HKS_MALLOC(ctx_cli_size);
hks_if_true_return_error((ctx_cli == NULL),
HKS_ERROR_INSUFFICIENT_MEMORY);
(void)memset_s(ctx_cli, ctx_cli_size, 0, ctx_cli_size);
//使用接口函数进行初始化并且调用mbedtls_ecp_group_load函数利用椭圆曲线ECP25519算法载入集群
mbedtls_ecdh_init(ctx_cli);
int32_t ret = mbedtls_ecp_group_load(&ctx_cli->grp,
MBEDTLS_ECP_DP_CURVE25519);
hks_if_status_error_goto_error(ret, exit);
//设置椭圆曲线初始坐标
/* set the elliptic curve initial coordinates */
ret = mbedtls_mpi_lset(&ctx_cli->Qp.Z, 1);
hks_if_status_error_goto_error(ret, exit);
//定义初始化对等公有密钥数据
uint8_t peer_public_key_data[CRYPTO_PUBLIC_KEY_BYTES] = { 0 };
//将对等公有密钥的数据复制到刚初始化的密钥数据数组中
ret = memcpy_s(peer_public_key_data, CRYPTO_PUBLIC_KEY_BYTES,
peer_public_key->data, peer_public_key->size);
hks_if_status_error_goto_error(ret, exit);
//hks编码转换:由于私有密钥数据是高位编址而对等公有密钥数据是低位编址因此需要将数据倒序
ret = hks_endian_swap(peer_public_key_data, CRYPTO_PUBLIC_KEY_BYTES);
hks_if_status_error_goto_error(ret, exit);
//读取对等公有密钥数据
ret = mbedtls_mpi_read_binary(&ctx_cli->Qp.X, peer_public_key_data,
CRYPTO_PUBLIC_KEY_BYTES);
hks_if_status_error_goto_error(ret, exit);
//检查公有密钥数据
ret = mbedtls_ecp_check_pubkey(&ctx_cli->grp, &ctx_cli->Qp);
hks_if_status_error_goto_error(ret, exit);
//读取私有密钥数据
ret = mbedtls_mpi_read_binary(&ctx_cli->d, private_key->data,
CRYPTO_PUBLIC_KEY_BYTES);
hks_if_status_error_goto_error(ret, exit);
//利用密钥协商机制建立沟通
ret = mbedtls_ecdh_compute_shared(&ctx_cli->grp, &ctx_cli->z,
&ctx_cli->Qp, &ctx_cli->d, NULL, NULL);
hks_if_status_error_goto_error(ret, exit);
//写入许可密钥
ret = mbedtls_mpi_write_binary(&ctx_cli->z, agreed_key->data,
CRYPTO_PUBLIC_KEY_BYTES);
hks_if_status_error_goto_error(ret, exit);
//将许可密钥进行编码转换
ret = hks_endian_swap(agreed_key->data, CRYPTO_PUBLIC_KEY_BYTES);
hks_if_status_error_goto_error(ret, exit);
//设置许可密钥大小
agreed_key->size = CRYPTO_PUBLIC_KEY_BYTES;
ret = HKS_SUCCESS;
exit:
//释放mbedtls语境空间
mbedtls_ecdh_free(ctx_cli);
hks_free_ptr(ctx_cli);
int32_t status = mbedtls_to_hks_error(ret);
hks_check_return_code(status, &status);
return status;
}
算法相关服务
1. hks_service_get_random
函数功能:获取随机数服务
获取随机数函数服务在初始化密钥时经常被使用,该服务是对随机数生成器的一个封装,主要功能是通过调用函数hks_gen_random()来实现的,我们将生成随机数函数hks_gen_random()附在下面:
/* 函数功能:生成随机数
* generate random number
*
* 参数说明:随机数存储缓冲区、随机数长度
* parameter:
* random - [out] - the buffer of random number.
* len - [in] - the length of random number.
*
* 返回值:成功或失败代码
* return value:
* success or error code
*/
int32_t hks_gen_random(uint8_t *random, uint32_t len)
{
if (random == NULL) {
log_error("invalid random");
return HKS_ERROR_NULL_POINTER;
}
if ((len == 0) || (len > HKS_RANDOM_MAX_LEN)) {
log_error("invalid len=%u", len);
return HKS_ERROR_INVALID_ARGUMENT;
}
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
(void)memset_s(&ctr_drbg, sizeof(ctr_drbg), 0, sizeof(ctr_drbg));
mbedtls_entropy_init(&entropy);
int ret = HKS_SUCCESS;
/* use the g_hks_random_seed_custom without string terminator */
//使用不带字符串终止符的g_hks随机种子自定义
int32_t rc = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
&entropy, g_hks_random_seed_custom,
sizeof(g_hks_random_seed_custom));
if (rc != HKS_STATUS_OK) {
log_error("ctr drbg seed fail,rc=%d", rc);
ret = HKS_ERROR_INTERNAL_UNKOWN;
goto exit;
}
rc = mbedtls_ctr_drbg_random(&ctr_drbg, random, len);
if (rc != HKS_STATUS_OK) {
log_error("ctr drbg random fail,rc=%d", rc);
ret = HKS_ERROR_INTERNAL_UNKOWN;
}
exit:
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
return ret;
}
详细的获取随机数服务函数hks_service_get_random()的代码及标注如下:
//函数功能:获取随机数服务
int32_t hks_service_get_random(struct hks_blob *random)
{
hks_if_true_return_error((random == NULL), HKS_ERROR_NULL_POINTER);
//调用生成函数生成随机数
int32_t status = hks_gen_random(random->data, random->size);
//检查状态并返回代码
hks_check_return_code(status, &status);
return status;
}
2. hks_service_hmac
函数功能:hmac服务
根据传入算法需求不同采用不同的算法对数据进行hash——sha算法的加密。
注:
- 安全散列算法SHA(Secure Hash Algorithm)是美国国家安全局 (NSA) 设计,美国国家标准与技术研究院(NIST) 发布的一系列密码散列函数,包括 SHA-1、SHA-224、SHA-256、SHA-384 和 SHA-512 等变体。主要适用于数字签名标准(DigitalSignature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。
详细的SHA-256、SHA-384和SHA-512见:密码学SHA函数。
//函数功能:hmac服务
static int32_t hks_service_hmac(const struct hks_blob *key, uint32_t alg,
const struct hks_blob *src_data, struct hks_blob *output)
{
int32_t status = 0;
//根据传入算法需求不同采用不同的算法对数据进行hash——sha算法的加密
/*Hash值长度依次为256位、384位和512位,分别称为SHA-256、SHA-384和SHA-512,这些算法统称为SHA-2。
SHA-2同SHA-1类似,都使用同样的迭代结构和同样的模算术运算与二元逻辑操作。*/
switch (alg) {
#if defined(MBEDTLS_SHA256_C)
case hks_alg_hmac(HKS_ALG_HASH_SHA_256):
status = mbedtls_md_hmac(
mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
key->data, key->size, src_data->data, src_data->size,
output->data);
break;
#endif
#if defined(MBEDTLS_SHA512_C)
case hks_alg_hmac(HKS_ALG_HASH_SHA_384):
status = mbedtls_md_hmac(
mbedtls_md_info_from_type(MBEDTLS_MD_SHA384),
key->data, key->size, src_data->data, src_data->size,
output->data);
break;
case hks_alg_hmac(HKS_ALG_HASH_SHA_512):
status = mbedtls_md_hmac(
mbedtls_md_info_from_type(MBEDTLS_MD_SHA512),
key->data, key->size, src_data->data, src_data->size,
output->data);
break;
#endif
default:
return (hks_alg_is_hash(alg) ? HKS_ERROR_NOT_SUPPORTED :
HKS_ERROR_INVALID_ARGUMENT);
}
return mbedtls_to_hks_error(status);
}
3. hks_mbedtls_hash
函数功能:用于mbedtls hash处理的封装函数
详细代码及注解如下:
//函数功能:用于mbedtls hash处理的封装函数
static int32_t hks_mbedtls_hash(uint32_t alg, const unsigned char *input,
size_t ilen, unsigned char *output)
{
int32_t ret = 0;
switch (alg) {
#if defined(MBEDTLS_SHA256_C)
case HKS_ALG_SHA_224:
ret = mbedtls_sha256_ret(input, ilen, output, 1);
break;
case HKS_ALG_SHA_256:
ret = mbedtls_sha256_ret(input, ilen, output, 0);
break;
#endif
#if defined(MBEDTLS_SHA512_C)
case HKS_ALG_SHA_384:
ret = mbedtls_sha512_ret(input, ilen, output, 1);
break;
case HKS_ALG_SHA_512:
ret = mbedtls_sha512_ret(input, ilen, output, 0);
break;
#endif
default:
//如果switch中的case未进入,则进入默认部分,根据算法返回它是否被支持(合法)
return (hks_alg_is_hash(alg) ? HKS_ERROR_NOT_SUPPORTED :
HKS_ERROR_INVALID_ARGUMENT);
}
//返回错误状态信息
return mbedtls_to_hks_error(ret);
}
4. hks_service_hash
函数功能:hash服务(对hks_mbedtls_hash函数的进一步封装)
详细代码及注解如下:
//hash服务(对hks_mbedtls_hash函数的进一步封装)
int32_t hks_service_hash(uint32_t alg, const struct hks_blob *src_data,
struct hks_blob *hash)
{
//检查算法选择是否合规,src与hash数据是否满足条件
hks_if_true_return_error(((alg != HKS_ALG_HASH_SHA_256) &&
(alg != HKS_ALG_HASH_SHA_512)), HKS_ERROR_INVALID_ARGUMENT);
hks_if_true_return_error(((src_data == NULL) || (src_data->data == NULL) ||
(src_data->size <= 0)), HKS_ERROR_NULL_POINTER);
hks_if_true_return_error(((hash == NULL) || (hash->data == NULL)),
HKS_ERROR_NULL_POINTER);
hks_if_true_return_error((((alg == HKS_ALG_HASH_SHA_256) &&
(hash->size < HKS_HASH256_MIN_OUT_SIZE)) ||
((alg == HKS_ALG_HASH_SHA_512) &&
(hash->size < HKS_HASH512_MIN_OUT_SIZE))),
HKS_ERROR_BUF_TOO_SMALL);
//调用hks_mbedtls_hash函数
int32_t status = hks_mbedtls_hash(alg, src_data->data, src_data->size,
hash->data);
//返回检查结果
hks_check_return_code(status, &status);
//从算法中获取hash值大小
status = hks_get_size_from_algrithom(alg, &hash->size);
hks_if_status_error_return(status);
return status;
}
本篇小结
本篇主要讲述了密钥相关部分以及有关算法选用以及通过算法获取密钥信息部分的相关代码,接下来将会继续更新有关非对称签名与认证部分以及管理服务部分和安全模块封装相关的代码解释,敬请期待!