一文读懂BLE

BLE名称概念

  1. BR/EDR:Basci Rate/Enhanced Data Rate,基本速率和增强速率技术,关注速率
  2. LE:Lower Energy,低功耗技术,关注功耗
  3. LQI和RSSI:LQI为Link Quality Indication,信号质量指示;RSSI为Received Signal Strength Indication,信号强度指示。LQI关注正确率(噪声noise干扰),RSSI关注信号强度
  4. L2CAP:Logical Link Control and Adaptation Protocol,逻辑链路控制和适配协议,实现不同应用可以共享同一个逻辑链路
  5. 物理层:物理层类似于城市上的各条道路。Physical Channel为物理信道,真实的物理实体频段;Physical Links为物理链路,对物理信道的封装
  6. 逻辑层:逻辑层类似于在这些道路上划分的快车道、慢车道等。Logic Links为逻辑链路;Logic Transport为逻辑传输
  7. Profile:蓝牙定义的各种应用服务,如SPP,HFP等
  8. GAP:Generic Access Profile,是一个基础的蓝牙profile,用于提供蓝牙设备的通用访问功能,包括设备发现、连接、鉴权、服务发现等
  9. ATT:Attribute Protocol,属性协议,定了客户端和服务端之间属性值的发现,读取,写入等操作
  10. GATT:Generic Attribute Profile,profile框架
  11. HCI:Host Controller Interface,仅仅是将Link Layer所提供的功能封装成特定的Command和Event,没有任何逻辑可言
  12. SM:Security Manager,安全管理,规定了跟蓝牙安全通信有关的所有要素
  13. SMP:Security Manager Protocol,安全管理协议,规定配对和密钥分发交互
  14. OOB:Out Of Band,带外,通过其他方式交换密钥,如NFC,WIFI等
  15. MITM:Man In The Middle,中间人,即设备双方通信过程中的第三者
  16. **LE legacy pairing **:遗留的配对方式,相对于LESC来说的。
  17. LESC:LE Secure Connections,蓝牙4.2以后引入的新的密钥生成方式和验证方式(ECDH)
  18. TK:Temporary Key,临时密钥,只要在legacy pairing方式中
  19. STK:Short Term Key,短期密钥,同样只用在legacy pairing方式中
  20. LTK:Long Term Key,长期没有,legacy pairing和LESC方式均会用到LTK。
  21. IRK:Identity Resolving Key,蓝牙设备地址解析密钥,用于解析随机地址,确保这些地址来自同一设备
  22. CSRK:Connection Signature Resolving Key,连接签名解析密钥,用于签名连接中的通信数据,另一方就能对签名值进行验签。

BLE协议框架

在这里插入图片描述

BLE协议可分为Bluetooth Application和Bluetooth Core两大部分,而Bluetooth Core又包含BLE Controller和BLE Host两部分。

Controller

Controller实现射频相关的模拟和数字部分,完成最基本的数据发送和接收,Controller对外接口是天线,对内接口是主机控制器接口HCI(Host controller interface);控制器包含物理层PHY(physicallayer),链路层LL(linker layer),主机控制器接口HCI。

Physical Layer

物理层定义通信介质(物理通道),BLE定义了40个RF Channel,每个带宽为2MHz,频率范围为2402-2480MHz。

Link Layer

链路层主要负责链路管理,链路控制,在物理通道上收发数据,控制RF收发相关的参数。解决物理信道的共享问题;为通信实体建立独享的逻辑链路(Logical Link);提供校验、重传等机制,确保数据传输的可靠性。

HCI

HCI定义Host和Controller之间(通常是两颗IC)的通信协议,如UART、USB、SDIO等。这两层之间为什么不是函数调用呢,因为BLE的产品形态不同导致:全协议栈,只有Controller,只有Host层。

Host

主机Host是蓝牙协议栈的核心部分。

GAP

用于提供蓝牙设备的通用访问功能,包括设备发现、连接、鉴权、服务发现等

L2CAP

逻辑链路控制和适配协议,实现不同应用可以共享同一个逻辑链路。作用为协议/通道的多路复用,负责上层应用数据(L2CAPService Data Units,SDUs)的分割(和重组),生成协议数据单元(L2CAP Packet Data Units,PDUs),以满足用户数据传输对延时的要求,并便于后续的重传、流控等机制的实现。

ATT/GATT

ATT属性协议定义了一个通信的基本框架,数据的基本结构,以及通信的指令,而GATT层就是service和characteristic这些,GATT层用来赋予每个数据一个具体的内涵,让数据变得有结构和意义。换句话说,没有GATT层,低功耗蓝牙也可以通信起来,但会产生兼容性问题以及通信的低效率。

SM

安全管理规定了跟蓝牙安全通信有关的所有要素。

Application

蓝牙应用协议层,在蓝牙核心协议的基础上,定义的各种profiles/services及各种具体的应用。

BLE通信连接

BLE设备双方通信按照状态机进行切换实现,被连接的一方按照Standby->Advertising->Connection状态顺序实现连接;主动连接的一方按照Standby->-Scanning->Initiating->Connection状态顺序实现连接。蓝牙发起广播的一方称为广播者,发起扫描的一方称为扫描者,双方连接成功后,分别变成Slave和Master两种角色。Master角色的设备称为Central设备,而Slave角色的设备称为Peripheral设备。由于Slave角色的设备一般提供服务,因此称为服务端;而Master角色的设备访问服务,因此称为客户端。

1. 从机发起广播

蓝牙广播者Advertiser发起广播,其广播的数据可以被扫描者和初始化者接收,广播数据在可以在37,38,39三个信道上广播。

广播数据

BLE协议规定广播数据不能超过31字节,其数据是由一个一个的AD Structure组成,每个AD Structure组成(LTV形式)由1字节的长度和剩余的数据组成,如下:

在这里插入图片描述

在Data下又划分成AD Type和AD Data两个域,BLE协议根据不同的使用场景定义了不同的AD Type,如:0x01为Flags,指示本设备支持Limited Discoverable Mode/General Discoverable Mode的能力,如AD Data 0x06为通用发现模式,不支持BR/EDR;0x09为Complete Local Name;0xFF为制造商数据等等

扫描响应数据

