BLE架构图在文章标题中我们多次引用这份架构图,只因为这份图实在是太重要了,但是对于初学者来说可能理解不了,还是希望大家多看看这张图,尤其是学习协议理论上的知识的时候。话不多说,今天我们要分析的是BLE的配对和绑定过程。简单来说配对就是密钥交换的过程,绑定就是存储密钥的过程。一,协议层面首先对协议做下回顾,广播就不讲了,讲的地方太多了,咱们直接从数据包开始。数据包的结构如下:
数据包
数据包PDU
数据包PDU包头数据包的PDU的头部的LLID,这是区分包的用途的主要标识。LLID:(Logical Link Identifier),信道标识符00 表示为保留;
01表示为链路层数据PDU,传输到上层的数据且L2CAP消息是连续分段或空的PDU;
10 表示为链路层数据PDU,传输到上层的数据且L2CAP消息的起始或未分段的完整I2CAP消息
11表示为链路层控制包,链路层完成控制
LLID=0x10时报文结构
信道ID:CID(Channel Identifier)
CID=0x06 表示数据是传输到安全管理协议层的数据
SMP层包结构CID=0x06后面紧SMP层的操作码
SMP层操作码
接下来我们看下绑定的通信过程
全部SMP通信过程数据接下来我们一条一条的解读一下。第1条数据包
操作码 Opcode=0x01 配对请求
当设备需要建立安全连接(如读写加密特征、绑定设备)时,由主设备主动发送。要传递的信息包含以下关于配对的信息说明。
1,自己的IO能力
2,OOB能力
3,请求的加密的属性设置
4,密钥长度
5,主设备可以分发密钥的类型有哪些
6,请求从设备可以分发的密钥类型有哪些
IO能力
IO能力说明自己是否包含键盘、显示器之类的人机交互设备,以便于输入或者显示配对码。
OOB标识
是否具有其他非无线的方式传递密钥信息,称为“带外”OOB。
请求的安全属性
Bonding_Flags:交换密钥后是否存储密钥信息。
MITM:设备请求MITM(防中间人攻击)。
SC:设备是否支持LE安全配对。
Keypress:仅在密钥输入协议中使用,双方都为1,将生成按键通知。
第2条数据包操作码 Opcode=0x02 配对响应
同样的从机也向主机表明自己的能力第3条数据包 操作码 Opcode=0x0C 配对公钥分发
精髓来了:
32字节的X坐标和32字节的Y坐标构成了公钥(基于椭圆曲线)。
1,公钥和私钥是具有一定关系,并不是完全独立的。
2,双方虽然不知道彼此的私钥,通过用自己的私钥和对方发来的公钥进行运算可以得到DHKey,另一方同样的可以得到一个密钥DHKey,而这个DHKey双方是相同的,然后用DHKey进行初步加密和进行后续的密钥计算。
通过上面的公钥交换,双方得到了同一个密钥,而第三方又不知道这个密钥,有没有觉得那些牛逼的数学家就是个天才。第4条数据包 操作码 Opcode=0x0C 配对公钥分发
从机也向主机发送自己的公钥,主机计算自己的DHKey。第5条数据包 操作码 Opcode=0x03 配对确认

发送确认值,确认值通过以下方式计算得出
Confirm Value = f4(DHKey || RandomValue || Address || Other parameters)

关于这个公式是什么,你只要知道f4是一个公式,经过这个公式计算后的数据是和后面括号里的参数唯一对应即可。
正常的配对过程应该是:
主机发送随机数(0x04),接着从机发送随机数(0x04),从机发送确认值(0x03),然后双方根据这些信息计算并验证确认值。
这样双方拥有相同DHKey、主机随机数、从机随机数,计算出来的确认码一致。
但是我不知道为什么nordic的协议栈会先发送确认值,然后才进行了随机数的交换,难道是没有使用随机数计算确认值?有知道朋友欢迎评论区交流。
第6条数据包
操作码 Opcode=0x04 发送随机数


经过交换
从机拥有:自己的随机数,主机的随机数,共享密钥,自己生成的确认码
主机拥有:自己的随机数,从机的随机数,共享密钥,从机生成的确认码
主机就可以通过
Confirm Value = f4(DHKey || RandomValue || Address || Other Parameters)
计算确认码和从机传送的确认码是否一致。
一旦双方成功通过DHKey Check,就说明两边:
拥有相同的Diffie-Hellman Key(DHKey)
使用了相同的输入参数(Na、Nb、r、IOcap 等)
没有中间人篡改或攻击
接下来,双方会使用如下公式来生成会话加密密钥(LTK,Long Term Key)
LTK = f5(DHKey, Na, Nb, A1, A2)

第7条数据包 操作码 Opcode=0x04 发送随机数

正常应该是先交换双方的随机数才对啊。
第8条数据包 操作码 Opcode=0x0d DHKey校验

这里校验码由以下信息生成E = f6(MacKey, Na, Nb, r, IOcap, A1, A2)

验证配对过程中的关键参数没有被篡改。第9条数据包 主机重复发送0x0d第10条数据包 操作码 Opcode=0x0d DHKey校验

从机也向主机发送自己的校验码双方校验完成以后,即验证了双方加密信息的一致性,其他密钥直接通过DHKey派生而来。根据加密方式的不同,后续可能进行密钥交换,nordic没有这个步骤,后续直接开启了链路加密。

第11条数据包 操作码 Opcode=0x05 配对失败



当然当你配对发生异常的时候,对端会发送一个0x05操作码的指令告诉你配对失败的原因。我使用官方心率例程的时候,第一次配对成功后,下次再次点击配对,那么回复的就是0x05配对码的0x05号原因。即使手机上删除绑定信息,依然不能再次绑定,除非擦除芯片后重新烧录程序。大概是因为设备端没有做删除密钥的操作,这个问题我们后续再研究。拿nordic代码举例跟没有paring的ble应用代码相比,有paring的ble应用只多了一个初始化函数:peer_manager_init(),peer_manager_init实现代码如下所示:

peer_manager_init里面注册了一个回调函数:pm_evt_handler,用来添加一些用户自定义的处理,例子代码pm_evt_handler的实现如下所示:

至此,一个just works的蓝牙配对例子就算完成了。
也就是我们只对加密提出了一些要求,进行了简单的配置,其他的工作全部是由协议栈完成的,所以你从代码里也找不到密钥,密钥是有协议栈生成的。
希望通过以上的介绍,大家能对神秘的配对过程不再感到那么神秘。 |