一 连接

同一款手机,为什么跟某些设备可以连接成功,而跟另外一些设备又连接不成功?同一个设备,为什么跟某些手机可以建立连接,而跟另外一些手机又无法建立连接?同一个手机,同一个设备,为什么他们两者有时候连起来很快,有时候连起来又很慢?Master是什么?slave又是什么?什么又是Connection event和slave latency?希望这篇文章能帮助你回答上述问题。

1 BLE连接示例

假设我们有一台手机A(以安卓手机为例),一个设备B(设备名称:Nordic_HRM),如下所示,我们可以通过安卓设置菜单里面的蓝牙界面,让两者连接起来。

  1. 打开安卓设置菜单
  2. 选择“蓝牙”条目
  3. 打开蓝牙
  4. 等待系统搜索结果,不出意外的话,设备“Nordic_HRM”会出现在结果列表中
  5. 点击“Nordic_HRM”,手机将与此设备建立连接

    上述即为大家直观感受到的“连接”,那么手机要与设备Nordic_HRM建立连接,具体包含哪些流程?他们为什么可以连接成功?下面给大家一一道来。

2 广播(advertising)

在手机跟设备B建立连接之前,设备B需要先进行广播,即设备B(Advertiser)不断发送如下广播信号,t为广播间隔。每发送一次广播包,我们称其为一次广播事件(advertising event),因此t也称为广播事件间隔。虽然图中广播事件是用一根线来表示的,但实际上广播事件是有一个持续时间的,蓝牙芯片只有在广播事件期间才打开射频模块,这个时候功耗比较高,其余时间蓝牙芯片都处于idle状态,因此平均功耗非常低,以Nordic nRF52810为例,每1秒钟发一次广播,平均功耗不到11uA。

android ble 配对方法 ble manager与手机怎么配对_BLE


上面只是一个概略图,按照蓝牙spec,实际上每一个广播事件包含三个广播包,即分别在37/38/39三个通道上同时广播相同的信息,即真正的广播事件是下面这个样子的。

android ble 配对方法 ble manager与手机怎么配对_蓝牙_02


设备B不断发送广播信号给手机(Observer),如果手机不开启扫描窗口,手机是收不到设备B的广播的,如下图所示,不仅手机要开启射频接收窗口,而且只有手机的射频接收窗口跟广播发送的发射窗口匹配成功,手机才能收到设备B的广播信号。由于这种匹配成功是一个概率事件,因此手机扫到设备B也是一个概率事件,也就是说,手机有时会很快扫到设备B,比如只需要一个广播事件,手机有时又会很慢才能扫到设备B,比如需要10个广播事件甚至更多。

android ble 配对方法 ble manager与手机怎么配对_连接配对_03

3 建立连接(connection)

根据蓝牙spec规定,advertiser发送完一个广播包之后150us(T_IFS,该值称为帧间隔,是指在同一个信道上连续两帧之间的间隔详见: 蓝牙核心卷,Vol 6, Part B,4.1.1),advertiser必须开启一段时间的射频Rx窗口,以接收来自observer的数据包。Observer就可以在这段时间里给advertiser发送连接请求。如下图所示,手机在第三个广播事件的时候扫到了设备B,并发出了连接请求conn_req。

android ble 配对方法 ble manager与手机怎么配对_连接配对_04


上图的交互流程比较粗略,为此我们引入下图,以详细描述连接建立过程。

android ble 配对方法 ble manager与手机怎么配对_连接配对_05


图5:连接建立过程

注:图中M代表手机,S代表设备B,M->S表示手机将数据包发给设备B,即手机开启Tx窗口,设备B开启Rx窗口;S->M正好相反,表示设备B将数据包发给手机,即设备B开启Tx窗口,手机开启Rx窗口。

