> 文档中心 > OpenHarmony解读之设备认证:数据接收管理-获取HiChain实例(2)

OpenHarmony解读之设备认证:数据接收管理-获取HiChain实例(2)


一、概述

上一篇博客 OpenHarmony解读之设备认证:数据接收管理-获取HiChain实例(1)介绍了hichain实例获取的部分内容,本文将继续进行分析。
在上一篇博客介绍的get_instance函数中,在进行完密钥等信息的初始化之后,调用build_self_lt_key_pair函数创建属于本端的长期保存的密钥对,这个密钥对初步分析是用于设备之间的身份可信认证。创建密钥对部分可分为四个阶段:1、获取协议参数。2、生成服务id。3、生成密钥别名。4、生成长期保存的密钥对。下面将对build_self_lt_key_pair函数及其涉及到的相关函数进行详细分析,重点分析第一个阶段的内容。

二、源码分析

这一模块的源码位于:/base/security/deviceauth。

  1. 首先总体分析函数build_self_lt_key_pair,具体如下:
/*函数功能:构建自己的long term store密钥对函数参数:    hichain:HiChain实例对象,传入传出参数函数返回值:无*/static void build_self_lt_key_pair(const struct hichain *hichain){    struct hc_pin pin = { 0, {0} };    struct operation_parameter para;//定义操作参数    (void)memset_s(&para, sizeof(para), 0, sizeof(para));//清空操作参数空间    hichain->cb.get_protocol_params(&hichain->identity, GENERATE_KEY_PAIR, &pin, &para);//设备可信认证过程:获取协议参数,主要获取认证会话密钥长度、对端认证id和本端认证id    if (para.self_auth_id.length > 0) {//获取成功 struct service_id service_id = generate_service_id(&hichain->identity);//生成服务id(HC包名称和服务类型进行哈希之后的值) if (service_id.length == 0) {//生成服务id失败则直接返回     LOGE("Generate service id failed");//日志信息     return; }#if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))//如果支持这两种机制 struct hc_key_alias alias = generate_key_alias(&service_id, &para.self_auth_id, KEY_ALIAS_LT_KEY_PAIR);#else struct hc_key_alias alias = generate_key_alias(&service_id, &para.self_auth_id, KEY_ALIAS_ACCESSOR_PK);//通过服务id和认证id(service id and auth id)生成密钥别名//类型为KEY_ALIAS_ACCESSOR_PK#endif if (alias.length == 0) {//生成密钥别名失败则直接返回     LOGE("Generate key alias failed");     return; }//成功生成密钥别名 int32_t ret = check_lt_public_key_exist(&alias);//根据别名判断long term公钥是否存在 if (ret != HC_OK) {//如果不存在     ret = generate_lt_key_pair(&alias, &para.self_auth_id);//生成自己本端的长期存储有效的密钥对Generate a long-lived key pair ED25519     if (ret != HC_OK) {  LOGE("Generate self ltpk return value is %d", ret);  return;}     DBG_OUT("Generate self ltpk ok"); }    }}
  1. 然后,对build_self_lt_key_pair函数进行逐阶段分析,在此函数中,首先是调用回调函数get_protocol_params获取协议参数,此函数的实现位于分布式软总线模块的auth_interface.c文件中,函数名为AuthGetProtocolParams,具体分析如下:
/*函数功能:设备可信认证过程:获取协议参数,主要获取认证会话密钥长度、对端认证id和本端认证id函数参数:    identity:认证会话标识    operationCode:操作码    hcPin:HC PIN码    para:操作参数函数返回值:无详细:    操作参数结构如下://操作参数struct operation_parameter {    struct hc_auth_id self_auth_id;//本端认证id    struct hc_auth_id peer_auth_id;//对端认证id    uint32_t key_length;//密钥长度};*/static void AuthGetProtocolParams(const struct session_identity *identity, int32_t operationCode,    struct hc_pin *hcPin, struct operation_parameter *para){    (void)operationCode;//此处未使用到这个参数,但为了避免编译器发出警告,做此处理    (void)hcPin;//此处未使用到这个参数,但为了避免编译器发出警告,做此处理    if (identity == NULL || para == NULL) {//参数有效性检查 return;    }    para->key_length = AUTH_SESSION_KEY_LEN;//赋值认证会话密钥长度    AuthSession *authSes = AuthGetAuthSessionBySessionId(identity->session_id);//根据会话id获取认证会话    if (authSes == NULL || authSes->conn == NULL) {//若认证会话为空或者该会话维护的连接为空,则返回错误 SOFTBUS_PRINT("[AUTH] AuthGetProtocolParams get session fail\n"); return;    }    para->peer_auth_id.length = strlen(authSes->conn->authId);//赋值对端认证id长度    int ret = memcpy_s(para->peer_auth_id.auth_id, sizeof(para->peer_auth_id.auth_id),  authSes->conn->authId, strlen(authSes->conn->authId));//将该认证会话维护的认证连接的认证id赋给操作参数中的对端认证id    if (ret != EOK) {//若拷贝失败,则返回 return;    }    DeviceInfo *info = BusGetLocalDeviceInfo();//获取本地设备信息    if (info == NULL) {//获取失败则返回 return;    }    para->self_auth_id.length = strlen(info->deviceId);//赋值本端认证id长度为设备id长度    ret = memcpy_s(para->self_auth_id.auth_id, sizeof(para->self_auth_id.auth_id),     info->deviceId, strlen(info->deviceId));//将本地设备id赋给操作参数中的本端认证id    if (ret != EOK) {//若拷贝失败,则返回 return;    }    SOFTBUS_PRINT("[AUTH] AuthGetProtocolParams ok\n");//打印日志信息    return;}
  1. 在函数AuthGetProtocolParams中调用了AuthGetAuthSessionBySessionId函数获取认证会话信息,具体分析如下:
*函数功能:根据会话id查询全局认证会话表,获取认证会话函数参数:    sessionId:会话id函数返回值:    成功:返回指向认证会话结构体的指针    失败:返回NULL详细:*/static AuthSession *AuthGetAuthSessionBySessionId(uint32_t sessionId){    if (g_authSessionMap == NULL) {//检查全局认证会话表是否为空 return NULL;    }    for (int i = 0; i < AUTH_SESSION_MAX_NUM; i++) {//遍历全局认证会话表 if (g_authSessionMap[i].isUsed == 0) {     continue; } if (g_authSessionMap[i].sessionId == sessionId) {//根据会话id定位到对应的认证会话     return &g_authSessionMap[i];//返回该会话指针 }    }    return NULL;}

三、小结

本文重点分析了hichain实例获取阶段的本端密钥对生成函数build_self_lt_key_pair的部分内容,对该函数进行了总体的分析,也对该函数中调用的分布式软总线模块的回调函数AuthGetProtocolParams进行了详细的分析,但是由于篇幅有限,其余内容将在下一篇博客中进行介绍。