security_huks模块下hks_client.c代码评注(上)
hks_client.c总述
hks_client.c是基于用户的hks安全模块的函数集成,其中囊括了hw_keystore_sdk当中主要文件夹common和soft_service当中的大部分功能模块。它将具体的功能封装成函数,在一些传入参数判空检查、格式大小检查的基础上再进一步调用核心模块,不仅提高了函数执行的效率,还提高了代码的鲁棒性和可读性,这样的代码思路值得我们学习。下面,就让我们深入hks_client.c的内容,一起来探索吧。
本篇的下篇部分详见:security_huks模块下hks_client.c代码评注(下)
代码关键部分模块框架
hks_client.c
├── include
│ └── "hks_client.h"
│ └── "hks_access.h"
│ └── "soft_service/hks_service.h"
│ └── "hks_types.h"
│ └── "common/hks_common.h"
├── functions
│ └── hks_client.h
│ └── hks_get_sdk_version
│ └── hks_access.c
│ └── hks_access_generate_key
│ └── hks_access_generate_key_ex
│ └── hks_access_import_key
│ └── hks_access_export_key
│ └── hks_access_delete_key
│ └── hks_access_get_key_param
│ └── hks_access_is_key_exist
│ └── hks_access_sign
│ └── hks_access_verify
│ └── hks_access_aead_encrypt
│ └── hks_access_aead_decrypt
│ └── hks_access_key_derivation
│ └── hks_access_key_agreement
│ └── hks_access_get_random
│ └── hks_access_hmac
│ └── hks_access_hash
│ └── hks_access_bn_exp_mod
│ └── hks_access_get_pub_key_alias_list
│ └── hks_access_init
│ └── hks_access_destroy
│ └── hks_access_refresh_key_info
│ └── hks_service.c
│ └── hks_service_register_file_callbacks
│ └── hks_service_register_get_hardware_udid_callback
│ └── hks_log_utils.c
│ └── hks_register_log
各模块详解
导入库函数与预编译
该模块包括了所需要的用到的头文件,其中#include "hks_access.h"尤为重要,本篇中大量的函数的调用都在 "hks_access.h"中有声明,且函数原型在 "hks_access.c"中。
#include "hks_client.h"
#include "securec.h"
#include "common/hks_common.h"
#include "common/hks_log_utils.h"
#include "hks_errno.h"
#include "hks_file_api.h"
#include "hks_hardware_api.h"
#include "hks_types.h"
#include "soft_service/hks_service.h"
#include "hks_access.h"
/* AES-GCM encrypt IV minimum size,96bit=12bytes */
//AES-GCM加密IV最小尺寸,96bit=12字节
#define HKS_AES_GCM_MIN_IV_LENGTH 12
获取版本号
需要注意的是:#define HKS_SDK_VERSION “1.0.0.10” 初始版本号为1.0.0.10,因此后序版本号都是在此基础上的拓展。代码如下:
//获取sdk版本号
void hks_get_sdk_version(struct hks_blob *sdk_version)
{
if (sdk_version == NULL)
return;
//#define HKS_SDK_VERSION "1.0.0.10"
const size_t version_len = strlen(HKS_SDK_VERSION);
if ((sdk_version->data != NULL) && (sdk_version->size > version_len)) {
//将版本号写入data数组中
if (memcpy_s(sdk_version->data, sdk_version->size, HKS_SDK_VERSION, version_len) != EOK) {
log_error("memcpy_s fail");
return;
}
sdk_version->data[version_len] = '\0';//末位标记
sdk_version->size = (uint32_t)version_len + 1;
}
}
密钥相关函数集(上)
这里包括了密钥的生成、公有密钥的导入导出、密钥的删除、获取密钥详细信息、判断密钥是否存在、hks非对称性标记与检验一系列函数。
需要注意的是:
-
HKS_DLL_API_PUBLIC 在hks_types.h中有定义,
定义如下:#define HKS_DLL_API_PUBLIC __declspec(dllimport),
详细意义见知识提点:DLL编程的导入导出部分。 -
函数:hks_if_true_return_error
它的作用在于检查各参数信息是否合规/* * warning: this macro function only can be used in the beginnig of * each function * do not use it after malloc, alloc etc. you can use goto statement instead */ #define hks_if_true_return_error(s, err) \ if ((s) == HKS_BOOL_TRUE) { \ log_error("%s %d return status: %d.\n", __func__, __LINE__, (err)); return err; }
-
HKS_status_OK
对于当前接口,如果status为HKS status OK表示key存在,others表示key不存在或出现错误
系列代码及注解如下:
//#define HKS_DLL_API_PUBLIC __declspec(dllimport)
//生成密匙
HKS_DLL_API_PUBLIC int32_t hks_generate_key(const struct hks_blob *key_alias,
const struct hks_key_param *key_param)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
HKS_TRACE_IN;
//检查上级状态:用户id与别名是否为success
hks_if_status_error_return(hks_is_valid_auth_id(key_param));
hks_if_status_error_return(hks_is_valid_alias(key_alias));
//检查密匙参数类型信息
if (key_param->key_type != HKS_KEY_TYPE_EDDSA_KEYPAIR_ED25519)
return HKS_ERROR_NOT_SUPPORTED;
//执行生成秘钥函数,返回生成密匙的key_alias和key_param信息
return hks_access_generate_key(key_alias, key_param);
#endif
}
//生成非对称密匙
HKS_DLL_API_PUBLIC int32_t hks_generate_asymmetric_key(
const struct hks_key_param *key_param, struct hks_blob *pri_key,
struct hks_blob *pub_key)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
HKS_TRACE_IN;
hks_if_true_return_error((key_param == NULL), HKS_ERROR_NULL_POINTER);
//检查密匙参数类型信息
if (key_param->key_type != HKS_KEY_TYPE_ECC_KEYPAIR_CURVE25519)
return HKS_ERROR_NOT_SUPPORTED;
//检查密匙参数模式信息
if (key_param->key_mode != hks_alg_ecdh(HKS_ALG_SELECT_RAW))
return HKS_ERROR_NOT_SUPPORTED;
//检查密钥参数验证模式 私有密匙与公有密匙是否为空
if ((pri_key == NULL) || (pri_key->data == NULL) || (pub_key == NULL) ||
(pub_key->data == NULL))
return HKS_ERROR_NULL_POINTER;
//执行生成密匙对对应函数
return hks_access_generate_key_ex(key_param, pri_key, pub_key);
#endif
}
//hks导入公有密匙
HKS_DLL_API_PUBLIC int32_t hks_import_public_key(
const struct hks_blob *key_alias,
const struct hks_key_param *key_param, const struct hks_blob *key)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
HKS_TRACE_IN;
hks_if_status_error_return(hks_is_valid_auth_id(key_param));
int32_t status = hks_is_valid_alias(key_alias);
//判断hks_is_valid_alias的状态是否正常
if (status != HKS_STATUS_OK)
return status;
//检查密匙参数类型信息
if (key_param->key_type != HKS_KEY_TYPE_EDDSA_PUBLIC_KEY_ED25519)
return HKS_ERROR_NOT_SUPPORTED;
hks_if_true_return_error((key == NULL), HKS_ERROR_NULL_POINTER);
//检查密匙内容以及大小是否合规
if ((key->data == NULL) || (key->size != CRYPTO_PUBLIC_KEY_BYTES))
return HKS_ERROR_INVALID_PUBLIC_KEY;
//执行hks存取导入密匙信息对应函数
return hks_access_import_key(key_alias, key_param, key);
#endif
}
//hks导出公有密匙
HKS_DLL_API_PUBLIC int32_t hks_export_public_key(
const struct hks_blob *key_alias, struct hks_blob *key)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
int32_t status = hks_is_valid_alias(key_alias);
//判断hks_is_valid_alias的状态是否正常
if (status != HKS_STATUS_OK)
return status;
if (key == NULL)
return HKS_ERROR_NULL_POINTER;
//检查密匙内容以及大小是否合规
if ((key->data == NULL) || (key->size < CRYPTO_PUBLIC_KEY_BYTES))
return HKS_ERROR_BUF_TOO_SMALL;
//执行hks获得存取出口密匙的权限对应函数
return hks_access_export_key(key_alias, key);
#endif
}
//hks删除密匙
HKS_DLL_API_PUBLIC int32_t hks_delete_key(const struct hks_blob *key_alias)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
/* to add log here track return value */
//注意:要在这里添加日志跟踪返回值
int32_t status = hks_is_valid_alias(key_alias);
//判断hks_is_valid_alias的状态是否正常
if (status != HKS_STATUS_OK)
return status;
//执行删除密匙信息对应的函数
return hks_access_delete_key(key_alias);
#endif
}
//hks获取密匙参数信息
HKS_DLL_API_PUBLIC int32_t hks_get_key_param(const struct hks_blob *key_alias,
struct hks_key_param *key_param)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
int32_t status = hks_is_valid_alias(key_alias);
if (status != HKS_STATUS_OK)
return status;
if (key_param == NULL)
return HKS_ERROR_NULL_POINTER;
//执行hks获得密匙参数信息对应的函数
return hks_access_get_key_param(key_alias, key_param);
#endif
}
/*
* For current interface, if status is HKS_STATUS_OK
* means key exist, others means key does not exist or error occurs
*/
//对于当前接口,如果status为HKS status OK表示key存在,others表示key不存在或出现错误
//hks判断密匙是否存在
HKS_DLL_API_PUBLIC int32_t hks_is_key_exist(const struct hks_blob *key_alias)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
int32_t status = hks_is_valid_alias(key_alias);
//如果该密钥可用,判断是否存在并且返回状态值
if (status != HKS_STATUS_OK)
return status;
status = hks_access_is_key_exist(key_alias);
return status;
#endif
}
//hks非对称标记
HKS_DLL_API_PUBLIC int32_t hks_asymmetric_sign(
const struct hks_blob *key_alias,
const struct hks_key_param *key_param, const struct hks_blob *hash,
struct hks_blob *signature)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
int32_t status = hks_is_valid_alias(key_alias);
//检查key_alias的状态是否正常
hks_if_status_error_return(status);
//检查密匙参数、hash方法、签名是否为空
hks_if_true_return_error(((key_param == NULL) || (hash == NULL) ||
(signature == NULL)), HKS_ERROR_NULL_POINTER);
//检查密匙参数类型、应用是否合规
if ((key_param->key_type != HKS_KEY_TYPE_EDDSA_KEYPAIR_ED25519) ||
((key_param->key_usage & HKS_KEY_USAGE_SIGN) == 0))
return HKS_ERROR_NOT_SUPPORTED;
//检查hash规则内容与大小
if ((hash->data == NULL) || (hash->size <= 0))
return HKS_ERROR_INVALID_ARGUMENT;
//检查签名内容与大小
if ((signature->data == NULL) ||
(signature->size < HKS_SIGNATURE_MIN_SIZE))
return HKS_ERROR_BUFFER_TOO_SMALL;
//执行hks存取签署信息对应函数
return hks_access_sign(key_alias, key_param, hash, signature);
#endif
}
//hks非对称性检验
HKS_DLL_API_PUBLIC int32_t hks_asymmetric_verify(const struct hks_blob *key,
const struct hks_key_param *key_param, const struct hks_blob *hash,
const struct hks_blob *signature)
{
#ifdef _CUT_AUTHENTICATE_
return HKS_ERROR_NOT_SUPPORTED;
#else
//先检查函数传入的参数是否有空值
hks_if_true_return_error(((key == NULL) || (key_param == NULL) ||
(hash == NULL) || (signature == NULL)), HKS_ERROR_NULL_POINTER);
int32_t status;
if (key->type == HKS_BLOB_TYPE_ALIAS) {
status = hks_is_valid_alias(key);
hks_if_status_error_return(status);
//当密匙的类型为alias类型时候,检查密匙的可用性然后将检查结果状态值返回
} else if (key->type == HKS_BLOB_TYPE_KEY) {
//密匙参数中的密匙类型不为公匙ED25519则函数退出
if (key_param->key_type != HKS_KEY_TYPE_EDDSA_PUBLIC_KEY_ED25519)
return HKS_ERROR_NOT_SUPPORTED;
if ((key->data == NULL) || (key->size != HKS_PUBLIC_BYTES_ED25519))
return HKS_ERROR_INVALID_KEY_INFO;
//检查密匙数据的合法性
} else {
return HKS_ERROR_INVALID_KEY_INFO;
}
//检查密匙参数中的usage属性
if ((key_param->key_usage & HKS_KEY_USAGE_VERIFY) == 0)
return HKS_ERROR_NOT_SUPPORTED;
//检查hash方法的内容及大小
if ((hash->data == NULL) || (hash->size <= 0))
return HKS_ERROR_INVALID_ARGUMENT;
//检查签名内容与大小
if ((signature->data == NULL) || (signature->size < HKS_SIGNATURE_MIN_SIZE))
return HKS_ERROR_INVALID_ARGUMENT;
return hks_access_verify(key, hash, signature);
#endif
}
知识提点
DLL编程的导入导出
#ifdef _EXPORTING
#define API_DECLSPEC __declspec(dllexport)
#else
#define API_DECLSPEC __declspec(dllimport)
#endif
这个宏,是为了便于开发和使用自己写的dll库的。
用同样的 API_DECLSPEC 类型声明,在dll的.cpp文件里,添加
#define _EXPORTING
则 API_DECLSPEC 为输出库。
在调用dll方,无 #define _EXPORTING,则 API_DECLSPEC 为输入库。
这样,用于dll的.h文件,可以直接用于调用dll的项目中。
常用传参结构体类型
-
hks_blob:主要用来定义密钥、密钥别名、hash算法、签名署名类型,如:
const struct hks_blob *key_alias, const struct hks_key_param *key_param, const struct hks_blob *hash, struct hks_blob *signature
它包含了密钥的类型,数据内容以及密钥的大小信息。
struct hks_blob { uint8_t type; uint8_t *data; uint32_t size; };
-
hks_key_param:主要用来定义密钥参数类型,其中包含了密钥使用的算法、密钥的应用、密钥使用的填充模式、密钥所属的组别模式以及密钥的域和角色等信息。
struct hks_key_param { uint32_t key_type; /*使用算法类型*/ uint32_t key_len; uint32_t key_usage; /* 密钥的应用方法*/ uint32_t key_pad; /*密钥的填充模式*/ uint32_t key_mode; /*密钥组模式*/ uint32_t key_role; /*密钥角色*/ uint16_t key_domain; /*密钥所属域*/ struct hks_blob key_auth_id; /*密钥对应的用户id*/ };
3.hks_crypt_param:主要用来定义加密参数类型,代码如下:
struct hks_crypt_param { struct hks_blob nonce; //没有值或iv向量 struct hks_blob aad; };
上述常用传参结构体能在security_huks\interfaces\innerkits\huks_lite\hks_types.h中找到,此处提出的原因在于多数函数的形式参数类型定义都为以上几种,其余类型不再赘述。
下篇我们将继续介绍hks_client.c的剩余代码!