文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

OpenHarmony蓝牙自动配对流程分析

2024-11-30 07:45

关注

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

前言

大家在实际使用蓝牙时会发现,有些蓝牙设备配对需要输入配对码,有些蓝牙设备则会自动配对;那这些设备有什么区别,OpenHarmony的蓝牙协议栈又是怎么实现的呢?本文对此进行分析和解读。

蓝牙协议分析

SSP(SECURE SIMPLE PAIRING)时当前蓝牙协议中最推荐采用的认证配对方案;在SSP配对模式下,认证配对总体分为两步:IO Capability信息交换和用户确认。

IO Capability

蓝牙设备按照输入输出能力分为四类,以设备A作Initiator组合后认证配置方式如下表:

设备B\设备A

DisplayOnly

DisplayYesNo

KeyboardOnly

NoInputNoOutput

DisplayOnly

自动配对

A用户确认,B自动配对

B显示数字,A输入

自动配对

DisplayYesNo

A自动配对,B用户确认

用户确认

B显示数字,A输入

A自动配对,B用户确认

KeyboardOnly

A显示数字,B输入

A显示数字,B输入

输入passkey

自动配对

NoInputNoOutput

自动配对

B自动配对,A用户确认

自动配对

自动配对

交换设备IO Capability信息流程如下图:

MITM Protection

参考蓝牙core specification Version 5.4 | Vol 4, Part E, 7.1.29,可以发现IO Capability消息中除了IO_Capability字段还包括Authentication_Requirements字段,该字段同样影响设备配对流程。

man-in-the-middle(MITM) ,中间人攻击是一种常见的攻击手法,蓝牙SSP机制在用户确认模式时可以有效防止中间人攻击。

协议规定:如果两台设备都明确指定不需要进行MITM攻击保护,设备应该按照自动匹配流程处理。

用户确认

host收到User_Confirmation_Request消息后需要按照上表中的IO Capability要求用户确认或自动回复确认信息。

OpenHarmony实现流程

IO Capability信息交换

void GapOnIOCapabilityResponseEvent(const HciIoCapabilityResponseEventParam *eventParam)
{
    LOG_DEBUG("%{public}s:" BT_ADDR_FMT "", __FUNCTION__, BT_ADDR_FMT_OUTPUT(eventParam->bdAddr.raw));
    BtAddr addr = BT_ADDR_NULL;

    GapChangeHCIAddr(&addr, &eventParam->bdAddr, BT_PUBLIC_DEVICE_ADDRESS);

    DeviceInfo *devInfo = NULL;
    devInfo = ListForEachData(GapGetConnectionInfoBlock()->devicelist, GapFindConnectionDeviceByAddr, (void *)&addr);
    if (devInfo != NULL) {
        devInfo->remoteAuthReq = eventParam->authenticationRequirements;
    }

    if (g_authenticationCallback.callback.IOCapabilityRsp) {
        g_authenticationCallback.callback.IOCapabilityRsp(
            &addr, eventParam->IOCapability, g_authenticationCallback.context);
    }
}

GapOnIOCapabilityResponseEvent函数处理对端设备的IOCapability信息,remoteAuthReq保存对端设备的认证要求;同时在ClassicAdapter模块保存对端设备IOCapability能力;这里比较奇怪的是IOCapability和remoteAuthReq分在两个模块保存。

void ClassicAdapter::SaveRemoteIoCapability(const BtAddr &addr, uint8_t ioCapability)
{
    HILOGI("enter");
    RawAddress device = RawAddress::ConvertToString(addr.addr);
    std::shared_ptr remoteDevice = FindRemoteDevice(device);
    remoteDevice->SetIoCapability(ioCapability);
}

确认处理

