OpenHarmony源码分析之分布式软总线:authmanager/auth_conn.c

一、概述

本文将详细分析auth_conn.c文件的源码,该文件主要为设备间的身份可信认证过程提供了数据发送、数据接收、认证、获取秘钥等功能,如认证数据的处理、构造回复消息、构造请求消息等。

DD一下: 欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。

erlang 复制代码
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

二、源码分析

auth_conn.c

scss 复制代码
/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "auth_conn.h"
#include <string.h>
#include "aes_gcm.h"
#include "auth_interface.h"
#include "os_adapter.h"
#include "securec.h"
#include "tcp_socket.h"
/*发送身份认证连接消息*/
int AuthConnSend(int fd, const char *buf, int offset, int count, int timeout)
{
    if ((buf == NULL) || (offset < 0) || (count <= 0) || (offset + count <= 0)) {
        return -1;
    }
    return TcpSendData(fd, buf + offset, count, timeout);//发送数据
}
/*
函数功能:接收设备认证过程中传输的数据
函数参数:
    fd:用于TCP通信的套接字fd
    buf:数据缓冲区首地址
    offset:缓冲区数据偏移
    count:缓冲区剩余量
    timeout:超时时间
函数返回值:
    成功:返回收到的数据大小
    失败:返回-1
详细:
*/
int AuthConnRecv(int fd, char *buf, int offset, int count, int timeout)
{
    if ((buf == NULL) || (offset < 0) || (count <= 0) || (offset + count <= 0)) {//健壮性检查,越界检查
        return -1;
    }
    return TcpRecvData(fd, buf + offset, count, timeout);//传入数据偏移后的地址,用于存储新收到的数据
}
/*
函数功能:根据module参数判断是否使用密文传输
函数参数:
    module:数据包类型
函数返回值:
    若数据包类型在MODULE_TRUST_ENGINE和MODULE_HICHAIN_SYNC之间,以及MODULE_AUTH_CHANNEL和MODULE_AUTH_MSG之间,则返回false,表示以明文传输
    若数据包类型不在上述区间,则返回true,表示以密文传输
详细:
*/
bool ModuleUseCipherText(int module)
{
    if (module >= MODULE_TRUST_ENGINE && module <= MODULE_HICHAIN_SYNC) {
        return false;
    }
    if (module >= MODULE_AUTH_CHANNEL && module <= MODULE_AUTH_MSG) {
        return false;
    }
    return true;
}
/*
函数功能:获取加密传输数据
函数参数:
    seqNum:数据包序列号
    dataIn:要传输的实际内容
    data:数据包负载部分偏移地址
    dataLen:数据包负载部分的长度
    bufLen:用于存储整个数据包的缓冲区大小
函数返回值:
    成功:返回0
    失败:返回-1
详细:
*/
static int GetEncryptTransData(long long seqNum, const char *dataIn, unsigned char *data, unsigned int dataLen,
    int *bufLen)
{
    SessionKey *skey = AuthGetNewSessionKey();//获取一个新的会话密钥
    if (skey == NULL) {
        return -1;
    }
    if (memcpy_s(data, sizeof(int), &skey->index, sizeof(int)) != EOK) {//为负载部分加上index字段
        return -1;
    }
    data += sizeof(int);
    AesGcmCipherKey cipherKey = {0};
    cipherKey.keybits = GCM_KEY_BITS_LEN_128;//密钥位数
    int ret = memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, skey->key, AUTH_SESSION_KEY_LEN);//将获取到的会话密钥赋给当前要进行加密的密钥
    unsigned char* randomIv = GenerateRandomIv();//产生随机IV值
    if (randomIv == NULL) {
        return -1;
    }
    ret += memcpy_s(cipherKey.iv, IV_LEN, randomIv, IV_LEN);
    free(randomIv);
    ret += memcpy_s(cipherKey.iv, sizeof(seqNum), &seqNum, sizeof(seqNum));//???
    if (ret != 0) {
        return -1;
    }
    int cipherLen = EncryptTransData(&cipherKey, (const unsigned char*)dataIn, strlen(dataIn), data, dataLen);//加密传输数据
    if (cipherLen <= 0) {
        return -1;
    }
    *bufLen = cipherLen + PACKET_HEAD_SIZE + MESSAGE_INDEX_LEN;//更新bufLen的值,代表整个数据包的大小
    return 0;
}
/*
函数参数:按字节构造设备身份认证数据包
函数参数:
    module:数据包类型
    flags:数据包头部标志位
    seqNum:数据包序列号
    str:实际要传输的数据内容
    bufLen:保存数据包的缓冲区大小,整个数据包大小(传输层以上)
函数返回值:
    成功:返回数据包缓冲区首地址
    失败:返回NULL
详细:
*/
unsigned char* AuthConnPackBytes(int module, int flags, long long seqNum, const char *str, int *bufLen)
{
    if ((str == NULL) || (bufLen == NULL)) {
        return NULL;
    }
    bool isCipherText = ModuleUseCipherText(module);//根据module参数判断是否使用密文传输
    int dataLen = isCipherText ? (strlen(str) + MESSAGE_ENCRYPT_OVER_HEAD_LEN) : strlen(str);
    int len = dataLen + PACKET_HEAD_SIZE;//数据包总长度
    unsigned char *buf = (unsigned char *)calloc(1, sizeof(unsigned char) * len);//申请保存数据包的内存空间
    if (buf == NULL) {
        return NULL;
    }
    unsigned char *data = buf;//用一个局部指针变量来作为偏移地址
    //构造认证数据包头部
    int identifier = PKG_HEADER_IDENTIFIER;
    unsigned int ret = (unsigned int)memcpy_s(data, sizeof(int), &identifier, sizeof(int));
    data += sizeof(int);
    ret |= (unsigned int)memcpy_s(data, sizeof(int), &module, sizeof(int));
    data += sizeof(int);
    ret |= (unsigned int)memcpy_s(data, sizeof(long long), &seqNum, sizeof(long long));
    data += sizeof(long long);
    ret |= (unsigned int)memcpy_s(data, sizeof(int), &flags, sizeof(int));
    data += sizeof(int);
    ret |= (unsigned int)memcpy_s(data, sizeof(int), &dataLen, sizeof(int));
    data += sizeof(int);
    if (ret != 0) {
        free(buf);
        return NULL;
    }
    if (isCipherText) {//若使用密文传输
        if (GetEncryptTransData(seqNum, str, data, dataLen, bufLen) != 0) {
            free(buf);
            return NULL;
        }
    } else {
        if (memcpy_s(data, dataLen, str, dataLen) != EOK) {
            free(buf);
            return NULL;
        }
        *bufLen = len;//更新bufLen的值,代表整个数据包的大小
    }
    return buf;
}
/*
函数功能:按字节构造身份认证连接的POST消息并通过TCP协议发送
函数参数:
    fd:通信fd
    module:数据包类型
    flags:消息类型标记
    seq:数据包序列号
    data:负载数据
函数返回值:
    成功:返回0
    失败:返回-1
详细:
*/
int AuthConnPostBytes(int fd, int module, int flags, long long seq, const char *data)
{
    if (data == NULL) {
        return -1;
    }
    int bufLen = 0;
    unsigned char *buf = AuthConnPackBytes(module, flags, seq, data, &bufLen);//构造身份认证数据包
    if (buf == NULL) {
        return -1;
    }
    int ret = AuthConnSend(fd, (char *)buf, 0, bufLen, 0);//通过TCP发送认证消息
    free(buf);
    buf = NULL;
    if (ret != bufLen) {
        SOFTBUS_PRINT("[AUTH] AuthConnPostBytes send fail\n");
        return -1;
    }
    return 0;
}
/*
函数功能:构造/封装身份认证Post消息并发送给对端
函数参数:
    fd:通信fd
    module:数据包类型
    flags:消息类型标记
    seqNum:数据包序列号
    msg:cJSON格式的数据负载
函数返回值:
    成功:返回0
    失败:返回-1
详细:
*/
int AuthConnPostMessage(int fd, int module, int flags, long long seqNum, const cJSON *msg)
{
    if (msg == NULL) {
        return -1;
    }
    char *msgStr = cJSON_PrintUnformatted(msg);//将cJSON对象输出为无格式的字符串
    if (msgStr == NULL) {
        return -1;
    }
    int ret = AuthConnPostBytes(fd, module, flags, seqNum, msgStr);//按字节构造身份认证连接的POST消息并通过TCP协议发送
    free(msgStr);
    msgStr = NULL;
    return ret;
}
相关推荐
SuperHeroWu717 分钟前
【HarmonyOS 5】鸿蒙检测系统完整性
华为·harmonyos·模拟器·系统完整性·越狱设备
慧一居士31 分钟前
Kafka批量消费部分处理成功时的手动提交方案
分布式·后端·kafka
京东云开发者39 分钟前
Taro on Harmony :助力业务高效开发纯血鸿蒙应用
harmonyos
搞不懂语言的程序员1 小时前
如何实现Kafka的Exactly-Once语义?
分布式·kafka·linq
ErizJ1 小时前
Golang|分布式索引架构
开发语言·分布式·后端·架构·golang
前端付豪2 小时前
2、ArkTS 是什么?鸿蒙最强开发语言语法全讲解(附实操案例)
前端·后端·harmonyos
zhujiaming2 小时前
鸿蒙端应用适配使用开源flutter值得注意的一些问题
前端·flutter·harmonyos
前端付豪2 小时前
8、鸿蒙动画开发实战:做一个会跳舞的按钮!(附动效示意图)
前端·后端·harmonyos
前端付豪2 小时前
3、构建你的第一个鸿蒙组件化 UI 页面:实现可复用的卡片组件(附实战代码)
前端·后端·harmonyos
前端付豪2 小时前
7、打造鸿蒙原生日历组件:自定义 UI + 数据交互(附实操案例与效果图)
前端·后端·harmonyos