如图所示,手机在收到A1广播包ADV_IND后,以此为初始锚点(这个锚点不是连接的锚点),T_IFS后给Advertiser发送一个connection request命令,即A2数据包,告诉advertiser我将要过来连你,请做好准备。手机在发完连接请求之后会被强制延时1.25ms,紧接着是发送窗口偏移,和发送窗口。发送窗口偏移可以是0到连接间隔之间的任意值,但必须是1.25ms的整数倍。从发送窗口开始从设备必须打开RX窗口用来接收手机发过来的P1数据包。如果发送窗口结束还没有收到P1数据包,那么从设备终止监听,并会在下一个连接间隔后再次尝试。从P1开始使用数据通道。Advertiser根据connect_req命令信息做好接收准备,connect_req包含如下关键信息:

  • Transmit window offset,定义如图5所示
  • Transmit window size,定义如图5所示
  • connect_req数据包完整定义如下所示
  • Initiator: 发起连接者的mac地址,BLE的MAC地址,随机地址的最高两位应该为11b
  • Advertiser: 广播者的地址mac地址
  • Access Address: 接入地址。LL层使用接入地址来区分当前发送的数据是广播包还是数据包,广播包接入地址固定为0x8E89BED6,数据包使用就是该值。
  • CRC initialization value: CRC初始值
  • transmitWindowSize: 发送窗口大小, 单位是1.25ms
  • transmitWindowOffset: 发送窗口偏移, 单位是1.25ms
  • connInterval: 连接间隔 单位是1.25ms
  • connSlaveLatency: 从设备延时,表示从设备可以跳过多少个连接事件。
  • connSupervisionTimeout: 监控超时。单位是10ms
  • Channel Map: 信道图,表示当前环境中哪一个信道可用,每一个bit表示一个信道1表示可用,0表示不可用。比如ff ff ff ff 1f(0x1fffffffff), 二进制为0001111111111111111111111111111111111111b
  • masterSCA: 00100b, 休眠时钟精度, 151 ppm to 250 ppm
  • hopIncrement: 110b, 跳频算法的hop值,6

connect_req其实是在告诉advertiser,手机将在Transmit Window期间发送第一个同步包(P1)给你,请在这段时间里把你的射频接收窗口打开。设备B收到P1后,T_IFS时间后将给手机回复数据包P2。一旦手机收到数据包P2,连接即可认为建立成功。后续手机将以P1为锚点(原点),Connection Interval为周期,周期性地给设备B发送Packet,Packet除了充当数据传送功能,它还有如下两个非常重要的功能:

  1. 同步手机和设备的时钟,也就是说,设备每收到手机发来的一个包,都会把自己的时序原点重新设置,以跟手机同步。
  2. 告诉设备你现在可以传数据给我了。连接成功后,BLE通信将变成主从模式,因此把连接发起者(手机)称为Master或者Central,把被连接者(之前的Advertiser)称为Slave或者Peripheral。BLE通信之所以为主从模式,是因为Slave不能“随性”给Master发信息,它只有等到Master给它发了一个packet后,然后才能把自己的数据回传给Master。

对于主设备而言,连接请求一旦发出就认为连接已经建立。当从设备收到连接请求时,它也认为自己已经处在连接之中,连接已经创建,但不能证明完全确立。

4 连接失败

有如下几种典型的连接失败情况:

  1. 如图5所示,如果slave在transmit window期间没有收到master发过来的P1,那么连接将会失败。此时应该排查master那边的问题,看看master为什么没有在约定的时间把P1发出来。
  2. 如果master在transmit window期间把P1发出来了,也就是说master按照connect_req约定的时序把P1发出来了,但slave没有把P2回过去,那么连接也会失败。此时应该排查slave这边的问题,看一看slave为什么没有把P2回过去
  3. 如果master把P1发出来了,slave也把P2回过去了,此时主机还是报连接失败,这种情况有可能是master软件有问题,需要仔细排查master的软件。
  4. 还有一种比较常见的连接失败情况:空中射频干扰太大。此时应该找一个干净的环境,比如屏蔽室,排除干扰后再去测试连接是否正常。

5 连接事件

连接事件(Connection events)