扫描响应包同广播数据格式相同,当扫描者为了请求广播者更多的数据,就会发送扫描请求包SCAN_REQ,广播者收到该请求后,可以携带更多信息回复扫描响应数据。

广播参数

广播参数包括广播间隔,广播类型,地址类型,信道,过滤策略等的配置。

  • 广播类型

    可连接非定向广播ADV_IND;可连接定向广播ADV_DIRECT_IND_LOW和ADV_DIRECT_IND_HIGH(包括低占空比和高占空比两种);可扫描非定向广播ADV_SCAN_IND;不可连接非定向广播ADV_NONCONN_IND

  • 广播间隔

    对于非定向广播和可连接的低占空比广播,广播事件的间隔由advInterval和advDelay组成。advInterval是N*0.625ms,N的范围为0x0020-0x4000,即20ms到10.21s之间,advDelay是协议层控制的0-10ms间的随机数。如果可扫描的非定向广播或者不可连接的非定向广播,advInterval不低于100ms。

    而对于高占空比的定向广播,广播周期小于等于3.75ms,但是广播时间不能超过1.28s,即最长1.28s后需要退出广播状态。

  • 地址类型

    BLE地址分为:Public Device Address和Random Device Address,而Random Device Address又分为Static Device Address和Private Device Address;Static Device Address上电随机生成,而Private Device Address通过定时更新和地址加密的方法。其根据地址是否加密,又分为Non-resolvable Private Address和Resolvable Private Address两类。

    广播参数中需要设置自身地址类型和对端地址类型及地址

  • 信道

    可以设置广播包的信道,只37,38,39信道一种或者所有

  • 广播过滤策略

    广播过滤策略分为:只接受位于白名单中的设备的扫描和连接请求;可以接受任何设备的扫描和连接请求;可以接受任何设备的扫描请求,但只接受位于白名单中的设备的连接请求;可以接受任何设备的连接请求,但只接受位于白名单中的设备的扫描请求。

开启广播

设置完成广播参数和广播数据后,就可开启广播,等待扫描者进一步扫描和连接处理。

2. 主机发起扫描

蓝牙扫描者发起扫描,接收广播者发送的广播。

扫描参数

扫描参数包括扫描模式,自身地址类型,扫描过滤策略,扫描间隔及窗口等

  • 扫描模式

    主动扫描(Active Scanning)和被动扫描(Passive Scanning)。被动扫描只听不问,即接收广播包,不发送扫描请求SCAN_REQ;而主动扫描还会发送扫描请求SCAN_REQ,并接收后续的SCAN_RSP。

  • 扫描过滤策略

    接收所有广播包除了没有包括自身地址的定向广播(定向广播是让指定的对端地址连接);只接收设备地址在白名单中的广播,没有包括自身地址的定向广播也进行忽略;接收所有非定向广播、Initiator Addresss是可解析私有地址的定向广播和包括自身地址的定向广播;接收设备地址在白名单中的广播、Initiator Addresss是可解析私有地址的定向广播和包括自身地址的定向广播

  • 扫描间隔

    两次扫描间的时间,扫描间隔等于N*0.625ms,N的范围为0x0004-0x4000,即2.5ms至10.24s之间

  • 扫描窗口

    单次扫描的持续时间,扫描窗口也等于N*0.625ms,N的范围为0x0004-0x4000,即2.5ms至10.24s之间,扫描窗口要小于等于扫描间隔

  • 自身地址类型

    同广播地址类型定义

开启扫描

设置完成扫描参数后,就可开启扫描,并设置扫描的超时时间。在扫描窗口内,如果扫描到广播包数据,就可解析广播者携带的flag、广播设备名、制造商等广播数据。如果该广播可以连接,并且是自己想连接的设备,即可发起连接,并停止扫描。

3. 主机发起连接

主动连接的设备(Initiator)在收到广播包之后,回应一个CONNECT_REQ请求,该请求携带了可决定后续“通信时序”的参数。Initiator在发出CONNECET_REQ请求后,自动转变为连接状态,成为Master角色。

4. 主从连接成功

广播者Advertiser在收到CONNECT_REQ请求之后,也自动转变为Connection状态,成为Slave角色。主从双方按照CONNECT_REQ参数所给出的约定,定时到切换到某一个Physical Channel上,按照Master->Slave然后Slave->Master的顺序,收发数据,直至连接断开。

连接参数

连接参数用于保证主从双方连接时序,包括

  • 最小连接间距

    最小连接间距等于N*1.25ms,N的范围为6-3000,即7.5ms至4s

  • 最大连接间距

    最大连接间距等于N*1.25ms,N的范围为6-3000,即7.5ms至4s

  • 从机延迟

    定义从机可以忽略多少个连接事件(从机可以睡眠省电,不会导致超时断开),范围为0-500,但必须满足

    (1 + connSlaveLatency) * connIntervalMax * 2 <= connSupervisionTimeout 
    
  • 监控超时

    监控超时等于N*10ms,N的范围为10-3200,即100ms至32s

对于IOS设备,连接参数要求更为严格,即

connIntervalMax * (1 + connSlaveLatency) <= 2s
connIntervalMin >= 20ms
connIntervalMin + 20ms <= connIntervalMax
connSlaveLatency <= 4
connSupervisionTimeout <= 6s
connIntervalMax * (1 + connSlaveLatency) * 3 < connSupervisionTimeout

连接超时及断开

主从连接断开原因有两种:预期内的主动断开,会走Termination Procedure过程;非预期的异常断开,如严重干扰,突然断电,距离过远等。第一种情况主从按照协议预定正常断开;而第二种情况对于从机来说,可以立马检测到异常断开,对于主机来说需要等到timeout后才会引发超时断开。

5. 主机发现服务

BLE蓝牙设计的初衷是应用在物联网上,物联网最广泛的应用就是信息采集,如温度、湿度、压力、PM2.5等等。

ATT

针对信息采集的需求,BLE抽象出一个协议ATT:Attribute protocol,该协议将这些“信息”以“Attribute(属性)”的形式抽象出来,并提供一些方法,供远端设备(remote device)读取、修改这些属性的值(Attribute value)。