void GapOnUserConfirmationRequestEvent(const HciUserConfirmationRequestEventParam *eventParam)
{
    
    int localMitmRequired = GAP_MITM_REQUIRED;
    int remoteMitmRequired = GAP_MITM_REQUIRED;
    DeviceInfo *devInfo =
        ListForEachData(GapGetConnectionInfoBlock()->devicelist, GapFindConnectionDeviceByAddr, (void*)&addr);

    if (devInfo != NULL) {
        remoteMitmRequired = devInfo->remoteAuthReq & GAP_MITM_REQUIRED;
        if (devInfo->actionReq != NULL) {
            if (!devInfo->actionReq->needAuthentication && devInfo->actionReq->needUnauthentication) {
                localMitmRequired = GAP_MITM_NOT_REQUIRED;
            }
        } else {
            localMitmRequired = remoteMitmRequired;
        }
    }
    
    if (g_authenticationCallback.callback.userConfirmReq) {
        g_authenticationCallback.callback.userConfirmReq(
            &addr, eventParam->numericValue,localMitmRequired, remoteMitmRequired, g_authenticationCallback.context);
    } else {
        GapUserConfirmationRequestNegativeReply(&addr);
    }
}

GapOnUserConfirmationRequestEvent函数获取到IO Capability交换流程中保存认证要求,并获取本设备最近一次连接的认证设置,作为参数传递到ClassicAdapter::SSPConfirmReq函数进行处理。

void ClassicAdapter::SSPConfirmReq(const BtAddr &addr, int reqType, int number, 
    int localMitmRequired, int remoteMitmRequired)
{
    HILOGI("reqTyep: %{public}d", reqType);

    RawAddress device = RawAddress::ConvertToString(addr.addr);
    std::shared_ptr remoteDevice = FindRemoteDevice(device);
    remoteDevice->SetPairConfirmState(PAIR_CONFIRM_STATE_USER_CONFIRM);
    remoteDevice->SetPairConfirmType(reqType);
    int remoteIo = remoteDevice->GetIoCapability();
    if (remoteDevice->GetPairedStatus() == PAIR_CANCELING) {
        UserConfirmAutoReply(device, reqType, false);
    } else if (CheckAutoReply(remoteIo, localMitmRequired, remoteMitmRequired) == true) {
        UserConfirmAutoReply(device, reqType, true);
    } else {
        reqType = CheckSspConfirmType(remoteIo, reqType);
        SendPairConfirmed(device, reqType, number);
    }

}

ClassicAdapter::SSPConfirmReq函数取出本设备及对端设备的IOCapability,调用CheckAutoReply函数结合认证信息进行最终的综合判断:如果是自动配对,则由ClassicAdapter::SSPConfirmReq调用UserConfirmAutoReply直接确认;否则向用户显示确认信息,要求用户确认。

bool ClassicAdapter::CheckAutoReply(int remoteIo, int localMitmRequired, int remoteMitmRequired) const
{
    HILOGI("enter");

    bool autoReply = false;
    int localIo = adapterProperties_.GetIoCapability();
    HILOGI("local io capability = %{public}d <==> remote io capability = %{public}d"
        "local mitm = %{public}d <==> remote mitm = %{public}d", localIo, remoteIo, 
        localMitmRequired, remoteMitmRequired);
    
    if (localMitmRequired == GAP_MITM_NOT_REQUIRED && remoteMitmRequired == GAP_MITM_NOT_REQUIRED) {
        return true;
    }

    switch (localIo) {
        case GAP_IO_DISPLAYONLY:
            autoReply = (remoteIo != GAP_IO_KEYBOARDONLY) ? true : false;
            break;
        case GAP_IO_KEYBOARDONLY:
            autoReply = (remoteIo == GAP_IO_NOINPUTNOOUTPUT) ? true : false;
            break;
        case GAP_IO_NOINPUTNOOUTPUT:
            autoReply = true;
            break;
        default:
            break;
    }
    return autoReply;
}

总结

本文介绍了蓝牙协议中SSP认证配对过程及OpenHarmony中相关实现流程,蓝牙配对时是否会出现用户确认提示信息依赖两端设备能力,同时也依赖业务对安全性的要求;如果业务本身有其它传输加密能力,可以指定不认证方式进行连接,避免用户多次认证导致降低使用体验,如OpenHarmony软总线就是采用这种方式建立蓝牙连接。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

来源:51CTO 开源基础软件社区内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