连接成功后,master和slave在每一个connection interval开始的时候,都必须交互一次,即master给slave发一个包,slave再给master发一个包,整个交互过程称为一个connection event。蓝牙芯片只有在connection event期间才把射频模块打开,此时功耗比较高,其余时间蓝牙芯片都是处于idle状态的,因此蓝牙芯片平均功耗就非常低,以Nordic nRF52810为例,每1秒钟Master和Slave通信1次,平均功耗约为6微安左右。Master不可能时时刻刻都有数据发给slave,所以master大部分时候都是发的空包(empty packet)给slave。同样slave也不是时时刻刻都有数据给master,因此slave回复给master的包大部分时候也是空包。另外在一个connection event期间,master也可以发多个包给slave,以提高吞吐率。综上所述,连接成功后的通信时序图应该如下所示:

android ble 配对方法 ble manager与手机怎么配对_低功耗_06


图7: 连接成功后的通信时序图(每个connection event只发一个包)

android ble 配对方法 ble manager与手机怎么配对_android ble 配对方法_07


图9: 连接成功后的通信时序图( connection event可能发多个包)

android ble 配对方法 ble manager与手机怎么配对_低功耗_08


图10:connection event细节图

6 从设备延时

从设备延时(Slave latency)

图10中出现了slave latency(slave latency = 2),那么什么叫slave latency?

如前所述,在每一个connection interval开始的时候,Master和Slave必须交互一次,哪怕两者之间交互的是empty packet(空包),但如果slave定义了slave latency,比如slave latency = 9,此时slave可以每9个connection interval才回复一次master,也就是说slave可以在前面8个connection interval期间一直睡眠,直到第9个connection interval到来之后,才回复一个packet给master,这样将大大节省slave的功耗,提高电池续航时间。当然如果slave有数据需要上报给master,它也可以不等到第9个connection interval才上报,直接像正常情况进行传输即可,这样既节省了功耗,又提高了数据传输的实时性。

7 GAP层角色总结

对上面提到的手机和设备B,在BLE通信过程中,随着时间的推移,他们的状态在发生变化,两者的关系也在发生变化,为此蓝牙spec根据不同的时间段或者状态给手机和设备B取不同的名字,即GAP层定义了如下角色:

  • advertiser。 发出广播的设备
  • observer或者scanner。可以扫描广播的设备
  • initiator。能发起连接的设备
  • master或者central。连接成功后的主设备,即主动发起packet的设备
  • slave或者peripheral。连接成功后的从设备,即被动回传packet的设备

图11通过时间把observer,initiator和central串起来了,其实这三个角色是相互独立的,也就是说一个设备可以只支持observer角色,而不支持initiator和central角色。同样,图11也把advertiser和peripheral串起来了,其实advertiser和peripheral也是相互独立的,即一个设备可以只作为advertiser角色,而不支持peripheral角色。

android ble 配对方法 ble manager与手机怎么配对_蓝牙_09


图11:GAP层角色

二 配对

区别于传统蓝牙的配对过程,BLE的配对过程发生在连接过程之后。

配对是一个三阶段的过程。前两个阶段是必须的,第三阶段是可选的。

  • 第一阶段:配对特征交换
  • 第二阶段:短期秘钥(STK)生成
  • 第三阶段: 传输特定秘钥分配

android ble 配对方法 ble manager与手机怎么配对_BLE_10

android ble 配对方法 ble manager与手机怎么配对_低功耗_11

STK生成规则

  1. Just work: 没有加密 TK=0x00
  2. passkey entry: 密码输入如果 passkey 是 ‘019655’ TK的值就是0x00000000000000000000000000004CC7。
    将输入的值作为一个6位数的十进制,转换成16字节的十六进制。
  3. OOB: 带外的TK值是一个16字节的随机数,通过非BLE的方式传递给对端。

2.1 第一阶段

设备首先在配对特征交换阶段交换IO能力来决定在第二阶段使用下面哪种方法:

  • JustWorks:只工作
  • PasskeyEntry:输入密码
  • OutOfBand(OOB):带外

LE Legacy Pairing - Just Works
Just Works方式不能抵抗窃听者和中间人攻击,只有在配对过程时没有遭受攻击,后面加密的链路的数据传输才是可信的。安全级别很低。

LE Legacy Pairing - Passkey Entry
这种方式通过输入6位数字的方式来进行配对,生成STK。6位数是随机产生的在000000到999999之间的数值,这个数值相当于一个TK,比如远端显示这个数字,需要在本地端输入这个数字给本地设备与远端配对。如输入019655,那此时的临时Key–TK是:0x00000000000000000000000000004CC7。