ATT协议定义了两种角色:ATT Server提供信息(属性),ATT Client访问信息(属性)。一个Attribute由四个元素组成:

  • attribute type:属性类型,使用UUID区分定义,标识我们常说的温度、湿度、电池等。SIG对常⽤用的一些数据类型进了归类,赋予不同的数据类型不同的标识码 (UUID)。例如 0x2A09 表示电池信息, 0x2A6E 表示温度信息。
  • attribute handle:属性句柄,16位值,协助找到相应的属性,正如可以使⽤用内存地址查找内存中的内容一样 。
  • attribute value:属性值是每个属性真正要承载的信息,其他三个元素都是为了让对方能够更好地获取属性值。
  • attribute permissions:属性许可,每个属性对各自的属性值有相应的访问限制,比如有些属性是可读的、有些是可写的、有些是可读又可写的等等。拥有数据的一方可以通过属性许可,控制本地数据的可读写属性。
属性句柄属性类型属性值属性许可
0x0001
0x0002
……
0xFFFE
0xFFFF

服务端和客户端之间常用数据操作:

  • 客户端发送数据给服务端

    通过对服务器的数据进行写操作 (Write),来完成数据发送工作。写操作分两种,一种是写入请求 (Write Request),一种是写入命令 (Write Command),两者的主要区别是前者需要对方回复响应 (Write Response),而后者不需要对方回复响应。

  • 服务端发送数据给客户端

    主要通过服务端指示 (Indication) 或者通知 (Notification) 的形式,实现将服务端更新的数据发给客户端。与写操作类似,指示和通知的主要区别是前者需要对方设备在收到数据指示后,进行回复 (Confirmation)。

  • 客户端读取服务端数据

GATT

ATT只定义client和server按照Attribute的形式共享信息,即规定了在 BLE 中的最小数据存储单位 ,但是具体共享哪些信息是由GATT决定的。GATT 规范则定义了如何⽤用特性值和描述符表示一个数据,如何把相似的数据聚合成服务 (Service),以及如何发现对端设备拥有哪些服务和数据。GATT是一个profile framwork,用于提供通用的、信息的存储和共享等功能,其层次结构如下:

在这里插入图片描述

GATT层次结构从顶层到底层为:Profile -> Service -> Characteristic。

在这里插入图片描述

  • Profile是一个抽象的概念,它只是一个被Bluetooth SIG或者外设设计者预先定义的Service的集合,例如心率Profile(Heart Rate Profile)就是结合了Heart Rate Service和Device Information Service。

  • Service是把数据分成一个个的独立逻辑项,每个Service是有一个UUID唯一标识。UUID有16bit的,或者128bit的。16bit的UUID是官方通过认证的,需要花钱购买,128bit是自定义的,这个就可以自己随便设置。每个Service可以包含一个或者多个Characteristic。

    Heart Rate Service为例,SIG官方通过的16bit的UUID为**0x180D**,其包含3个Characteristic:Heart Rate Measurement,Body Sensor Location和Heart Rate Control Point。

  • Characteristic是最小的逻辑数据单元,由一个Properties、一个Value、一个或者多个Descriptor组成。Properties定义了characteristic的Value如何被使用,以及characteristic的Descriptor如何被访问;Value是特征的实际值,例如一个温度特征,其Characteristic Value就是温度值;Descriptor则保存了一些和Characteristic Value相关的信息,如用户描述,CCC,展示格式,单位格式。

    与Service类似,每个Characteristic用16bit或者128bit的UUID唯一标识。你可以免费使用Bluetooth SIG官方定义的标准Characteristic,使用官方定义的,可以确保BLE的软件和硬件能相互理解。当然,你可以自定义Characteristic,这样的话,就只有你自己的软件和外设能够相互理解。以Heart Rate Measurement为例,其UUID为0x2A37

注意:以上所有的Service、Characteristic、Characteristic Properties、Characteristic Value、Characteristic Descriptor等等,都是作为一个Attribute存在的。具备Attribute所有特征:Attribute Handle、Attribute Types、Attribute Value和AttributePermissions。

一个profile定义示例如下:

属性句柄属性类型
0x0001服务1
0x0002特性声明1
0x0003特性数值1
0x0004描述符1
0x0005特性声明2
0x0006特性数值2
0x0007描述符2
0x0008描述符3
0x0009服务2

服务发现

参考:BLE发现过程通用属性规范

服务Service的声明格式如下,服务Service可以是主要服务项(UUID=0x2800)或次要服务项(UUID=0x2801)。在绝大多数情况下均可以不使用次要服务项,仅使用主要服务。

在这里插入图片描述

服务发现有两种方案:发现全部服务;发现指定UUID服务。

  • 发现全部主要服务

    客户端设备发送Read By Group Type Request,起始句柄为0x0001,结束句柄为0xFFFF,属性类型为0x2800(Primary Service Declaration),查找全部符合条件的首要服务项。

    服务端设备回应Read By Group Type Response,返回多个主要属性信息组成的列表,每个属性信息包括三个参数:元素长度,首尾句柄、属性的UUID。例如返回响应Generic Attribute服务:(0x06, 0x0001, 0x0005, 0x1801)分别代表元素长度6字节,起始句柄0x0001,结束句柄0x0005,UUID为0x1801(Generic Attribute)。即按服务声明格式如下所示:

    Attribute HandleAttribute TypeAttribute ValueAttribute Permission
    0x0001-0x00050x28000x1801只读

    由于列表长度不能超过属性层的PDU长度,因此可能需要发送多个请求,直至服务端设备返回“未找到属性项”或到达结束句柄,从而获取全部的主要服务项。

    发现全部主要服务示例如下:

    在这里插入图片描述

  • 发现指定的主要服务

    客户端设备发送Read By Type Value Request,起始句柄为0x0001,结束句柄为0xFFFF,属性类型为0x2800(Primary Service),指定的UUID如0x1801(Generic Attribute),查找符合指定条件的首要服务项。

    服务端设备返回响应Find By Type Value Response,其包含了该指定UUID服务的首尾句柄,如起始句柄0x0001,结束句柄0x0005。

    发现指定UUID的服务,可以快速找到目标服务,对于不关心的服务项可以快速略过,加快整体发现过程的速度。

    发现指定的主要服务示例如下:

    在这里插入图片描述

