2. BLE协议基础回顾:BLE协议栈架构、GATT与GAP角色、配对与绑定机制、ATT层安全属性

好,咱们正式开始聊 BLE 配网安全之前,得先把地基打牢。BLE 协议栈这东西,说白了就是一套分层的通信规则。我刚开始啃 BLE 的时候,也被那几层结构绕得头晕。后来做项目踩了坑才明白——不理解协议栈,你根本不知道安全漏洞会从哪一层钻进来。

这一节我会带着大家把 BLE 协议栈的核心骨架捋一遍。重点放在跟安全强相关的部分:GATT/GAP 角色、配对绑定、还有 ATT 层的安全属性。嗯,咱们不搞教科书式的罗列,我会穿插一些实际项目里的教训。

2.1 BLE协议栈架构:Controller、Host、Application

BLE 协议栈分三层:Controller(控制器)、Host(主机)、Application(应用)。

Controller 管物理层和链路层,说白了就是负责发信号、收信号、跳频这些底层活。Host 管逻辑链路控制和适配协议(L2CAP)、安全管理(SM)、属性协议(ATT)、通用属性协议(GATT)这些。Application 就是咱们写业务逻辑的地方。

我见过不少工程师把安全逻辑全堆在 Application 层,觉得底层不用管。结果呢?中间人攻击一来,数据在 Host 层就被截了。所以我的习惯是:安全必须贯穿三层。

关键点:Controller 和 Host 之间通过 HCI(Host Controller Interface)通信。HCI 本身也可能成为攻击面——如果你用 UART 做 HCI,线缆暴露在外,攻击者可以直接监听。

下面这张图是我自己画的 BLE 协议栈分层结构,方便大家对照着看:

BLE 协议栈分层架构 Application(应用层) 用户业务逻辑、配网流程、安全策略 Host(主机层) GATT / ATT SM(安全管理) L2CAP GAP HCI(主机控制器接口) Controller(控制器层) 物理层(PHY) + 链路层(LL) ⚠ 注意 HCI 接口暴露 可能被物理监听

2.2 GATT 与 GAP 角色

GAP(Generic Access Profile)管的是设备怎么被发现、怎么建立连接。GATT(Generic Attribute Profile)管的是连接之后怎么读写数据。

你想想看,配网场景里:手机要发现设备,这是 GAP 的事;手机要写入 WiFi SSID 和密码,这是 GATT 的事。两个角色缺一不可。

GAP 角色

  • Broadcaster:只发广播,不连。比如 Beacon。
  • Observer:只收广播,不连。
  • Peripheral:从设备,发广播,等待连接。配网设备通常是这个角色。
  • Central:主设备,扫描并发起连接。手机通常是这个角色。

我的经验:配网时,设备作为 Peripheral,广播包里不要放敏感信息。我曾经见过有人把 WiFi 密码直接塞广播数据里——嗯,那等于把钥匙挂在大门上。

GATT 角色

  • Server:提供数据(Service、Characteristic)。配网设备通常是 Server。
  • Client:读写 Server 的数据。手机通常是 Client。

GATT 的数据模型是:Service → Characteristic → Descriptor。每个 Characteristic 有 UUID、属性(读/写/通知/指示)、还有安全权限。

GATT 元素 说明 配网中的用途
Service 一组功能的集合 WiFi 配网服务(自定义 UUID)
Characteristic 具体的数据点 SSID 特征、密码特征、状态特征
Descriptor 特征的配置信息 客户端特征配置(CCCD)

2.3 配对与绑定机制

配对(Pairing)是建立安全连接的过程。绑定(Bonding)是把配对信息存下来,下次重连不用再配一次。

BLE 配对分三个阶段:

  1. 配对特征交换:双方交换 IO 能力、认证要求、密钥大小。
  2. 短期密钥(STK)生成:用 Just Works、Passkey Entry、或 OOB 方式生成 STK。
  3. 传输特定密钥:用 STK 加密通道,分发长期密钥(LTK)、身份解析密钥(IRK)、连接签名解析密钥(CSRK)。

避坑指南:Just Works 配对方式不提供中间人攻击(MITM)保护。我曾经在一个智能锁项目里看到产品用了 Just Works,结果测试时用一块 nRF52840 DK 就能模拟手机完成配对——这太危险了。配网场景,我建议至少用 Passkey Entry 或 OOB。

配对方式对比:

配对方式 MITM 保护 适用场景 我的建议
Just Works 无 低安全需求 ❌ 不推荐配网
Passkey Entry 有 有显示屏/键盘的设备 ✅ 推荐
OOB(Out of Band) 有 有 NFC/二维码等带外通道 ✅ 强烈推荐
Numeric Comparison 有 双方都有显示屏 ✅ 可用

2.4 ATT 层安全属性

ATT(Attribute Protocol)是 GATT 的底层传输协议。每个 ATT 属性都有安全属性,包括:

  • 读权限:是否需要加密、是否需要认证、是否需要授权。
  • 写权限:同上。
  • 加密要求:数据在传输时是否必须加密。
  • 认证要求:是否必须经过配对认证。

说白了,ATT 安全属性就是给每个数据点贴标签:谁能读、谁能写、要不要加密、要不要认证。

核心原则:配网过程中,WiFi 密码所在的 Characteristic 必须设置 加密写 权限。如果设成 无安全写,攻击者在连接建立后可以直接写入恶意数据——我见过不止一个产品犯这个错。

ATT 安全属性在代码中的配置示例(以 Zephyr 为例):

// 定义 WiFi 密码特征,要求加密写
BT_GATT_CHARACTERISTIC(&wifi_password_uuid,
                       BT_GATT_CHRC_WRITE,
                       BT_GATT_PERM_WRITE_ENCRYPT,
                       NULL,
                       on_password_write,
                       NULL);

注意看 BT_GATT_PERM_WRITE_ENCRYPT 这个标志。它告诉协议栈:写这个特征之前,必须先建立加密连接。如果没有配对,写入请求会被直接拒绝。

嗯,这里还要提一句:ATT 安全属性是在 Host 层强制执行的。也就是说,即使 Application 层代码写错了,Host 层也会帮你拦住未加密的访问。这就是分层设计的好处——安全底线由底层兜着。

小技巧:调试时可以用 bt_gatt_get_perm() 检查当前特征的权限设置。我习惯在初始化后打印所有特征的权限,确保没有遗漏。