Out of Band 带外
这种方式是通过BLE之外的,设备上的其他方式来获取这个OOB data,比如通过IR红外,或其余的方式,因此对于蓝牙窃听者/攻击者而言这个data的传输是不可见的了,因此会显得要安全些。

2.1.1 配对请求的数据格式

android ble 配对方法 ble manager与手机怎么配对_低功耗_12

1. IO capabilities表明输入,输出的能力

输入是按键、键盘,输出是显示数字用的界面。

  • 0x00 DisplayOnly 只能是显示000000 ~ 999999的数字
  • 0x01 DisplayYesNo 显示Yes/No 的按钮
  • 0x02 KeyboardOnly 只能是输入000000 ~ 999999的数字
  • 0x03 NoinputNoOutput 没有输入也没有显示,只能用Just work工作方式
  • 0x04 KeyboardDisplay 能输入000000 ~ 999999的数字和输出

2. OOB data flag

  • 0x00 OOB 数据没有发送
  • 0x01 OOB 数据通过远端设备发送(如IR)
  • 0x02-0xFF 保留

3. 身份验证请求

android ble 配对方法 ble manager与手机怎么配对_蓝牙_13

  • Bonding_Flags b1b0 Bonding Type
  • 00 No Bonding
  • 01 Bonding
  • 10 Reserved
  • 11 Reserved
  • MITM

MITM域设置为1为请求MITM(中间人介入)保护,否则设置为0. 设备将标志设置为1为STK请求认证的安全属性。
选择Key生成的方法
如果auth Req中MITM没有,则说明不需要人参与中间,所以IO capabilities会被忽略,只用Just Works就OK了。
如果有OOB data,auth Req将可直接忽略,会直接选择OOB的方式了。

  • SC

SC字段是一个1位标志,设置为1以请求LE安全连接配对,否则应根据发起方和响应方支持的功能将其设置为0,可能的结果配对机制为:如果两个设备均支持 LE安全连接,使用LE安全连接; 否则,请使用LE旧式配对。

  • Keypress

keypress字段是一个1位标志,仅在Passkey Entry协议中使用,而在其他协议中将被忽略。 当双方将该字段设置为1时,应使用SMP配对按键通知PDU生成并发送按键通知。

4. MaximumEncryptionKeySize

最大秘钥长度,7到16字节之间

5. InitiatorKeyDistribution

发起者的秘钥分配,该域表明秘钥初始化设备请求分配使用。

配对请求命令中的“生成”字段由主机使用,以请求发起者向响应者分发或生成哪些密钥。

6. ResponderKeyDistribution

响应者的秘钥分配,该字段表明秘钥初始化设备请求响应设备来分配秘钥分配使用。

2.1.2 配对请求实例

android ble 配对方法 ble manager与手机怎么配对_低功耗_14

1. Code (1 octet)

0x01 Pairing Request

2. IO Capability (1 octet)

0x03 NoInputNoOutput: 用just work 认证方式

3. OOB data

0x00 OOB(out of band)
没有带外认证, 带外这种方式是通过BLE之外的,设备上的其他方式来获取这个OOB data,比如通过IR红外,或其余的方式,因此对于蓝牙窃听者/攻击者而言这个data的传输是不可见的了,因此会显得要安全些。

4. AuthReq (1 octet)

AuthReq字段是一个位字段,指示STK和LTK以及GAP绑定信息的请求安全属性
0x01 :表示绑定

5. MaxEncKeySize

0x10 表示最大认证key大小是0x10个字节

6. InitiatorKeyDistribution

该域表明秘钥初始化设备请求分配秘钥分配使用。

7. ResponderKeyDistribution

001 该字段表明秘钥初始化设备请求响应设备来分配秘钥分配使用。

2.1.3 从设备向主设备向发送配对回复报文

android ble 配对方法 ble manager与手机怎么配对_BLE_15

具体字段含义参考 配对请求报文。

2.2 第二阶段

2.2.1 配对确认