发现特征

发现特征是发现某个指定服务下的特征,因此一定要先发现服务,再发现特征。通过服务发现,已知服务的首尾句柄,如0x1801服务的起始句柄0x0001,结束句柄0x0005。在服务的句柄范围内搜索特征声明的UUID 0x2803(Characteristic),一旦找到就返回响应,响应中包含了特征的关键信息,包括特征的句柄范围,特征属性,特征值句柄,特征UUID,权限。特征声明格式如下。

在这里插入图片描述

同发现服务类似,发现特征也有两个方案:发现全部特征,发现指定UUID的特征。

  • 发现全部特征

    客户端设备发送Read By Type Request,设置已知的服务首尾句柄,如起始句柄0x0001,结束句柄0x0005,属性类型为特征项声明的UUID即0x2803(Characteristic),查找全部符合条件的特征项。

    服务端返回Read By Type Response,响应中包含多个“属性句柄 – 值”元素组成的列表。单个元素包含三个参数:元素长度、特征项声明的句柄和特征值参数。特征值参数包括特征值的功能特性、特征值句柄和UUID。如返回响应Service Changed特征:(0x07, 0x0002, 0x10, 0x0003, 0x2A05)分别代表元素长度7字节,特征句柄为0x0002,特征功能特性为0x10,即Notify功能,特征值句柄为0x0003,特征值UUID为0x2A05,即Service Changed。即按照特征声明格式如下所示:

    Attribute HandleAttribute TypesCharacteristic PropertiesCharacteristic Value Attribute HandleCharacteristic UUIDAttribute Permissions
    0x00020x28030x100x00030x2A05只读

    发现全部特征示例如下:

    在这里插入图片描述

  • 发现指定UUID特征

    根据已知的特征项UUID和首末句柄范围,查找满足条件的特征项。如根据特征UUID 0x2A05(Service Changed)和起始句柄0x0001,结束句柄0x0005,属性类型为特征项声明的UUID即0x2803(Characteristic),查找符合指定条件的特征项。

    发现指定UUID特征的示例如下:

    在这里插入图片描述

不难发现,特征声明Characteristic declaration的Attribute Value字段包括Characteristic Properties,Characteristic Value Attribute Handle,Characteristic UUID三项。按照特征声明的Attribute Value字段格式如下:

在这里插入图片描述

  • 特征特性

    定义特征值如何使用,或者特征描述符如何获取。其定义位如下:

    在这里插入图片描述

  • 特征值句柄

    特征值的属性句柄

  • 特征值UUID

    获取到了特征值属性句柄Characteristic Value Attribute Handle,服务端和客户端就可以进行读、写、Notify等数据操作。特征值声明格式如下:

在这里插入图片描述

发现描述符

紧跟特征之后,可能会存在特征描述符Characteristic Descriptor Declaration。描述符也是一种属性,它是特征项的一部分,用以提供特征值的额外信息。协议栈定义了6种不同的描述符,协议定义了六种描述符,如下:

属性类型UUID描述
«Characteristic Extended Properties»0x2900特征项的扩展描述符
«Characteristic User Description»0x2901特征项的用户描述符
«Client Characteristic Configuration»0x2902客户端特征项配置描述符
«Server Characteristic Configuration»0x2903服务端特征项配置描述符
«Characteristic Presentation Format»0x2904特征项数据格式描述符
«Characteristic Aggregate Format»0x2905聚合特征项数据格式描述符
  1. 0x2900 扩展性描述符,用于Reliable Write和Writable Auxiliaries这两类写属性。

  2. 0x2901 用户描述符,用于给出该特征值的文字描述。

  3. 0x2902 客户端特征项配置描述符,简称为CCCD,客户端设备通过一个标志参数,设置该特征值能否发送通知和指示。如果该标志参数为0x0001,表示该特征值允许发送通知;如果该标志参数为0x0002,表示该特征值允许发送指示。如果该标志参数为0x0000,表示该特征值不能发送通知和指示。

  4. 每个特征项最多能包含一个CCCD,对于具有Broadcast、Notify和Indicate功能的特征项,必须拥有一个CCCD。在两个建立了绑定的设备中,断开连接不会丢失CCCD信息。

  5. 0x2903 服务端特征项配置描述符,服务端设备通过一个标志参数,设置该特征值是否在广播中发出。如果该标志参数为0x0001,则广播消息中应该包含该特征值;如果该标志参数为0x0000,则广播消息中不包含该特征值。

  6. 0x2904 特征值格式描述符,用于提供特征值的数据格式。可选的数据类型包括:Boolean、1/4字节、1/2字节、1字节、2字节、3字节、4字节、8字节、16字节、带符号整数、无符号整数、浮点数、字符串、结构体等。还可以指定数据的指数、单位、名字空间、描述信息等。特征格式声明如下:

    在这里插入图片描述

    特征格式描述符的属性值如下定义:

    在这里插入图片描述

    以温度特征为例(摘自Core_V4.2的Vol3 Part G附录A),温度特征值为0x028A=650,特征格式描述符为{0x0E, 0xFE, degree Celsius, 0x01, Outside}分别代表:Format为sint16,Exponent为-2,Unit为摄氏度,组织,描述。即该特征表示室外温度为6.5℃。

    在这里插入图片描述

  7. 0x2905 聚合特征项格式描述符,专用于聚合特征项。所谓聚合特征值,是指多个特征值共同组合成一个数值,每个特征值仅是该聚合数值的一部分。

客户端发现服务端描述符流程如下:

  • 客户端向服务端发送Find Information Request,设置已知的特征首尾句柄,查找全部符合条件的描述符。
  • 服务端返回Find Information Response,响应中包含多个“属性句柄 – 值”元素组成的列表。单个元素包含三个参数:UUID格式、特征值的句柄和描述符的UUID。如果UUID格式参数等于1,表示描述符的UUID为2字节UUID,如果等于2,表示描述符的UUID为16字节UUID。

发现全部描述符的示例如下:

在这里插入图片描述

以具有Notify属性的Service Changed(0x2A05)特征为例,其一定会携带一个CCCD(Client Characteristic Configuration Declaration)描述符。Client Characteristic Configuration的描述符UUID为0x2902,主机发出描述符发现请求,从机返回响应,其响应包中给出属性句柄和UUID信息。CCCD声明格式如下:

在这里插入图片描述

CCC属性值的格式如下:

在这里插入图片描述

至此,服务的所有信息发现完毕。可以看出服务发现就是发现各个ATT协议属性(Service、Characteristic、Characteristic Descriptor等)的句柄Handle,有了句柄可以通过其获取到具体的值(类似通过指针获取数据一样)。

6. 主从数据交互

通过以上服务发现过程,客户端可以获取到服务端所有特征值句柄,那么就可以向服务端发送读取、写入命令。另外服务端也能向客户端发送通知和指示命令。

特征值读取

特征值读取包括四个子功能:读取特征值,按UUID读取特征值,读取长包特征值,读取多个特征值。

  • 读取特征值

    如果客户端已知特征值句柄,向服务端发送Read Request,请求该句柄的特征值。读取特征值的示例如下:

    在这里插入图片描述

  • 按UUID读取特征值

    如果客户端只知道特征UUID,不知其句柄,向服务端发送Read By Type Request,需携带首尾句柄和特征UUID,读取特征值。按UUID读取特征值示例如下:

    在这里插入图片描述

  • 读取长包特征值

    客户端已知特征值的句柄,但是特征值的长度大于(ATT_MTU-1),向服务端发送Read Request以读取前(ATT_MTU-1)个字节,然后发送Read Blob Request并设置合适的偏移量,以读取随后的(ATT_MTU-1)个字节,重复执行Read Blob Request直到服务端的Read Blob Response内容小于(ATT_MTU-1),表明该特征值完全被读取。读取长包特征值示例如下:

    在这里插入图片描述

  • 读取多个特征值

    客户端已知多个特征值的句柄,向服务端发送Read Multiple Request,参数为多个特征值句柄。服务端返回Read Multiple Response,包含了多个指定的特征值数据。读取多个特征值示例如下:

    在这里插入图片描述

特征值写入

特征值写入包括五个子功能:无需回应的写命令,无需回应的带签名的写命令,写请求,写长包请求,可靠的写请求。

  • 无需回应的写命令

    客户端已知特征值句柄,向服务端发送Write Command,参数为特征值句柄和待写入的特征值。该命令不需要服务端进行回应,数据长度不能超过(ATT_MTU-3)个字节。其示例如下:

    在这里插入图片描述

  • 无需回应的带签名的写命令

    客户端已知特征值句柄,且ATT Bearer没有进行加密。向服务端发送Signed Write Command,并设置签名认证标志位,实现带签名的写命令。数据长度不能超过(ATT_MTU-3-12)字节,其中12表示认证签名的长度,如果超过,仅写入前(ATT_MTU-3-12)个字节。该命令也无需服务端返回响应。其示例如下:

    在这里插入图片描述

  • 写请求

    客户端已知特征值句柄,向服务端发送Write Request,写入指定数据。数据长度不能超过(ATT_MTU-3)字节,如果超过,仅写入前(ATT_MTU-3)个字节。该命令需要服务端返回响应Write Response。其示例如下:

    在这里插入图片描述

  • 写长包请求

    客户端已知特征值句柄,但待写入数据长度过长,向服务端发送Prepare Write Request,设置适当的偏移量,将数据发送至服务端缓存起来,数据发送完毕后,服务端发送Execute Write Request执行写请求。待写数据总长度不受限制,但是分步发送数据每次数据长度不得超过(ATT_MTU-3)。两种请求均需要对应的服务端响应。其示例如下:

    在这里插入图片描述

  • 可靠的写请求

    客户端已知特征值句柄,希望数据的每个字节都必须被安全写入服务端设备,向服务端发送Prepare Write Request,偏移量永远等于0,一次性只发送一个数据,待多字节数据缓存完毕,再发送Execute Write Request执行写请求。其示例如下:

    在这里插入图片描述

特征值通知

服务端执行Handle Value Notification,参数为特征值句柄和通知数据,向客户端推送通知。执行通知前,该特征值需要已经使能通知,并且将通知数据写入该特征值。该命令无需客户端返回响应。其示例如下:

在这里插入图片描述

特征值指示

与特征值通知类似,但是需要响应。服务端执行Handle Value Indication,参数为特征值句柄和指示数据,向客户端推送指示。执行指示前,该特征值需要已经使能指示,并且将指示数据写入该特征值。该命令需要客户端返回响应Handle Value Confirmation。其示例如下:

在这里插入图片描述

读写描述符

读写特征描述符分为四个子功能:读描述符,读长包描述符,写描述符,写长包描述符。

  • 读描述符

    读描述符同读特征值一致,其示例如下:

    在这里插入图片描述

  • 读长包描述符

    读长包描述符与读长包特征值一致,其示例如下:

    在这里插入图片描述

  • 写描述符

    写描述符与写特征值一致,其示例如下:

    在这里插入图片描述

  • 写长包描述符

    写长包描述符与写长包特征值一致,其示例如下:

    在这里插入图片描述

BLE安全机制

安全管理

设备间要安全通信,最重要的就是双方要共享一把密钥,在BLE就是LTK(Long Term Key)。Security Manager安全管理定义了一系列复杂的机制来完成LTK的实现:配对和密钥分发方法,这些方法的一套协议SMP,以及密码工具箱等。SM是利用密钥分发方式去完成通信的身份认证和加密功能。该安全架构设计的优点是:响应设备(responding device)对内存和处理能力的要求比初始化设备(initiating device)低。

这里要先讲下配对和绑定的关系。配对包括配对能力交换,设备认证,密钥生成,连接加密以及机密信息分发等过程。绑定是配对过程中会生成一个长期密钥(LTK,long-term Key),如果配对双方把这个LTK存储起来,那么这两个设备再次重连的时候,就可以跳过配对流程,而直接使用LTK对蓝牙连接进行加密。这就类似于TLS通信协议,配对类似握手过程,绑定类似会话恢复功能。

广义上的配对(Paring)包括绑定(Bonding)过程,只paring不bonding的应用情况非常少见。因此我们就拿配对paring当成paring和bonding两者的组合。

