> 文档中心 > OpenHarmony深度解读之分布式软总线:authmanager模块(4)/设备身份认证过程

OpenHarmony深度解读之分布式软总线:authmanager模块(4)/设备身份认证过程


一、概述

authmanager模块是鸿蒙为设备提供认证机制的模块。模块内的主要处理过程包括报文的接收、解密、再次封装、加密、发送的步骤。本文将继续介绍设备身份认证过程的细节。

二、源码分析

本文源代码主要是位于wifi_auth_manager.c文件中。

  1. 函数 OnDataReceived() 中处理认证协议数据包负载部分。
/*函数功能:处理接收到的认证协议数据包数据负载部分函数参数:    conn:认证设备连接信息结构体    pkt:认证协议数据包头部结构体的地址    data:数据负载部分的起始地址函数返回值:无详细:*/static void OnDataReceived(AuthConn *conn, const Packet *pkt, const char *data){    SOFTBUS_PRINT("[AUTH] OnDataReceived\n");    //如果module字段为MODULE_AUTH_SDK,则调用AuthInterfaceOnDataReceived继续进行处理。这里没有直接用==,是为了可扩展性    if ((pkt->module > MODULE_HICHAIN) && (pkt->module <= MODULE_AUTH_SDK)) {    //若数据包类型为MODULE_AUTH_SDK,表示对端请求创建设备身份认证环境(暂定) AuthInterfaceOnDataReceived(conn, pkt->module, pkt->seq, data, pkt->dataLen); return;    }//解密消息,返回cJSON结构体格式的数据    cJSON *msg = DecryptMessage(pkt->module, data, pkt->dataLen);    if (msg == NULL) { SOFTBUS_PRINT("[AUTH] OnDataReceived DecryptMessage fail\n"); return;    }//根据数据包类型字段module,对接收到的cJSON数据选择不同的处理方式    OnModuleMessageReceived(conn, pkt->module, pkt->flags, pkt->seq, msg);    cJSON_Delete(msg);    msg = NULL;}
  1. 若数据包类型不属于MODULE_HICHAINMODULE_AUTH_SDK之间,则应是加密消息,首先进行解密,在函数 DecryptMessage() 中实现。
/*函数功能:对接收到的消息进行解密函数参数:    module:数据包类型    data:数据起始地址    dataLen:数据长度函数返回值:    成功:返回解密后的cJSON格式的数据    失败:返回NULL详细:*/static cJSON *DecryptMessage(int module, const char *data, int dataLen){    if (data == NULL) { return NULL;    }    if (!ModuleUseCipherText(module)) {//根据数据包类型判断该数据包负载部分是否加密    //若是明文传输,则直接解析为cJSON结构体格式的数据 return DecryptPlainMessage(data, dataLen);    }    if (dataLen < MESSAGE_ENCRYPT_OVER_HEAD_LEN) {//检查数据包是否合法 return NULL;    }    int index = GetKeyIndex(data, 0, MESSAGE_INDEX_LEN);//解析会话密钥索引    //根据会话密钥索引查找并获取会话密钥    SessionKey *sKey = AuthGetSessionKeyByIndex(index);    if (sKey == NULL) { SOFTBUS_PRINT("[AUTH] DecryptMessage get session key fail\n"); return NULL;    }//获取数据包实际有效负载长度(即加密部分的长度)    unsigned int len = dataLen - MESSAGE_ENCRYPT_OVER_HEAD_LEN + 1;    unsigned char *output = malloc(len);//申请解密后的数据存储空间    if (output == NULL) { return NULL;    }    if (memset_s((void *)output, len, 0, len) != EOK) { free(output); output = NULL; return NULL;    }    AesGcmCipherKey cipherKey = {0};//定义一个临时会话密钥    cipherKey.keybits = GCM_KEY_BITS_LEN_128;//密钥长度为128位    int ret = memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, sKey->key, AUTH_SESSION_KEY_LEN);//初始化密钥    ret += memcpy_s(cipherKey.iv, IV_LEN, data + MESSAGE_INDEX_LEN, IV_LEN);//初始化IV    if (ret != 0) { free(output); output = NULL; return NULL;    }//解密,结果保存在output缓冲区中    ret = DecryptTransData(&cipherKey, (unsigned char*)&data[MESSAGE_INDEX_LEN], dataLen - MESSAGE_INDEX_LEN, output, len);    if (ret <= 0) { SOFTBUS_PRINT("[AUTH] DecryptMessage DecryptTransData fail\n"); free(output); output = NULL; return NULL;    }//将output中字符串格式的json数据转换为cJSON结构体    cJSON *msg = cJSON_Parse((char*)output);    free(output);    output = NULL;    return msg;}
  1. 根据数据包类型字段module,对接收到的cJSON数据选择不同的处理方式,在函数OnModuleMessageReceived() 中实现。
/*函数功能:根据数据包类型字段module,对接收到的cJSON数据选择不同的处理方式函数参数:    conn:认证设备连接信息    module:数据包类型    flags:数据包头部标记    seq:数据包序列号    msg:cJSON数据函数返回值:无详细:*/static void OnModuleMessageReceived(AuthConn *conn, int module, int flags, long long seq, const cJSON *msg){    switch (module) { case MODULE_TRUST_ENGINE: {//如果是MODULE_TRUST_ENGINE类型,表明是可信设备 //如果此数据包不是"回复数据包",那么表明对端是请求端     if (((unsigned int)flags & FLAG_REPLY) == 0) {  OnMsgOpenChannelReq(conn, seq, msg);//处理请求消息     }     break; } case MODULE_CONNECTION: {//如果是MODULE_CONNECTION类型,表明是连接设备     OnMessageReceived(conn, seq, msg);//处理接收到的消息,解析并按规则回复给对端     break; } default: {     break; }    }    return;}