结合实例从HCI层分析经典蓝牙连接和配对过程
我们知道,经典蓝牙BREDR的link key协商是在LMP层做的,那么蓝牙Host在鉴权的过程中,会跟BT SOC有哪些交互:
首次配对
- 在HCI Inuqiry找到想要配对的设备后,Host会调用HCI Create Connection命令去连接对方设备,创建ACL连接,如下图,ACL Connection handle = 0x0004:
- ACL连接创建成功后: 蓝牙HOST会去读取时钟偏移,设置Link Policy(支持role swithc, Hold Mode和Sniff Mode),以及读取对方设备的feature和extended feature:需要注意的是extended feature里的SC Host就是说支持Secure connection,也就是蓝牙4.2采用的基于ECDH鉴权加密机制,如下图:
- 接下来蓝牙Host还会读取对方设备的名字,会设置APCF的过滤规则(通过0xFD57命令),然后就开始进入鉴权过程,如下图红色框:
步骤 | HCI | 详解 |
---|---|---|
1 | HCI Authentication Requested | 蓝牙host发起鉴权 |
2 | HCI Command Status (Success, Command=Authentication Requested) | BTSOC响应OK |
3 | HCI Link Key Request | BTSOC请求HOST是否有现成的link key |
4 | HCI Link Key Request Negative Reply | HOST找了一通没有发现对方设备的link key |
5 | HCI Command Complete (Command=Link Key Request Negative Reply, Success) | BTSOC响应HOST:好的,我知道了,你没有现成的Link key,我会告诉对方设备的 |
6 | HCI IO Capability Request | 对方设备要来查询HOST的IO capability |
7 | HCI IO Capability Request Reply (IoCapability=Yes/No, HostOobDataPresent=None, Auth=MITM+Dedicated) | HOST告诉对方设备IO Capability是支持显示,并且要求认证需要MIMT,以及Dedicated Bond |
8 | HCI Command Complete (Command=IO Capability Request Reply, Success) | BTSOC回应HOST,同时会问对方设备的IO Capbility |
9 | HCI IO Capability Response (IoCapability=None, RemoteOobDataPresent=None, Auth=!MITM+General) | 对方设备的IO Capability是不支持显示,也不支持OOB,不要求MIMT,需要General Bonding |
10 | HCI User Confirmation Request (Pass=039802) | 经过上面双方交互了IO Capability,双方确定了Numeric comparison配对方式,对方要求显示4个字节字符:039802 ,这里手机上会有一个弹窗显示这几个数字,让用户点击确认 |
11 | HCI User Confirmation Request Reply | 用户点击确认,没错,就是这个数字 |
12 | HCI Command Complete (Command=User Confirmation Request Reply, Success) | BTSOC把这个用户的确认信息告诉了对方设备 |
13 | HCI Simple Pairing Complete (Success) | BTSOC和对方设备经过一番LMP交流计算出最终的link key之后,告诉HOST鉴权成功完成。 |
14 | HCI Link Key Notification ( Key=F6E7A1F5:80C01AEF:27F16B1B:75C0B7E5, Type=Unauthenticated-256) | BTSOC告诉HOST Link key,HOST会帮BTSOC保存在本地。 |
15 | HCI Authentication Complete (Success, Connection=0x0004) | 鉴权成功结束,皆大欢喜。 |
配对后的连接
如果首次配对结束,蓝牙HOST会保存Link key 在本地,那么下次连接的时候就不需要重新计算Link Key,过程就简单了很多,如下图:
步骤 | HCI | 详解 |
---|---|---|
1 | HCI Authentication Requested | 蓝牙host发起鉴权 |
2 | HCI Command Status (Success, Command=Authentication Requested) | BTSOC响应OK |
3 | HCI Link Key Request | BTSOC请求HOST是否有现成的link key |
4 | HCI Link Key Request Reply (14:6C:27:DF:91:B1, Key=26AF7922:13E89779:8D76C776:C35BA8F2) | HOST在本地找到了之前配对过的Link key,然后发给了BTSOC |
5 | HCI Command Complete (Command=Link Key Request Reply, Success, 14:6C:27:DF:91:B1) | BTSOC回应了BTHOST给的link key说明没问题 |
6 | HCI Authentication Complete (Success, Connection=0x000E) | 鉴权成功结束。 |
配对后,但对方设备的Link Key丢失
- 对方设备如果擦除了Link Key,那么整个流程就要分为两次了: 由于手机端不知道对方设备的Link Key已经丢失,然后会把之前的配对过的Link Key发给对方,但鉴权肯定是不成功的,对方会返回HCI Authentication Complete (PIN Or Key Missing, Connection=0x000C),如下图:
- 由于手机端收到了PIN Or Key Missing,说明对方Link Key已经不存在了,那么需要重新鉴权协商Link Key,这个过程就跟首次配对的流程是一样的,如下图:
曾经遇到过的问题
之前碰到过一个对方Link key丢失后,手机重新配对,但不会发起A2DP音乐播放的问题,最后通过比较鉴权过程发现有细小差别:
差别就在于对方设备回复的HCI IO Capability Response ,里面有个Authentication Requirement,正常情况下是0x04,异常情况下是0x00,然后查看Core Spec:
应该是手机看到这个设备不需要Bonding,所以不会发起A2DP等服务的SDP查询,近而不会进行A2DP播放。