配对包括三个阶段,第一二阶段必须,第三阶段可选,如下所示:

在这里插入图片描述

阶段1:配对特性交换,交换各自支持的哪些配对特性,如是否支持LESC,是否支持MITM,是否支持OOB,以及输入输出能力等

阶段2:有两种情况:

  • LE legacy pairing:STK(Short Term Key)短期密钥生成
  • LE Secure Connections:LTK(Long Term Key)长期密钥生成

阶段3:传输特定密钥分发,Legacy paring需要分发LTK,IRK等,而SC paring只需分发IRK。

参考:低功耗蓝牙配对绑定解读和实践

阶段1:配对特性交换

配对总是由主机发起,从机进行响应,但是从机可以先发送Security_Request安全请求,因为如果主从以前配对绑定过,可以直接走加密流程,省去配对过程。

  • Security_Request

    从机设备可以向主机发送安全请求命令,主机收到该命令后,要么加密链路,要么开始进行配对流程,要么拒绝该请求。比如主从设备如果第一次连接,主机收到Security Request后进入配对流程,配对成功后用长期密钥进行加密;如果之前主从设备配对过,有LTK,那么主机直接可用长期密钥进行加密。

    在这里插入图片描述

    Security Request命令包的格式如下:

    在这里插入图片描述

  • Pairing_Request

    主机向从机发送配对请求Pairing_Request命令,用于配对特性交换,配对请求Pairing_Request包的格式如下:

    在这里插入图片描述

  • Pairing_Response

    如果允许配对,从机须向主机回复Pairing_Response命令,完成配对特性交换,配对响应Pairing_Response包的格式如下:

在这里插入图片描述

可以看出,配对特性交换主要是交换:IO能力,OOB认证标志,认证请求,密钥最大长度,初始化者的密钥分发,响应者密钥分发。

  • IO Capability

    IO能力是指设备的输入输出能力是怎样的,比如是否有键盘,显示屏等等,其综合能力表如下所示:

    在这里插入图片描述

    相应的IO能力值(一个字节)的定义如下:

    在这里插入图片描述

    其中,DisplayOnly:设备只有显示的输出能力(比如显示屏);DisplayYesNo:设备既有显示的输出能力,还具备键入Yes或No的输入能力(比如两个按键);KeyboardOnly:设备只有键盘的输入能力;NoInputNoPut:设备没有任何输入输出能力;KeyboardDisplay:设备既有键盘的的输入能力,也有显示的输出能力。

  • OOB data flag

    带外数据标志表示设备是否可以用带外认证数据去认证对端设备。值定义(一个字节)如下:

    在这里插入图片描述

  • AuthReq

    认证请求是指明用于STK、LTK以及GAP绑定信息的安全特性Security Properties,SM定义的安全特性Security Properties分为四类:

    • LE Secure Connection pairing:LE安全连接配对
    • Authenticated MITM protection:可靠的中间人保护
    • UnAuthenticated no MITM protection:不可靠的中间人保护
    • No security requirements:无安全需求

    这里的中间人是指第三方蓝牙设备,中间人保护是指设备双方交换参数时,第三方设备无法知道。认证请求标志(1字节)按位定义,包括绑定标志,启用中间人保护,使能SC配对,启用输入密码。如下:

    在这里插入图片描述

  • 密钥最大长度

    该值(1字节)定义设备支持的密钥最大长度,密钥长度为7-16字节。

  • 发起者密钥分发

    该值(1字节)定义了发起者密钥分发的类型。以LE Secure Connections为例,从机向主机可分发的密钥类型有:

    • 使用身份信息命令分发的IRK
    • 使用唯一地址信息命令的公有设备或者随机设备地址
    • 使用签名信息命令的CSRK

    主机向从机可分发的密钥类型与上一致:

    • 使用身份信息命令分发的IRK
    • 使用唯一地址信息命令的公有设备或者随机设备地址
    • 使用签名信息命令的CSRK

    该值定义的密钥分发类型的格式如下:

    在这里插入图片描述

    其中:

    • EncKey只针对LE legacy pairing模式,表示设备是否应当分发LTK;对于SC模式,该值被忽略
    • IdKey表示设备是否应当分发IRK
    • Sign表示设备是否应当分发CSRK
    • LinkKey表示设备是否从LTK中派生出Link Key
  • 响应者密钥分发

    该值(1字节)定义了响应者密钥分发的类型。

对于发起者密钥分发和响应者密钥分发,总结如下:

  • 如果是作为从机,Initiator Key Distribution意味着你期望主机分发哪种类型的密钥给你;Responder Key Distribution意味着你能分发哪种类型的密钥给主机。
  • 如果是作为主机,Initiator Key Distribution意味着你能分发哪种类型的密钥给从机;Responder Key Distribution意味着你期望从机分发哪种类型的密钥给你。

阶段2:密钥生成

第一阶段交换的信息将用于选择第二阶段的密钥生成方法。密钥生成阶段有如下认证方式:

  • Just Works

    仅工作方式。比如当主从设备双方IO能力均是NoInputNoOutput,即采用此方式

  • Numeric Comparison(只LE Secure Connections Pairing独有)

    数字比较,显示6位的数字在显示器上,用户判断确定是否一致。比如主从设备双方IO能力均是DisplayYesNo,即采用此方式,主从设备显示6位数字,用户输入Yes或No确认这两个数字是否相等。

  • Passkey Entry

    密码输入,用户在键盘中输入的一串数字,以达到相互认证的目的。比如从机设备IO能力为DisplayOnly,主机设备是KeyboardOnly,即采用此方式,从机显示一串数字,主机用键盘输入该数字。

  • Out of Band

根据不同的IO能力,密钥生成方法如下表:

在这里插入图片描述

在这里插入图片描述