第一阶段的配对特征交换成功之后,用来启动STK生成。该命令被两个对等设备使用,来向对等设备发送确认值。初始化设备通过向响应设备发送配对确认命令启动STK生成。

报文格式

android ble 配对方法 ble manager与手机怎么配对_连接配对_16

启动STK的生成,这一部分可简述为以下步骤的实现

  1. Initiator生成128-bit随机数Mrand,并使用这个Mrand结合一些其他的输入,使用密码工具箱中c1计算出一个128-bit的Mconfirm值:
Mconfirm = c1(TK, Mrand,
Pairing Request command, Pairing Response command,
initiating device address type, initiating device address,
responding device address type, responding device address)

Responder也生成一个128-bit随机数Srand,并使用这个Srand结合一些其他的输入,使用密码工具箱中c1计算出一个128-bit的Sconfirm值:

Sconfirm = c1(TK, Srand,
Pairing Request command, Pairing Response command,
initiating device address type, initiating device address,
responding device address type, responding device address)
  1. Initiator将其计算的Mconfirm值通过Pairing Confirm包发送给Responder,而Responder也将其计算的Sconfirm值通过Pairing Confirm包发送给Initiator;
  2. Initiator收到Sconfirm后,再将Mrand值通过Pairing Random包发送给Responder;
  3. Responder收到Mrand值后计算它的Mconfirm值,再跟前面那个Initiator送过来的Mconfirm值进行比较,若不同说明配对失败了。若相同,则Responder也会将它的Srand值通过Pairing Random包发送给Initiator;
  4. 而Initiator也会计算收到的Srand值的Sconfirm值,并跟前面那个Responder送过来的Sconfirm值进行比较,若不同说明配对失败了,若相同,继续。

报文实例

主设备向从设备发送配对确认报文,从设备也向主设备发送配对确认报文。

android ble 配对方法 ble manager与手机怎么配对_BLE_17

android ble 配对方法 ble manager与手机怎么配对_蓝牙_18

2.2.2 随机配对

该命令用来由初始化和响应设备发送,用来计算在配对确认命令中的确认值的随机数。

报文数据格式

android ble 配对方法 ble manager与手机怎么配对_android ble 配对方法_19

报文实例

主设备向从设备发送配对随机值报文,从设备也向主设备发送配对随机值报文。

android ble 配对方法 ble manager与手机怎么配对_BLE_20

android ble 配对方法 ble manager与手机怎么配对_BLE_21

2.3 第三阶段

2.3.1 传输特定的密钥分发

所有的键和值都由主从设备分发。

要分发的密钥由配对请求和配对响应的密钥分发参数决定,

配对请求和配对响应来自第一阶段配对特征交换

android ble 配对方法 ble manager与手机怎么配对_蓝牙_22

BLE的SMP的一些Key相关定义

  1. Long Term Key (LTK):加密链路用,128-bit;
  2. Encrypted Diversifier (EDIV):在LE legacy pairing过程中,用于识别LTK分发,16-bit;
  3. Random Number (Rand):在LE legacy pairing过程中,用于识别LTK分发,64-bit。
  4. Identity Resolving Key (IRK):用于生成和解析random address用的,128-bit;
  5. AddrType (1 octet)
    如果BD_ADDR是公共设备地址,则AddrType应设置为0x00。
    如果BD_ADDR是静态随机设备地址,则AddrType应设置为0x01。
    BD_ADDR(6个八位字节)此字段设置为分发设备的公共设备地址或静态随机地址。
  6. Connection Signature Resolving Key (CSRK):用于对数据进行签名已经验证签名数据,128-bit;

2.3.2 特定key分发原因

密钥分发阶段的从设备将密钥发送给主设备,这样就可以对重新连接进行加密,并解析其随机地址。或者,主设备可以验证来自从设备的签名数据,主设备也可以向从设备提供密钥,这样,如果角色互换,可以对重连接进行加密,可以解析主设备的随机地址,或者从设备可以验证来自主设备的签名数据。

三 绑定

就是将配对阶段产生的一系列key 保持到flash中,以便后续使用。

以上这个过程的报文交互如下图,

android ble 配对方法 ble manager与手机怎么配对_蓝牙_23