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

📌往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)

①📖 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

②📖嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

③📖 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

④📖 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

⑤📖 记录一场鸿蒙开发岗位面试经历~

⑥📖 持续更新中……


一、概述

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

二、源码分析

auth_conn.c

/*
 * 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值