接下来以设备双方都支持LE Secure Connections Pairing为例进行介绍。

  1. LESC配对使用的ECDH密钥协商算法,采用P-256椭圆曲线。ECDH算法首先各自生成公私钥对,接着双方交换各自的公钥,最后根据ECDH算法计算出一把对称密钥DHKey,该密钥主从设备计算出来是一样的(为什么不能立马用该DHKey密钥呢?因为ECDH交换公钥的过程中,MITM中间人可以进行攻击,替换成自己的公钥,因此需要保证DHKey是真实的双方协商出来的,而不是与中间人协商出来的密钥,这就是接下来的认证阶段)。密钥协商阶段流程如下:

    在这里插入图片描述

    配对公钥交换命令的格式为:

    在这里插入图片描述

  2. 接着按照第一阶段交换的信息,可以有以下方式完成认证:

    Numeric Comparison方式

    如果设备双方具备DisplayYesNo or KeyboardDisplay(即显示Yes和No或者键盘显示)能力,并且第一阶段MITM位为1的话,配对将会采取数字比较方式。认证流程如下:

    在这里插入图片描述

    主机和从机分别生成随机数Na和Nb,然后从机使用f4函数计算Cb认证值,计算如下
    C b = f 4 ( P K b , P K a , N b , 0 ) Cb=f4(PKb, PKa, Nb, 0) Cb=f4(PKb,PKa,Nb,0)

    其中f4函数如下:
    f 4 ( U , V , X , Z ) = A E S − C M A C X ( U ∣ ∣ V ∣ ∣ Z ) f4(U, V, X, Z) = AES-CMAC_X (U || V || Z) f4(U,V,X,Z)=AESCMACX(UVZ)
    可以看出其实就是计算密码学中的消息认证码,方法为AES_CMAC,密钥为生成的随机数Nb,消息为主从机双方的公钥和零值。

    接着从机将Cb发送给主机,主机收到Cb后则发送随机数Na,从机收到Na后发送随机数Nb给主机。主机收到Nb,用f4函数做同样的消息认证码计算,如果收到的Cb值与计算值一样,则继续往下走,否则终止配对,这一步可以保证Nb没有被篡改。

    接下来,主机和从机分别用g2函数计算出Va和Vb,计算如下
    V a = g 2 ( P K a , P K b , N a , N b ) Va=g2(PKa, PKb, Na, Nb) Va=g2(PKa,PKb,Na,Nb)

V b = g 2 ( P K a , P K b , N a , N b ) Vb=g2(PKa, PKb, Na, Nb) Vb=g2(PKa,PKb,Na,Nb)

其中g2函数如下:

g 2 ( U , V , X , Y ) = A E S − C M A C X ( U ∣ ∣ V ∣ ∣ Y ) m o d 2 32 g2(U, V, X, Y) = AES-CMAC_X (U || V || Y) mod 2^{32} g2(U,V,X,Y)=AESCMACX(UVY)mod232
其实也是计算消息认证码的方式,只不过最后要进行模2^32运算。然后将计算出Va和Vb结果转换成10进制,取最低的6位。比如如果Va或者Vb为0x 01 2e b7 2a,则对应的十进制为19838762,展示的6位值为838726

最后主机和从机分别展示计算出的Va和Vb值,交由用户去判断这个值是否一致,如果相同则认证成功,否则失败。

在这里,我有几个疑问:

a. 为什么需要生成随机数呢?

​ 我看文档规范里说的随机数是用来防止重放攻击,不明白重放攻击什么时候会发生?

b. 不用随机数,使用哈希运算直接计算Va和Vb不更高效吗?

​ 这个过程其实就是为了完成认证,即对主机A而言,自己在密钥协商阶段接收的对端公钥就是从机B的,而不是中间人C的;反之也一样,对从机B而言,自己在密钥协商阶段接收的对端公钥就是主机A的,而不是中间人C的。哈希运算只能保证完整性,无法认证。而消息验证码既可以保证完整性,也能进行认证,其是通过设备双方共享的对称密钥来实现的。那么这个密钥来自何处呢?有人可能会说用密钥协商出来的DHKey,这不回环了嘛,本来目的就是为了保证DHKey是真实设备双方协商出来的。因此这个认证阶段最重要的就是如何安全地共享一把用于消息认证码计算的密钥呢?这就可以回答问题c了。

c. 如何保证密钥协商阶段的公钥就是真实的对方呢?

​ 我们假设主机A和从机B在密钥协商阶段遭受了中间人M攻击,其可以获取AB之间的通信包并进行拦截篡改,即与A通信时冒充B,与B通信时冒充A。这样主从机AB交换公钥时,其实际上收到的是中间人M的公钥,因此最后AB协商出来的DHKey其实是它们分别与中间人M的对称密钥,而且两把密钥不一致。这些只有中间人M明白,主从机AB完全不知道,还以为是在与真实的对方通信。接下来有点难懂,还是尽量讲清楚。

​ 设备B在3c步骤计算Cb时,其实使用的PKa公钥其实是中间人M的。为了保证6a步骤的验证顺利通过,中间人必须同时篡改Cb和Nb数据。因为:如果Cb和Nb都不篡改,那么设备A在6a计算Cb时,其输入的公钥PKb其实是以前中间人M的,而设备B计算时输入的PKb是自己的,这样Cb计算值和收到的值不等,导致验证不过;如果只更改Cb,中间人不知道改成多少,因为Nb是在Cb之后发送的,其不能提前预知Nb的值,这样只改Cb,而不改Nb,6a验证步骤无法通过;同样只改Nb,而不改Cb,也会导致验证失败。

​ 因此为了保证6a步骤验证顺利通过,中间人需要自己生成一个Nb值,并且在计算Cb时,将PKb公钥替换成自己的公钥,PKa公钥还是真实的Pka公钥,这样6a步骤就能顺利通过。但是到第7阶段,7a步骤计算的值Va=g2(PKa, PKm, Na, Nbm),7b步骤计算的值Vb=g2(PKm, PKb, Na, Nb),很明显Na密钥相同,但是其他消息输入参数不一致,Va不等于Vb,用户会校验失败。可能有人会说把Na也改了,中间人在更改Na之前提前计算出设备A计算的Va值,然后反推需要把Na改成多少才会让设备B计算的Vb值与Va一样。即此时是这样的情况:Va=g2(PKa, PKm, Na, Nbm),Vb=g2(PKm, PKb, Nam, Nb)。这样概率上有可能的,但是观察g2函数的表达式,可以发现有一个mod2^32动作,根据Va的值反推以前的消息值在数学上是很困难的(即使能够反推也需要类似超级计算机计算很长的时间),因此如果Na的值无法改成意想的值,用户也无法校验成功。

