BLE连接、配对和绑定

参考:一篇文章带你解读蓝牙配对绑定
参考:BLE安全之SM剖析(1)
参考:BLE安全之SM剖析(2)
参考:BLE安全之SM剖析(3)
参考:https://blog.csdn.net/chengbaojin/article/details/103691046
参考:https://www.cnblogs.com/lim11/p/11158153.html

连接

BLE连接示例

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

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

在这里插入图片描述

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

广播(advertising)

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

在这里插入图片描述

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

在这里插入图片描述

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

扫描二维码关注公众号,回复: 16523903 查看本文章

在这里插入图片描述

建立连接(connection)

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

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

在这里插入图片描述
图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除了充当数据传送功能,它还有如下两个非常重要的功能:

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

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

连接失败

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

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

连接事件

连接事件(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,以提高吞吐率。综上所述,连接成功后的通信时序图应该如下所示:
在这里插入图片描述
图7: 连接成功后的通信时序图(每个connection event只发一个包)

在这里插入图片描述
图9: 连接成功后的通信时序图( connection event可能发多个包)

在这里插入图片描述
图10:connection event细节图

从设备延时

从设备延时(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才上报,直接像正常情况进行传输即可,这样既节省了功耗,又提高了数据传输的实时性。

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角色。

在这里插入图片描述
图11:GAP层角色

配对和绑定

什么是低功耗蓝牙配对?什么又是绑定?配对和绑定有什么区别?配对有什么好处?如何删除绑定信息?如何确定配对的安全等级?just work的配对一定就不安全吗?如何开发自己的配对应用?本文将对以上问题进行论述。

Paring(配对)和bonding(绑定)是实现蓝牙射频通信安全的一种机制,有两点需要注意:

  • 一是paring/bonding实现的是蓝牙链路层的安全,对应用来说完全透明,也就是说,不管有没有paring/bonding,你发送或接收应用数据的方式是一样的,不会因为加了paring/bonding应用数据传输需要做某些特殊处理;

  • 二安全有两种选项:加密或者签名,目前绝大多数应用都是选择加密,后续我们也会以加密为重点进行讲述

实现蓝牙通信安全,除了 paring/bonding 这种底层方式,用户也可以在应用层去实现相同功能,两者从功能上和安全性上没有本质区别,只不过应用层自己实现的话,需要自己选择密码算法,密钥生成,密钥交换等,如果你不是这方面的专家,你的应用就有可能会存在安全漏洞。Paring/bonding则把上述过程标准化,放在了蓝牙协议栈中,并且其安全性得到了充分评估,用户可以 “无感的” 用上安全的蓝牙通信

Paring/bonding是蓝牙security manager(SM)的一部分,SM定义了蓝牙通信的安全框架,里面涉及安全架构,密码工具箱,paring协议等,其中paring协议是关键,所以我们经常把paring和SM二者等价,下面将对paring进行详细阐述。

Paring(配对)

配对包括配对能力交换,设备认证,密钥生成,连接加密以及机密信息分发等过程,配对的目的有三个:加密连接认证设备,以及生成密钥。从手机角度看,一旦设备跟手机配对成功,蓝牙配置菜单将包含该配对设备,如下所示:

在这里插入图片描述

如果用户需要主动删除配对设备,点击配对设备右边的“设置”菜单,出现如下界面,选择“取消配对”或者“忽略该设备”,设备的配对信息即被手机删除。

在这里插入图片描述

Bonding(绑定)

配对过程中会生成一个长期密钥(LTK,long-term Key),如果配对双方把这个LTK存储起来放在Flash中,那么这两个设备再次重连的时候,就可以跳过配对流程,而直接使用LTK对蓝牙连接进行加密,设备的这种状态称为bonding

如果 paring 过程中不存储LTK(不分发LTK)也是可以的,paring完成后连接也是加密的,但是如果两个设备再次重连,那么就需要重走一次paring流程,否则两者还是明文通信

在不引起误解的情况下,我们经常把paring当成paring和bonding两者的组合,因为只paring不bonding的应用情况非常少见。在不引起混淆的情况下,下文就不区分paring和bonding的区别,换句话说,我们会把paring和bonding两个概念等同起来进行混用

STK短期秘钥、LTK长期秘钥等

SM(security manager)

蓝牙协议栈的安全管理层,规定了跟蓝牙安全通信有关的所有要素,包括paring,bonding,以及下文提到的SMP。

SMP(security manager protocol)

安全管理协议,SMP着重两个设备之间的蓝牙交互命令序列,对 paring 的空中包进行了严格时序规定。

OOB(out of band,带外)

OOB就是不通过蓝牙射频本身来交互,而是通过比如人眼,NFC,UART等带外方式来交互配对信息,在这里人眼,NFC,UART通信方式就被称为OOB通信方式。

Passkey

又称pin码,是指用户在键盘中输入的一串数字,以达到认证设备的目的。低功耗蓝牙的passkey必须为6位。

Numeric comparison(数字比较)

Numeric comparison其实跟 passkey 一样,也是用来认证设备的,只不过passkey是通过键盘输入的,而numeric comparison是显示在显示器上的,numeric comparison也必须是6位的数字。

MITM(man in the middle)

MITM是指A和B通信过程中,C会插入进来以模拟A或者B,并且具备截获和篡改A和B之间所有通信报文的能力,从而达到让A或者B信任它,以至于错把C当成B或者A来通信。

如果对安全要求比较高,需要具备MITM保护能力,在SM中这个是通过认证(authentication)来实现的,SM中实现认证的方式有三种:OOB认证信息,passkey以及numeric comparison,大家根据自己的实际情况,选择其中一种即可。

LESC(LE secure connections)

又称SC,蓝牙4.2引入的一种新的密钥生成方式和验证方式,SC通过基于椭圆曲线的Diffie-Hellman密钥交换算法来生成设备A和B的共享密钥,此密钥生成过程中需要用到公私钥对,以及其他的密码算法库。

LESC同时还规定了相应的通信协议以生成该密钥,并验证该密钥。需要注意的是LESC对paring的其他方面也会产生一定的影响,所以我们经常会把LESC看成是一种新的配对方式。

Legacy paring

在LESC引入之前的密钥生成方式,称为legacy paring,换句话说,legacy paring是相对LESC来说的,不支持LESC的配对即为legacy paring(legacy配对)。

TK(Temporary Key,临时密钥)

legacy paring里面的概念:

  • 如果采用 just work 配对方式,TK就是为全0;
  • 如果采用passkey配对方式,TK就是passkey;
  • 如果采用OOB配对方式,TK就是OOB里面的信息。

https://blog.csdn.net/mcgrady_tracy/article/details/78424254
Just Works配对方式是不需要配对码的,也就是直连的。
密码方式进行配对,也就是Passkey Entry。打开手机,连接改设备时需要输入一个配对码,只有输入正确后才能正常连接。这个配对码是由底层协议栈随机生成的。

STK(short term key,短期密钥)

legacy配对里面的概念,STK是通过TK推导出来的,通过TK对设备A和B的随机数进行加密,即得到STK。

LTK(long term key,长期密钥)

legacy配对LESC配对都会用到LTK,如前所述,LTK是用来对未来的连接进行加密和解密用的。Legacy paring中的LTK由从设备根据相应的算法自己生成的(LTK生成过程中会用到EDIV(分散因子)和Rand(随机数)),然后通过蓝牙空中包传给主机。

LESC配对过程中,先通过Diffie-Hellman生成一个共享密钥,然后这个共享密钥再对设备A和B的蓝牙地址和随机数进行加密,从而得到LTK,LTK由设备A和B各自同时生成,因此LTK不会出现在LESC蓝牙空中包中,大大提高了蓝牙通信的安全性。

IRK(Identity Resolving Key,蓝牙设备地址解析密钥)

有些蓝牙设备的地址为可解析的随机地址,比如iPhone手机,由于他们的地址随着时间会变化,那如何确定这些变化的地址都来自同一个设备呢?

答案就是IRK,IRK通过解析变化的地址的规律,从而确定这些地址是否来自同一个设备,换句话说,IRK可以用来识别蓝牙设备身份,因此其也称为Identity information。IRK一般由设备出厂的时候按照一定要求自动生成。

Identity Address(设备唯一地址)

蓝牙设备地址包括public,random static, private resolvable,random unresolved共四类。
如果设备不支持privacy,那么identity address就等于public或者random static设备地址。
如果设备支持privacy,即使用private resolvable蓝牙设备地址,在这种情况下,虽然其地址每隔一段时间会变化一次,但是identity address仍然保持不变,其取值还是等于内在的public或者random static设备地址。
Identity Address和IRK都可以用来唯一标识一个蓝牙设备。

IO capabilities(输入输出能力)

是指蓝牙设备的输入输出能力,比如是否有键盘,是否有显示器,是否可以输入Yes/No两个确认值。

Key size(密钥长度)

一般来说,密钥默认长度为16字节,为了适应一些低端的蓝牙设备处理能力,你也可以把密钥长度调低,比如变为10个字节。

Paring配对流程及命令

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

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

  • 阶段1:配对特性交换,即交换各自都支持哪些配对特性,比如支不支持SC,支不支持MITM,支不支持OOB,以及它的输入输出能力等。

  • 阶段2:密钥生成阶段,包括(LE legacy pairing)短期密钥(STK)生成、(LE Secure Connections):长期密钥(LTK)生成。legacy paring和LESC paring两者的区别就在这里,因此后续我们会分开阐述legacy paring和SC paring的阶段2。
    Legacy paring:STK生成(注:legacy paring的LTK生成跟配对流程无关,如前所述,其是由从机自己生成的)
    SC paring:LTK生成

  • 阶段3:通过蓝牙空中包分发一些秘密信息。Legacy paring需要分发LTK,IRK等,而SC paring只需分发IRK。秘密信息分发之前,必须保证连接已加密。

在这里插入图片描述

在这里我们需要搞清楚两个概念:LE legacy pairing和LE Secure Connections。LE是“low energy”的缩写,是蓝牙4.0及以上版本的主要功能之一。在蓝牙4.2规范中,添加了LE物理传输的安全连接特性,升级了对蓝牙LE物理传输的配对,使用了FIPS-approved的算法(AES-CMAC和P-256椭圆曲线)。为了区分蓝牙4.0和4.1规范中定义的安全连接和配对,将其称为LE legacy pairing,而到蓝牙4.2版本后增加了LE Secure Connections的模式。

STK生成规则

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

Paring流程如下所示:

在这里插入图片描述

阶段1:配对特性交换Paring流程及命令

设备首先在配对特征交换阶段交换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的传输是不可见的了,因此会显得要安全些。

配对请求的数据格式

在这里插入图片描述
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. 身份验证请求

在这里插入图片描述

  • 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

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

配对请求实例

在这里插入图片描述

  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:密钥生成

配对确认

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

报文格式

在这里插入图片描述

启动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)

2、Initiator将其计算的Mconfirm值通过Pairing Confirm包发送给Responder,而Responder也将其计算的Sconfirm值通过Pairing Confirm包发送给Initiator;
3、Initiator收到Sconfirm后,再将Mrand值通过Pairing Random包发送给Responder;
4、Responder收到Mrand值后计算它的Mconfirm值,再跟前面那个Initiator送过来的Mconfirm值进行比较,若不同说明配对失败了。若相同,则Responder也会将它的Srand值通过Pairing Random包发送给Initiator;
5、而Initiator也会计算收到的Srand值的Sconfirm值,并跟前面那个Responder送过来的Sconfirm值进行比较,若不同说明配对失败了,若相同,继续。

报文实例

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

在这里插入图片描述
在这里插入图片描述

随机配对

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

报文数据格式

在这里插入图片描述
报文实例

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

在这里插入图片描述
在这里插入图片描述

一旦LTK生成成功,主机端就可以发起加密连接流程,如下所示:

在这里插入图片描述

至此,LESC连接被LTK加密了,后面就可以分发秘密信息了。

阶段3:秘密信息分发

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

要分发的密钥由配对请求和配对响应的密钥分发参数决定,
配对请求和配对响应来自第一阶段配对特征交换

一旦连接加密了,主机和从机之间就可以分发一些秘密信息。如果是legacy paring,如下秘密信息必须分发:

  • LTK
  • EDIV
  • Rand

°同时根据情况,legacy paring还需分发如下信息:

  • IRK
  • Identity adresss

对于LESC paring,秘密信息分发是可选,一般有可能分发如下信息:

  • IRK
  • Identity adresss

如下为legacy paring可能分发的最多秘密信息的一个例子:

在这里插入图片描述

BLE的SMP的一些Key相关定义

  • Long Term Key (LTK):加密链路用,128-bit;

  • Encrypted Diversifier (EDIV):在LE legacy pairing过程中,用于识别LTK分发,16-bit;

  • Random Number (Rand):在LE legacy pairing过程中,用于识别LTK分发,64-bit。

  • Identity Resolving Key (IRK):用于生成和解析random address用的,128-bit;

  • AddrType (1 octet)
    如果BD_ADDR是公共设备地址,则AddrType应设置为0x00。
    如果BD_ADDR是静态随机设备地址,则AddrType应设置为0x01。
    BD_ADDR(6个八位字节)此字段设置为分发设备的公共设备地址或静态随机地址。

  • Connection Signature Resolving Key (CSRK):用于对数据进行签名已经验证签名数据,128-bit;

特定key分发原因

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

绑定,重连和加密

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

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

在这里插入图片描述

如上所述,如果配对的两个设备生成了LTK及其他秘密信息,并且把LTK及其他秘密信息保存到Flash等永久化存储设备中,那么我们就可以说这两个设备绑定成功。换句话说,paring和bonding是两个不同的概念,paring更强调认证和密钥生成,而bonding更强调密钥保存

一旦两个设备bonding成功,那么这两个设备断开再次重连的时候,主机就可以发起加密流程,从而使用paring生成的LTK对后续的连接进行加密。主机发出加密连接流程如下所示:

在这里插入图片描述
这里说明一下,加密连接只能由主机发出,而不能由从机发起。不过从机可以发出加密请求,主机收到从机的加密请求后,可以发起加密连接也可以拒绝其请求。如下为主机同意从机的加密请求的工作流程:

在这里插入图片描述

配对命令一览表

如下为SM中用的PDU命令列表:

(注:加密连接命令属于LL控制命令,所以没有包含在其中)

在这里插入图片描述

其他注意的点

苹果手机的一点不同:

安卓手机允许用户手动发起paring请求,而苹果手机则没有这个功能。因此,即使你的characteristic没有使能安全级别,安卓手机还是可以跟你的设备完成配对的,而苹果手机则不支持这个功能,苹果手机要不要跟设备进行配对,不能由人来控制的,只能由苹果iOS来控制。

欲触发苹果iOS发起配对请求,有两种方法:

  • 一是将某个characteristic加上安全认证权限,这样iOS在服务发现过程中就会自动发起配对请求,以满足characteristic的安全认证级别;
  • 二是从机端主动发起安全请求,iOS收到从机的安全请求后,会等待用户的授权确认从而发起配对请求。这两种方法在ble_app_gls中都有体现,大家可以参考相关代码。

重连加密等级

绑定成功后,如果发生重连,那么主机应该自动发起加密连接请求,以对连接进行加密。一般来说,在连接没有成功加密前,主从机不要做敏感数据的交互,否则softdevice API会报NRF_ERROR_FORBIDDEN。对于有MITM保护的加密连接,在收到PM_EVT_CONN_SEC_SUCCEEDED这个事件后,设备应该去检测连接的安全等级是否符合要求,具体可参考ble_app_gls例子的做法。

Service changed(服务改变)

设备跟手机绑定成功后,手机再次重连这个设备时,就会自动跳过service discovery过程,换句话说,配对的时候手机会把设备所有服务和characteristic的handle保存下来,二次重连的时候,直接用以前保存的 handle 值去操作设备。

但是,如果设备的服务改变了,此时手机再用之前的 handle 去操作设备,就会出问题。为了解决这个问题,在GATT主服务里面引入了 service changed characteristic,如下所示:

在这里插入图片描述

有了这个characteristic,当设备的服务发生改变时,设备就可以通过这个characteristic发送一个indicate PDU给到手机,从而手机知道设备的服务已发生了改变,此时手机会重新发起service discovery流程,以重新获得service和characteristic最新的handle列表。欲添加service changed characteristic,你只需在sdk_config.h文件中打开如下两个宏:

在这里插入图片描述
然后当服务发生改变时,调用pm_local_database_has_changed(),协议栈就会自动发起service changed indicate PDU给手机,从而引起手机重走服务发现过程。

删除主机端绑定信息:

如果手机端删除了绑定信息,为了安全起见,设备端也需要跟着一起删除绑定信息,否则手机无法再次跟设备进行配对,这个是最理想的情况,但是我们有的设备没有任何输入接口,无法手动删除绑定信息,这个时候能不能有一种办法可以让手机跟设备进行二次配对呢?

为此,Nordic提供了一种workaround,在蓝牙事件回调函数里面,加上如下代码即可:

if (p_evt->evt_id == PM_EVT_CONN_SEC_CONFIG_REQ){
    
    pm_conn_sec_config_t cfg;

​        cfg.allow_repairing = true;pm_conn_sec_config_reply(p_evt->conn_handle, &cfg);} 

这样,即使用户把手机端paring信息删掉,设备端paring信息没有删掉,手机还是可以跟设备进行二次配对的。

删除从机端绑定信息:

跟上面相反,如果设备端 bonding 信息被删除了,而手机端 bonding 信息没有被删除,这种情况下如何实现二次配对?

最安全的方式,让用户主动删除手机端绑定信息,但是很多开发者希望,用户体验好一点,也就是说,碰到这种情况希望手机能自动删除绑定信息,这个能不能实现跟手机有很大关系,首先我们确保协议栈返回LL_REJECT_IND or LL_REJECT_EXT_IND,错误码为“PIN or key missing”,一般而言,手机收到这个PDU后,都会自动删除bonding信息。

如果上述方法行不通的话,那么发送完LL_REJECT_IND后再调用断开函数(sd_ble_gap_disconnect),同时将断开原因设为BLE_HCI_AUTHENTICATION_FAILURE即可。

同时绑定多个设备:

Nordic SDK是支持一个设备同时跟多个主机绑定,只要设备存储空间足够大,那么可以绑定的设备数就不设限。nRF5 SDK中bonding信息也是通过fds来存储的,也就是说绑定信息和用户Flash数据共享同一块空间,如果需要绑定多个设备,那么FDS_VIRTUAL_PAGES这个宏的值必须进行修改,以保证分配的Flash空间可以同时容纳bonding信息和用户Flash数据。

一般来说,如果需要绑定多个设备,请设置一个最大绑定数,比如8个,这样,一旦检测到绑定数达到8了,就可以把以前老的bonding设备删除,从而节省存储空间。那如何知道哪个设备是老设备哪个设备是新设备?这个是通过peer rank来实现的,大家只要使能 PM_PEER_RANKS_ENABLED 这个宏,就可以自动实现排序。

循环绑定测试:

很多开发者喜欢做循环绑定测试,即同一部手机不断跟同一个设备进行配对,然后删除配对信息,然后再进行配对,他们测试下来发现:

达到一定次数后,设备就工作不正常了,这个是由于当bonding信息不断累积而不进行删除的话,那么分配给fds的Flash空间就会耗尽,从而导致异常出现(最新的SDK会在Flash存储空间耗尽时,自动删除最老设备的绑定信息,但即使这样,对用户Flash数据的操作影响还是很大)。

解决这个问题的方法就是设定一个最大bonding数,达到这个数目后,删除老bonding信息,从而达到循环利用Flash空间的目的。当然如果你的fds只是用来存储bonding信息而不做其他用户数据操作的话,那么就没有必要加上这个功能了。

白名单与绑定:

虽然白名单和绑定二者没有任何联系,但是我们一般都把两者结合起来一起使用,以达到我们的使用期望。当两个设备绑定成功后,我们就可以将对方的mac地址或者IRK放入白名单中,同时开启白名单广播,这样设备只跟白名单中的主机进行连接,白名单以外的设备在controller层面就被过滤掉了,从而提高私密性以及连接效率。

这样,即使用户把手机端paring信息删掉,设备端paring信息没有删掉,手机还是可以跟设备进行二次配对的。

这种情况下,哪怕是合法的设备,如果之前没有跟设备绑定,那么它也无法跟设备建立连接。换句话说,如果你想把新设备加入到白名单中,那么首先需要禁止白名单广播而采用普通广播,然后跟新设备进行配对,成功后再把新设备身份信息加入到白名单中。白名单与绑定的例子具体可参考:ble_app_hids_keyboard。

Authenticated payload timeout:

大家都知道蓝牙连接有一个 supervision timeout 时间,也就是说,当建立连接的两个设备,任何一方在supervision timeout(比如4s)时间内,没有给对方发送任何蓝牙空口包,此时认为连接已断开,并触发 supervision timeout 事件。

当设备双方建立加密连接后,不仅有上述的supervision timeout,还有一个authenticated payload timeout,authenticated payload timeout默认为30s,它的意思是,两个设备加密后,30s内必须有一个有数据的空口包交互,而不能一直发空包,否则认为authenticated payload timeout。

Authenticated payload timeout是协议栈自动管理的,对软件开发来说是透明的,每30s时间到,如果期间没有任何有效数据包交互(一直在发空包),协议栈会自动发送一个ping request给对方,以避免authenticated payload timeout的出现(注:这里的协议栈既可以是设备的协议栈,也可以是手机的协议栈)。

有时候不想等到30s超时到了再发送ping request,大家可以在connected事件中,调用如下API以提前发出ping request。

在这里插入图片描述
当然,如果你能保证每30s时间内,手机和设备之间肯定会有有效数据包交互,或者手机端能及时准确地发出ping request,那么上述过程就完全没有必要了。

评论:你好,请问如果NRF52840和手机已经配对绑定了,手机如何下次自动连接呢?不通过nrf Connect App。就像一般蓝牙耳机一样。

回答:完成了绑定流程之后,手机端和设备端会存储对方的信息密钥。后面收到设备的广播后,手机会自动发起回连的,信息和密钥验证成功后,就回连成功了。

总结

BLE 配对与绑定过程详细解析

  1. 蓝牙绑定
    绑定真正来说属于通用访问规范的讨论范畴。绑定指的无非是将密钥及相关身份信息保存到数据库中。如果设备不保存这些值,他们虽然能匹配,但不能绑定。
    只要当中某一个设备不保存,重新连接后,只有一个设备拥有 LTK,因此加密的启动将会失败。
    为了避免这种情况,两个设备在最初配对时就会交换绑定信息,从而能够清楚地知道对方是否保留了该绑定信息。
    如果对方设备不保存信息,那么一旦启动加密的尝试失败,主机将试图再次配对。
  2. 绑定的相关知识
    绑定并不是一个独立存在的过程。 可以理解成配对有两种方式, 没有设置绑定表示的配对请求和设置绑定标志的配对请求。
    配对的目的就是单纯的加密链路,但是配对过程比较耗时(包括配对信息交换,用户输入配对码或带外传输配对码,协议层的配对确认交换和随机数交换以及确认验证,都没问题后才会生成链路加密秘钥来加密链路),如果为了数据始终都是加密传输而每次连接都去配对的话就比较麻烦, 所以又定义了一个绑定过程,绑定过程是在 配对后链路加密的情况下 分发一个 LTK(其他秘钥这里不涉及),这个LTK就可以供以后直接加密链路, 而不用经过繁琐的配对过程。
    Notes:其实LTK分配之后,每次重新连接时的加密并不是用LTK直接加密链路,而是双方交换一些信息(称为会话秘钥分散器),然后利用这些信息和LTK最终生成一个会话秘钥,真正的加密是用这个会话秘钥。
  3. 总结
    1)配对认证:主从机一方提供密码,一方输入密码,如果双方密码一致,那么此密码将作为TK(临时密码);
    2)加密链路:利用得到的TK(临时密码)等信息计算出STK(短期密码)用来做加密认证;
    3)绑定:加密认证通过后,利用STK等信息生成LTK(长期密码),把LTK保存下来,用于下次连接时做加密认证,不需要再次配对就可以加密链路,这就是绑定了;
    绑定后通讯过程 : 每次连接时,从机会向主机发送安全请求,如果主从机相互绑定过,主机不会发送配对请求,主机直接利用绑定时保存的LTK发送加密请求,从机也会利用绑定时保存的LTK来做加密回复,三次握手成功后(加密成功,三次握手通讯由底层完成,用户不可见),从机回复主机加密状态success。
  4. 配对和绑定区别:
    1)连接:通讯的基础,通讯数据为明文;
    2)配对:配对仅仅是为了在连接的基础上加密(通讯数据经过加密为密文),提高蓝牙链路传输的安全性。不配对也能连接进行通信。
    3)绑定:绑定是配对发起时的一个可选配置。把配对信息记录下来, 下次不用配对自动进入加密的连接;所以没在bonding列表里的设备不影响连接,照连不误。

猜你喜欢

转载自blog.csdn.net/zhuguanlin121/article/details/131999840