这个阶段涉及的认证值交换和随机数交换命令格式分别如下:

在这里插入图片描述

在这里插入图片描述

​ 总结一下,可以看出公钥真实的保证性其实交给了用户,因为用户可以看到Va和Vb值是否相等。

Just Works方式

​ 如果可以保证主从配对过程中不会存在中间人攻击,可以使用Just Works方式,Just Works方式不会有7a和7b步骤,也即不会展示6位数字给用户。另外设备不支持一定的输入输出IO能力,也只能用Just Works方式。

Passkey Entry方式

​ 用户在设备双方上输入身份确认密码Passkey。如果一方设备可以显示Passkey,那么用户则在另一方设备上输入该密码。这个简短的密码就成了设备双向认证的基础。其认证流程如下:

在这里插入图片描述

其中,对于k为的Passkey,步骤3到步骤8会循环执行k次。比如输入的六位Passkey为99999(xF423F),按二进制计算占据20位,则会循环执行20次。这种“gradual disclosure(逐步透露)”的机制可以防止泄露超过1位以上的Passkey信息,从而应对MITM攻击。

Passkey Entry认证消息交换的命令格式如下:

在这里插入图片描述

Out of Band方式

​ 如果配对请求或者配对响应中一方的OOB数据标志为1的话,可以使用带外信息帮助设备身份确认。但是这种先带内(通过BLE)发现设备,接着通过OOB接口传输认证参数的模式是不支持的。OOB认证模式的流程如下:

在这里插入图片描述

可以看出,在4a和4b步骤中,通过带外的通道交换消息认证码Ca和Cb,即完成对公钥的认证工作,进行设备的身份确认。

  1. 接下来这个阶段用于证实设备已经成功完成信息交换,并进行LTK计算。

    在这里插入图片描述

    根据以前阶段交换的值,每个设备均会计算出MacKey和LTK(9a和9b),然后再计算消息认证码进行认证(10a和10b)。至此我们就可以利用LTK完成对后续数据的加密通信。

阶段3:特定的密钥分发

BLE主从设备可以进行密钥的分发(Transport Specific Key Distribution)。还是以LESC为例,主从设备相互之间可以分发以下密钥:IRK,公共或静态随机地址,CSRK。具体下发哪些密钥,是以阶段1中配对请求和配对响应中的密钥分发字段值决定的。当使用LESC进行配对时,密钥以下面的顺序进行分发:

  • IRK by the slave
  • BD ADDR by the slave
  • CSRK by the slave
  • IRK by the master
  • BD_ADDR by the master
  • CSRK by the master

具体来看,每种密钥详细如下:

  • Identity Information

    有些蓝牙设备的地址为可解析的随机地址,比如IPhone的地址是随时间变化的,IRK可以用来解析变化的地址规律,从而确定这些地址来自同一设备,IRK一般由设备厂商出厂时按照一定的要求自动生成。身份信息命令是用于分发IRK,其只能用密钥(LTK)进行加密发送,IRK长度为16字节,其命令格式如下:

    在这里插入图片描述

  • Identity Address Information

    首先的说明一下BLE地址,有四种:Public Device Address,Static Device Address,Non-resolvable private address,Resolvable private address。

    • Public Device Address是由IEEE组织颁发的,需要购买,高24位是公司ID,低24位由公司自己颁布,其格式如下:

    在这里插入图片描述

    • Static Device Address是在每次上电后才随机生成,高2位为11,低46位随机生成,其格式如下:

      在这里插入图片描述

    • Non-resolvable private address是不可解析的,也就是以TGAP(private_addr_int)间隔进行更新,高2位为00,低46位随机生成,其格式如下:

      在这里插入图片描述

    • Resolvable private address是可解析的随机地址,同样也是以TGAP(private_addr_int)间隔进行更新,高2位为10,接着22位随机生成,低24位是一个哈希值,由hash = ah(IRK, prand)计算得到,而对端设备收到该地址,提取prand,使用IRK作同样的哈希计算,然后比较计算值与收到的地址低24位值是否一致,相等则说明解析成功。其格式如下:

      在这里插入图片描述

    针对前两种地址,它们就是设备唯一地址(Identity Address)。对于Resolvable private address,地址会定期更新,但是Identity Address仍然保持不变,其取值还是等于内在的Public Device Address或者Static Device Address设备地址。

    身份地址信息命令Identity Address Information也只能加密发送,AddrType地址类型可以是Public Device Address或者Static Device Address,命令格式如下:

    在这里插入图片描述

    这里我还是没搞懂这个可解析地址的使用场景以及为什么要发送身份地址信息Identity Address Information?

  • Signing Information

    签名信息命令用来下发用来签名数据的CSRK,其格式如下:

    在这里插入图片描述

    这个签名密钥Signature Key是用于计算数据PDU中的信息完整性检查MIC(Message Integrity Check)。即如下:

    在这里插入图片描述

消息序列图

参考Vol2, Part H的附录C,描述一下最为常见的配对场景流程。配对流程总览如下:

在这里插入图片描述

阶段1:配对特征交换

主机使用配对请求命令发起配对的流程如下:

在这里插入图片描述

此外,从机也能主动发起安全请求,流程如下:

在这里插入图片描述

阶段2:认证和加密

完成配对特征交换后,会选择一个配对模式,还是以LE Secure Connections为例。

  1. 公钥交换

    在这里插入图片描述

  2. 认证阶段1

    只列举Numeric Comparison or Just Works成功的例子,流程如下:

    在这里插入图片描述

  3. 长期密钥计算

    在这里插入图片描述

  4. 对称密钥DHKey校验

    一旦LTK计算完成,DHKey值就校验成功。流程如下:
    在这里插入图片描述

阶段3:传输特定密钥分发

长期密钥生成后,链路层已是加密的,接下来就是特定用途的密钥分发,流程如下:

在这里插入图片描述

使用以前的LTK完成安全重建

设备可以利用以前LTK进行安全重连,主机总是会发起加密流程,因此这会有两种情况:主机发起,从机请求。

  • 主机发起安全加密

    由于主机总是要发起加密流程,这里没有SM信号来使能。

  • 从机安全请求

    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值